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

如何使用MPI_Scatter拆分数据并分发至除根进程外的所有进程

MPI根进程仅分发不保留数据的分片实现方法

场景说明

  • 测试集群共4个MPI进程,rank编号0~3
  • 初始状态:rank 0持有完整数据集[1,2,3,4,5,6],rank1、rank2、rank3初始持有空数组[]
  • 预期效果:分发完成后rank 0持有空数组[],rank1获取分片[1,2]、rank2获取[3,4]、rank3获取[5,6],根进程只承担分发职责,不保留任何分片
  • 常见踩坑:很多人第一反应是搭配MPI_IN_PLACE调用MPI_Scatter实现,但根本跑不通——MPI_IN_PLACE在Scatter接口中的设计作用是让根进程跳过接收步骤、保留自身内存中对应位置的分片,和「根进程不保留任何分片」的需求完全相反。

可直接落地的两种实现

方案1:MPI_Scatterv 自定义分片长度(性能最优,推荐)

标准MPI_Scatter要求所有进程的分片长度一致,默认会给根进程也分配一份分片,不适合当前场景。换成支持可变分片长度的MPI_Scatterv,给根进程设置收发长度为0即可,一次集合通信就能完成分发,比点对点通信效率高。
核心代码逻辑(C风格伪代码):

int sendcounts[4] = {0, 2, 2, 2}; // 各进程接收的元素个数,rank0设为0
int displs[4] = {0, 0, 2, 4};     // 各分片在根进程原数组中的偏移位置,rank0的偏移无实际意义可随意填
int *recv_buf = NULL;

// 非根进程提前分配接收缓存
if (rank != 0) {
    recv_buf = (int*)malloc(2 * sizeof(int));
}

MPI_Scatterv(
    rank == 0 ? full_array : NULL, // 只有根进程传入完整原数组
    sendcounts,
    displs,
    MPI_INT,
    recv_buf,
    rank == 0 ? 0 : 2, // 根进程接收长度设为0,不接收任何数据
    MPI_INT,
    0, // 指定根进程为rank0
    MPI_COMM_WORLD
);

// 根进程分发完成后直接释放原数组内存,即达到持有空数组的状态
if (rank == 0) {
    free(full_array);
    full_array = NULL;
}

注意:MPI标准明确允许Scatterv接口中给任意进程设置sendcount为0,不会触发通信错误,该写法完全符合MPI规范,可在所有主流MPI实现(OpenMPI、MPICH、Intel MPI)上正常运行。

方案2:点对点通信发送(逻辑简单,无参数门槛)

如果进程规模不大,或者对Scatterv的偏移、计数参数不熟悉,直接用点对点MPI_Send/MPI_Recv实现即可,逻辑直观不容易写错。
核心代码逻辑:

if (rank == 0) {
    // 按分片给其余三个进程发数据
    MPI_Send(full_array,     2, MPI_INT, 1, 0, MPI_COMM_WORLD);
    MPI_Send(full_array + 2, 2, MPI_INT, 2, 0, MPI_COMM_WORLD);
    MPI_Send(full_array + 4, 2, MPI_INT, 3, 0, MPI_COMM_WORLD);
    // 发完释放原数组
    free(full_array);
    full_array = NULL;
} else {
    recv_buf = (int*)malloc(2 * sizeof(int));
    MPI_Recv(recv_buf, 2, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}

这个写法没有集合通信的参数配置成本,代码可读性高,进程数少于100的时候性能差异可以忽略。

内容的提问来源于stack exchange,提问作者Liang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 17:25:33