MPI程序仅2个处理器可正常运行,超过2个时卡住无响应,求代码问题排查
MPI代码死锁问题排查
已确认的错误点
- 运行命令参数错误:你使用的
mpiexec -n -4 ./name.exe中-n参数后多了多余的减号,正确格式为mpiexec -n 4 ./name.exe - 中间进程发送目标错误:
0 < rank < size-1的中间进程代码中,虽然定义了sendToNumber = rank + 1,但实际MPI_Send调用时硬编码了接收进程为0,完全不符合“发送给下一个进程”的设计逻辑 - 阻塞通信顺序错误导致死锁:所有进程都先执行阻塞
MPI_Send再执行MPI_Recv,进程数为2时短消息被MPI缓冲所以能正常运行,进程数超过2时缓冲不足,所有进程都会卡在MPI_Send调用等待接收方执行接收操作,形成死锁 - 最后一个进程逻辑顺序错误:按设计应该先接收前一个进程的消息,再将结果发送给0号进程,现有代码顺序刚好相反,会加剧死锁概率
修复后的代码
#include <stdio.h> #include <mpi.h> #include <stdlib.h> int main() { int rank, sent, size; MPI_Status status; MPI_Init(NULL, NULL); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); int valueToSend = rank * 10; if (rank == 0) { // 0号进程先发给下一个进程,再等待最后一个进程的消息 MPI_Send(&valueToSend, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); MPI_Recv(&sent, 1, MPI_INT, size - 1, MPI_ANY_TAG, MPI_COMM_WORLD, &status); printf("Process %d otrzymal %d od %d\n", rank, sent, status.MPI_SOURCE); } else if (rank < size - 1) { int sendToNumber = rank + 1; int receivedFromNumber = rank - 1; // 中间进程先收前一个的消息,再发给下一个进程 MPI_Recv(&sent, 1, MPI_INT, receivedFromNumber, MPI_ANY_TAG, MPI_COMM_WORLD, &status); printf("Process %d otrzymal %d od %d\n", rank, sent, status.MPI_SOURCE); MPI_Send(&valueToSend, 1, MPI_INT, sendToNumber, 0, MPI_COMM_WORLD); } else if (rank == size - 1) { int receivedFromNumber = rank - 1; // 最后一个进程先收前一个的消息,再发给0号进程 MPI_Recv(&sent, 1, MPI_INT, receivedFromNumber, MPI_ANY_TAG, MPI_COMM_WORLD, &status); printf("Process %d otrzymal %d od %d\n", rank, sent, status.MPI_SOURCE); MPI_Send(&valueToSend, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); } MPI_Finalize(); return 0; }
修复验证
修复后使用mpiexec -n 4 ./name.exe运行,会依次输出4个进程的接收信息,不会再出现死锁无输出的问题。
内容的提问来源于stack exchange,提问作者Kokomi
相关产品推荐
相关产品推荐

