使用MPI_Irecv与MPI_ANY_SOURCE通信时source返回-1的原因
问题成因
你遇到的MPI_Status.source返回-1的核心原因是对已完成且被释放的MPI请求调用了MPI_Request_get_status,拿到的是无效状态值,具体逻辑如下:
MPI_Wait(&R2[i], &status)调用成功后,会自动将请求R2[i]设置为MPI_REQUEST_NULL,并释放该请求对应的资源- 后续调用
MPI_Request_get_status(R2[i], &flag, &status)时,传入的已经是无效的空请求,MPI实现会将status字段的所有值初始化为默认无效值,因此MPI_SOURCE返回-1 - 你实际已经在
MPI_Wait的出参status里拿到了有效的源进程号,完全不需要再调用MPI_Request_get_status获取状态
其他潜在问题
另外你的代码还有两个容易引发异常的隐患:
- 没有校验
MPI_Init_thread返回的线程支持级别是否真的是MPI_THREAD_MULTIPLE,部分MPI实现默认不开启多线程并发调用MPI接口的支持,可能会引发未定义行为 - 你用2个OpenMP线程在同一个进程内同时调用MPI收发接口,即使
MPI_THREAD_MULTIPLE支持正常,也要确保没有请求号、缓冲区的竞争,当前代码里的缓冲区是函数内局部变量暂时没有竞争,但后续扩容容易踩坑
修复方案
直接删掉MPI_Request_get_status这一行即可,用MPI_Wait返回的status值获取源进程号,修改后的fun1循环部分代码如下:
for (int i=0; i<L; ++i) { statusflag = MPI_Irecv(&buffer[i], 1, MPI_INT, MPI_ANY_SOURCE, 2501, MPI_COMM_WORLD, &R2[i]); MPI_Status status; // Wait调用成功后status里已经有所有需要的信息 MPI_Wait(&R2[i], &status); int q = status.MPI_SOURCE; printf("Flag was 1, source was %d, the error was %d, and statusflag was %d\n\n\n", q, status.MPI_ERROR, statusflag); std::cout<<std::flush; answers[i] = i*5; MPI_Ssend(&answers[i], 1, MPI_INT, q, i, MPI_COMM_WORLD); }
修改后重新编译运行即可解决source返回-1以及后续段错误的问题。
内容的提问来源于stack exchange,提问作者Gaston
相关产品推荐
相关产品推荐

