问题描述
我想知道如果任何人都可以在MPI_Waitall功能为我闪耀光芒。我在使用MPI_Isend和MPI_Irecv程序传递信息。之后所有的发送和接收是完整的,在节目中的一个过程(在这种情况下,过程1),将打印的消息。我Isend / Irecv正在努力,但消息在程序中的一些随机点打印出;所以我试图用MPI_Waitall要等到所有的请求都打印消息之前完成。我收到以下错误信息:
I wonder if anyone can shed some light on the MPI_Waitall function for me. I have a program passing information using MPI_Isend and MPI_Irecv. After all the sends and receives are complete, one process in the program (in this case, process 0), will print a message. My Isend/Irecv are working, but the message prints out at some random point in the program; so I am trying to use MPI_Waitall to wait until all the requests are done before printing the message. I receive the following error message:
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)
下面是一些相关的code:
Here is some relevant code:
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完成。
Without the call to MPI_Waitall, the program runs cleanly, but the "All done" message prints as soon as process 0's Isend/Irecv messages complete, instead of after all Isend/Irecvs complete.
感谢您的帮助,您可以提供。
Thank you for any help you can provide.
推荐答案
您只设置要求
阵列,即要求[中的一个要素任务id]
(顺便说一句,你用覆盖发送请求手柄收到,无可挽回地失去了前)。请记住,MPI用于分布式内存的机器上编程,每个MPI进程都有自己的要求
数组的副本。设置军衔一个元素的taskid
不会奇迹般地价值传播到其他队伍,即使是这样,请求只有当地的有效性。正确的实现将是:
You are only setting one element of the request
array, namely request[taskid]
(and by the way you overwrite the send request handle with the receive one, irrevocably losing the former). Remember, MPI is used to program distributed memory machines and each MPI process has its own copy of the request
array. Setting one element in rank taskid
does not magically propagate the value to the other ranks, and even if it does, requests have only local validity. The proper implementation would be:
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();
对了,还有你的code数据竞争。无论 MPI_Isend
和 MPI_Irecv
使用相同的数据缓冲区,这是不正确。如果你只是想数据
的内容发送到 DEST
,然后接收到从源
,然后用 MPI_Sendrecv_replace
来代替,而忘记了非阻塞操作:
By the way, there is a data race in your code. Both MPI_Isend
and MPI_Irecv
are using the same data buffer, which is incorrect. If you are simply trying to send the content of data
to dest
and then receive into it from source
, then use MPI_Sendrecv_replace
instead and forget about the non-blocking operations:
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();
这篇关于MPI_Waitall失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!