gpt4 book ai didi

c - MPI_Waitall 失败

转载 作者:太空狗 更新时间:2023-10-29 14:54:09 25 4
gpt4 key购买 nike

我想知道是否有人可以为我阐明 MPI_Waitall 函数。我有一个使用 MPI_Isend 和 MPI_Irecv 传递信息的程序。在所有发送和接收完成后,程序中的一个进程(在本例中为进程 0)将打印一条消息。我的 Isend/Irecv 正在工作,但消息在程序中的某个随机点打印出来;所以我试图使用 MPI_Waitall 等待所有请求完成后再打印消息。我收到以下错误消息:

Fatal error in PMPI_Waitall: Invalid MPI_Request, error stack:
PMPI_Waitall(311): MPI_Waitall(count=16, req_array=0x16f70d0, status_array=0x16f7260) failed
PMPI_Waitall(288): The supplied request in array element 1 was invalid (kind=0)

这里是一些相关的代码:

MPI_Status *status;
MPI_Request *request;

MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &taskid);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
status = (MPI_Status *) malloc(numtasks * sizeof(MPI_Status));
request = (MPI_Request *) malloc(numtasks * sizeof(MPI_Request));

/* Generate Data to send */
//Isend/Irecvs look like this:
MPI_Isend(&data, count, MPI_INT, dest, tag, MPI_COMM_WORLD, &request[taskid]);
MPI_Irecv(&data, count, MPI_INT, source, tag, MPI_COMM_WORLD, &request[taskid]);
MPI_Wait(&request[taskid], &status[taskid]

/* Calculations and such */

if (taskid == 0) {
MPI_Waitall (numtasks, request, status);
printf ("All done!\n");
}
MPI_Finalize();

如果不调用 MPI_Waitall,程序会正常运行,但“全部完成”消息会在进程 0 的 Isend/Irecv 消息完成后立即打印,而不是在所有 Isend/Irecvs 完成后打印。

感谢您提供的任何帮助。

最佳答案

您只设置了 request 数组的一个元素,即 request[taskid](顺便说一句,您用接收请求句柄覆盖了发送请求句柄,不可撤销失去前者)。请记住,MPI 用于对分布式内存机器进行编程,每个 MPI 进程都有自己的 request 数组副本。在 rank taskid 中设置一个元素不会神奇地将值传播到其他 ranks,即使这样,请求也只有本地有效性。正确的实现方式是:

MPI_Status status[2];
MPI_Request request[2];

MPI_Init(&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &taskid);
MPI_Comm_size (MPI_COMM_WORLD, &numtasks);

/* Generate Data to send */
//Isend/Irecvs look like this:
MPI_Isend (&data, count, MPI_INT, dest, tag, MPI_COMM_WORLD, &request[0]);
// ^^^^
// ||
// data race !!
// ||
// vvvv
MPI_Irecv (&data, count, MPI_INT, source, tag, MPI_COMM_WORLD, &request[1]);
// Wait for both operations to complete
MPI_Waitall(2, request, status);

/* Calculations and such */

// Wait for all processes to reach this line in the code
MPI_Barrier(MPI_COMM_WORLD);

if (taskid == 0) {
printf ("All done!\n");
}
MPI_Finalize();

顺便说一下,您的代码中存在数据竞争。 MPI_IsendMPI_Irecv 使用相同的数据缓冲区,这是不正确的。如果您只是想将 data 的内容发送到 dest,然后从 source 接收到它,则使用 MPI_Sendrecv_replace 而不是忘记非阻塞操作:

MPI_Status status;

MPI_Init(&argc, &argv);
MPI_Comm_rank (MPI_COMM_WORLD, &taskid);
MPI_Comm_size (MPI_COMM_WORLD, &numtasks);

/* Generate Data to send */
MPI_Sendrecv_replace (&data, count, MPI_INT, dest, tag, source, tag,
MPI_COMM_WORLD, &status);

/* Calculations and such */

// Wait for all processes to reach this line in the code
MPI_Barrier(MPI_COMM_WORLD);

if (taskid == 0) {
printf ("All done!\n");
}
MPI_Finalize();

关于c - MPI_Waitall 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15441163/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com