我试图通过一个小例子来理解 MPI-Function `MPI_Fetch_and_op() 并遇到了我想理解的奇怪行为。
在该示例中,等级为 0 的进程正在等待,直到进程 1..4 各自将 result 的值加一,然后再继续。
0
在函数中使用 assert的默认值时,MPI_Win_lock_all()
有时(10 次中有 1 次)会出现无限循环,即将result[0]
MASTER 中的值更新为 3。终端输出类似于以下代码片段:
result: 3
result: 3
result: 3
...
根据文档,功能 MPI_Fetch_and_op 是原子的。
此操作相对于其他“累积”操作是原子的。
第一个问题:
为什么不将 的值更新result[0]
为 4?
如果我将值更改assert
为MPI_MODE_NOCHECK
它似乎工作
第二个问题:
为什么它与MPI_MODE_NOCHECK
根据文档,我认为这意味着必须以不同的方式组织互斥。有人可以解释文档中的段落MPI_Win_lock_all()
吗?
MPI_MODE_NOCHECK
当调用者持有窗口锁时,没有其他进程持有或将尝试获取冲突锁。当通过其他方式实现互斥时,这很有用,但仍需要可能附加到 lock 和 unlock 调用的一致性操作。
提前致谢!
示例程序:
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#define MASTER 0
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
MPI_Comm comm = MPI_COMM_WORLD;
int r, p;
MPI_Comm_rank(comm, &r);
MPI_Comm_size(comm, &p);
printf("Hello from %d\n", r);
int result[1] = {0};
//int assert = MPI_MODE_NOCHECK;
int assert = 0;
int one = 1;
MPI_Win win_res;
MPI_Win_allocate(1 * sizeof(MPI_INT), sizeof(MPI_INT), MPI_INFO_NULL, comm, &result[0], &win_res);
MPI_Win_lock_all(assert, win_res);
if (r == MASTER) {
result[0] = 0;
do{
MPI_Fetch_and_op(&result, &result , MPI_INT, r, 0, MPI_NO_OP, win_res);
printf("result: %d\n", result[0]);
} while(result[0] != 4);
printf("Master is done!\n");
} else {
MPI_Fetch_and_op(&one, &result, MPI_INT, 0, 0, MPI_SUM, win_res);
}
MPI_Win_unlock_all(win_res);
MPI_Win_free(&win_res);
MPI_Finalize();
return 0;
}
使用以下 Makefile 编译:
MPICC = mpicc
CFLAGS = -g -std=c99 -Wall -Wpedantic -Wextra
all: fetch_and
fetch_and: main.c
$(MPICC) $(CFLAGS) -o $@ main.c
clean:
rm fetch_and
run: all
mpirun -np 5 ./fetch_and