我正在尝试使用MPI_Win_lock
和MPI_Win_unlock
对MPI的RMA操作进行简单测试。程序只是让进程0更新进程1中的整数值并显示它。
以下程序运行正常(至少结果似乎对我来说):
#include "mpi.h"
#include "stdio.h"
#define root 0
int main(int argc, char *argv[])
{
int myrank, nprocs;
int send, recv, err;
MPI_Win nwin;
int *st;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
MPI_Alloc_mem(1*sizeof(int), MPI_INFO_NULL, &st);
st[0] = 0;
if (myrank != root) {
MPI_Win_create(st, 1*sizeof(int), sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &nwin);
}
else {
MPI_Win_create(NULL, 0, sizeof(int), MPI_INFO_NULL, MPI_COMM_WORLD, &nwin);
}
if (myrank == root) {
st[0] = 1;
MPI_Win_lock(MPI_LOCK_EXCLUSIVE, 1, 0, nwin);
MPI_Put(st, 1, MPI_INT, 1, 0, 1, MPI_INT, nwin);
MPI_Win_unlock(1, nwin);
MPI_Win_free(&nwin);
}
else { // rank 1
MPI_Win_free(&nwin);
printf("Rank %d, st = %d\n", myrank, st[0]);
}
MPI_Free_mem(st);
MPI_Finalize();
return 0;
}
我得到的输出是Rank 1, st = 1
。但奇怪的是,如果我将else块中的行切换为等级1到
else { // rank 1
printf("Rank %d, st = %d\n", myrank, st[0]);
MPI_Win_free(&nwin);
}
输出为Rank 1, st = 0
。
我无法找出其背后的原因,以及为什么我需要在加载数据后放置MPI_Win_free
最初我需要将所有内容放入while循环中并让等级0来确定何时停止环。当条件满足时,我尝试让等级0更新等级1中的标志(st)。我尝试将MPI_Win_free置于while循环之外,以便窗口仅在循环之后被释放。现在似乎我不能这样做,并且每次都需要在循环中创建和释放窗口?
答案 0 :(得分:0)
我会说实话,MPI RMA不是我的专长,但我会给这一点:
问题是你遇到了竞争状态。当您执行MPI_PUT
操作时,它会将等级0到等级1的数据发送到将来的某个时刻放入缓冲区。从0级的角度来看,你没有任何控制权。
一个等级1的一方,你没有做任何事情来完成操作。我知道RMA(或片面操作)听起来好像不应该在目标方面进行任何干预,但确实需要一点。当您使用单面操作时,您必须在接收端有一些同步数据的东西。在这种情况下,您尝试将MPI put / get操作与非MPI加载存储操作结合使用。这是错误的,导致你看到的竞争条件。当您将MPI_WIN_FREE
切换为第一个时,您将完成所有未完成的操作,以便您的数据正确无误。
您可以通过以下问题了解有关被动目标同步的更多信息(这是您在此处所做的):MPI with C: Passive RMA synchronization。