我正在尝试实现某种形式的持久调用。不知怎的,下面的代码一直悬而未决 - 我猜想我必须引入一个僵局,但却无法真正解开它...
MPI_Request r[4];
[...]
MPI_Send_init(&Arr[1][1], 1, MPI_DOUBLE, 1, A, MPI_COMM_WORLD, &r[0]);
MPI_Recv_init(&Arr[1][0], 1, MPI_DOUBLE, 0, A, MPI_COMM_WORLD, &r[1]);
MPI_Send_init(&Arr[2][1], 1, MPI_DOUBLE, 0, B, MPI_COMM_WORLD, &r[2]);
MPI_Recv_init(&Arr[2][0], 1, MPI_DOUBLE, 1, B, MPI_COMM_WORLD, &r[3]);
[...]
MPI_Startall(4, r);
MPI_Waitall(4, r, MPI_STATUSES_IGNORE);
我认为这是死锁的完美材料 - 如果我想初始化这些发送/接收消息并稍后只使用Startall
和Waitall
调用这些进程,那么这将是什么补救措施?
编辑:所以如果我这样做
MPI_Start(&r[0]);
MPI_Wait(&r[0], &status):
然后它不会挂起。调用类似的东西:
for (int k=0; k<1; k++)
{
MPI_Start(&r[k]);
MPI_Wait(&r[k], &status);
}
失败并挂起。如果有帮助
答案 0 :(得分:1)
您的代码不匹配。
例如,排名0
从标签为A
的标签中收到
但它会使用标记B
答案 1 :(得分:0)
我必须承认我不熟悉MPI请求的概念和 MPI_Send / Recv_init 。但是,我可以通过简单的发送和接收来重现死锁。这是代码(它有一个死锁):
double someVal = 3.5;
const int MY_FIRST_TAG = 42;
MPI_Send(&someVal, 1, MPI_DOUBLE, 1, MY_FIRST_TAG, MPI_COMM_WORLD);
MPI_Recv(&someVal, 1, MPI_DOUBLE, 0, MY_FIRST_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
即使只使用两个进程运行它,问题如下:进程0和1都向进程1发送消息。然后两个进程都希望从进程0接收消息。进程1可以因为进程零实际上是向进程1发送了一条消息。但没有人发送消息进行处理0.因此,这个进程将永远等待。
如何修复:您需要指定只有进程0发送到进程1,并且只有进程1应该从进程0接收。您只需执行以下操作:
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0)
MPI_Send(&someVal, 1, MPI_DOUBLE, 1, MY_FIRST_TAG, MPI_COMM_WORLD);
else // Assumption: Only two processes
MPI_Recv(&someVal, 1, MPI_DOUBLE, 0, MY_FIRST_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
我并非100%确定如何将此转换为请求的概念以及 MPI_Send / Recv_init ,但这可能会对您有所帮助。