MPI_COMM_WORLD子集执行Broadcast引发死锁的问题排查
MPI批量处理场景下第一次迭代死锁问题排查
无法理解为何程序在第一次迭代时于rank=3处发生死锁(可能因环境不同有所差异)。我需要实现批量处理逻辑,且必须兼容批量大小无法被进程数整除的场景。
我预期的程序执行流程如下:
- 所有进程加入
activ_com通信器; rank=1退出流程:断开activ_com连接,等待MPI_Finalize;- 第一次迭代:
rank=0发送数据,rank=2、3接收数据; rank=3退出流程:断开activ_com连接,等待MPI_Finalize(实际场景中步骤5可能先于断开操作执行);- 第二次迭代:
rank=0发送数据,rank=2接收数据; rank=0、2退出流程。
显然我对MPI某些核心概念存在误解,但无法定位具体问题。我已查阅MPI官方文档及相关解决方案,尝试使用子通信器仅在活跃进程上执行MPI_Bcast,但死锁仍出现在步骤3的第一次迭代中。我知道可以通过MPI_Scatterv和MPI_Gatherv处理此类场景,但希望找到替代MPI_Scatterv的方案;也考虑过Session Model,但当前更想明确导致本次死锁的具体原因。
可复现代码
#include <mpi.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #include <stdbool.h> #define N 32 static int world_size; MPI_Comm activ_com; #define COM_ACTIVE_TAG 1 static void signoff(int rank) { printf("Registered for Signoff: rank %d out of %d processors\n", rank, world_size); /* tested splitting for signoff */ //MPI_Comm_split(MPI_COMM_WORLD, MPI_UNDEFINED, rank, &activ_com); if (rank != 0) { int process = 0; MPI_Status status; MPI_Iprobe(MPI_ANY_SOURCE,MPI_ANY_TAG, activ_com, &process, &status); if (process) printf("Communication still pending from %d on %d\n", status.MPI_SOURCE, rank); } MPI_Comm_disconnect(&activ_com); } int main(int argc, char** argv) { MPI_Init(NULL, NULL); // initialize MPI environment MPI_Comm_size(MPI_COMM_WORLD, &world_size); int world_rank; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); //MPI_Comm_split(MPI_COMM_WORLD, COM_ACTIVE_TAG, world_rank, &activ_com); MPI_Comm_dup(MPI_COMM_WORLD, &activ_com); int workers[world_size]; for (int i = 0; i < world_size; ++i) workers[i] = true; long dummy[N]; time_t t; if (world_rank == 0) srand(3); if (world_rank == 2) srand(7); if (world_rank == 0) { for (int i = 0; i < N; ++i) dummy[i] = i; } if (world_rank == 1) { //printf("Registered for Signoff: rank %d out of %d processors\n", world_rank, world_size); signoff(world_rank); MPI_Finalize(); printf("Signoff: rank %d out of %d processors\n", world_rank, world_size); return 0; } for(int i = world_rank; i < 7; i+=world_size) { int wait = 0; /* use different wait times for testing */ if (world_rank != 3) wait = rand() % 10; printf("Bcast: %d/%d, i=%d, waittime=%d\n", world_rank, world_size, i, wait); sleep(wait); /* rank=3 is hanging here in the first iteration */ MPI_Bcast(&dummy, N, MPI_LONG, 0, activ_com); printf("Bcast: %d/%d, i=%d, processed\n", world_rank, world_size, i); } /* keep rank alive for testing */ if (world_rank == 3) sleep(5); signoff(world_rank); MPI_Comm_free(&activ_com); MPI_Finalize(); printf("Signoff: rank %d out of %d processors\n", world_rank, world_size); return 0; }
运行环境
$ mpirun --version mpirun (Open MPI) 4.1.2 $ mpicc --version gcc (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0
内容的提问来源于stack exchange,提问作者VladMir
相关产品推荐
相关产品推荐

