【发布时间】:2016-06-29 16:17:24
【问题描述】:
我在数值模拟的进程之间传递大向量。一切正常,直到某个时间步长。我没有收到错误,但输出的解决方案显然不正确。
我现在调试了很长时间,我的假设是 MPI 通信中存在错误。
我的代码的通信部分如下所示:
MPI_Request req;
for(int j=0;j<numProcs;j++){
if(j!=myId){
tag=0;
sizeToSend=toProc[j].size();
MPI_Isend(&sizeToSend, 1, MPI_LONG_LONG, j, tag, MPI_COMM_WORLD,&req);
MPI_Request_free(&req);
}
}
for(int j=0;j<numProcs;j++){
if(j!=myId){
tag=0;
MPI_Recv(&sizeToReceive[j], 1, MPI_LONG_LONG, j, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
}
for(int j=0;j<numProcs;j++){
if(j!=myId){
if(toProc[j].size()>0){
tag=1;
MPI_Isend(&toProc[j][0], toProc[j].size(), MPI_LONG_LONG, j, tag, MPI_COMM_WORLD,&req);
MPI_Request_free(&req);
}
}
}
for(int j=0;j<numProcs;j++){
if(j!=myId){
if(sizeToReceive[j]>0){
receiveBuffer.resize(sizeToReceive[j]);
tag=1;
MPI_Recv(&receiveBuffer[0], sizeToReceive[j], MPI_LONG_LONG, j, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
for(int k=0;k<sizeToReceive[j];k++){
domain.field[receiveBuffer[k]]=1;
}
receiveBuffer.clear();
}
}
}
MPI_Barrier(MPI_COMM_WORLD);
for(int j=0;j<toProc.size();j++){
toProc[j].clear();
}
变量numProcs 是一个包含进程数量的整数,myId 是一个包含进程等级的整数,tag 是一个整数,domain.field 是一个vector<char>。
其他必要的变量定义如下:
vector<vector <long long> > toProc;
toProc.resize(numProcs);
long long sizeToReceive[numProcs];
long long sizeToSend=0;
vector<long long> receiveBuffer;
我在上面的代码中尝试做的是发送向量toProc[j] 以在每个进程上使用id==j for j=0,...,numProcs-1, j!=myId 进行处理。
为了实现这一点,我在前两个 for 循环中发送和接收这些向量的大小,并在第三和第四个 for 循环中发送和接收实际数据。我使用 Isend 是因为我显然希望这些调用是非阻塞的。
toProc[j] 中的值是索引,必须在进程 j 的向量 domain.field 中设置为 1(每个进程都有自己的 domain.field)。
我的问题是: 在我对 Isend-Recv 策略的使用中,您是否看到任何潜在的意外行为。
【问题讨论】:
-
我没有看到直接的问题,除了可能会发送太多正在进行的请求,但您似乎可以通过
MPI_Alltoall和MPI_Alltoallv大大简化和加快整个操作。跨度> -
感谢您的建议,我将尝试使用
MPI_Alltoall实现相同的行为,您认为多少请求太多?如果我只使用 4 个进程也会出现错误,那会不会已经太多了? -
似乎我忽略了一个相当明显的问题,请看我的回答。
-
四个请求都没有问题。但是如果你想要一个可扩展的应用程序,你应该使用 MPI 提供的集合,如果你正在处理多组进程。这些集体实施中进行了大量优化