You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 07:17:04