You need to enable JavaScript to run this app. 使用MPI_Send/MPI_Recv替代MPI_Gather时根进程缓冲区未更新问题
优惠活动
大模型
产品
解决方案
定价
更多

使用MPI_Send/MPI_Recv替代MPI_Gather时根进程缓冲区未更新问题

核心问题定位

运行结果和预期不符的根本原因是接收逻辑的内存写入位置错误,和MPI基础收发接口无关:

  • 根进程的MPI_Recv每次都从single_arr的起始地址开始写入数据,没有按照进程编号做内存偏移,导致每接收一个进程的数据集,就会把之前写入的内容完全覆盖,根本没有按块存储不同进程的发送内容
  • 这种写法下,根进程的single_arr只有开头两个元素会被最后一次接收的进程数据覆盖,其余位置都是vector默认初始化的0值。当启动4个进程时,最后一次接收操作是收取rank3的数据集,写入缓冲区开头,这也是你看到输出前两个值为3、4,其余全为0的直接原因。
代码调整方案

只需要修改根进程的接收循环逻辑,让每个进程的数据集写入到对应的缓冲区位置,整体布局和MPI_Gather的默认内存规则保持一致,不需要改动其他流程:

  • 按照MPI_Gather的标准布局约定:第p个进程的N个元素,在根进程的接收缓冲区中的起始偏移为p * N
  • 接收i号进程的数据时,把接收指针从single_arr.data()调整为single_arr.data() + i * N,避免反复覆盖开头的内容
  • 原代码中从未被使用的receive_data变量可以直接删除,不影响运行逻辑

修改后的根进程接收段代码如下:

if (rank == root) {
    for (int i = 1; i < size; i++) {
        // 定位到当前进程对应的缓冲区写入位置
        int* write_pos = single_arr.data() + i * N;
        MPI_Recv(write_pos, N, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    }
}
调整后的运行效果

当进程数为4、N=2时,根进程的接收缓冲区存储内容会和预期完全匹配:

  • 偏移0、1:根进程自己的x数组值 0, 1
  • 偏移2、3:rank1发送的x数组值 1, 2
  • 偏移4、5:rank2发送的x数组值 2, 3
  • 偏移6、7:rank3发送的x数组值 3, 4
    拼接后的完整输出和你期望的顺序完全一致,结果和直接调用MPI_Gather没有任何差异。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.30 14:54:09