You need to enable JavaScript to run this app. MPI_Recv 从接收缓冲区指定位置存储数据的实现问题排查
优惠活动
大模型
产品
解决方案
定价
更多

MPI_Recv 从接收缓冲区指定位置存储数据的实现问题排查

代码问题排查结果

你的程序从最初版本就存在自定义MPI派生类型的计数重复错误,修改recv_buf后出现的无输出阻塞,是这个遗留问题叠加MPI底层内存越界保护的直接结果。

具体错误拆解

  • 对自定义MPI类型的语义理解偏差
    MPI_Type_contiguous(r, MPI_DOUBLE, &type)的作用是创建新的派生数据类型,单个该类型实例本身就等价于连续排布的r(也就是4)个MPI_DOUBLE元素。即1个type对象 = 4个double值。
    但你在后续MPI_Send、MPI_Recv的调用中,count参数依然传入r=4,这会导致实际通信的总元素规模变为:传入的count值 * 单个自定义类型的元素数 = 4 * 4 = 16个double。

  • 最初版本能输出的本质原因
    最初版本的recv_buf仅分配了4个double的栈空间,你让MPI往这块只有4个元素的缓冲区里写入16个double,属于栈内存踩踏的未定义行为。只是恰好写入的前4个值就是你要发送的mat数组内容,才凑巧输出了1 2 3 4,程序本身已经处于内存损坏的异常状态,只是没有触发崩溃而已。

  • 修改后程序无输出的原因
    你把recv_buf调整为10个double长度后,接收缓冲区的起始位置设在&recv_buf[6],从这个位置往后只有4个double的可用存储空间。但你的接收逻辑依然要求接收总大小为16个double的数据流,MPI底层会检测到接收缓冲区的可用空间完全无法容纳预期数据,直接不完成通信匹配,导致MPI_Recv永久阻塞,程序根本走不到后续的打印环节,自然没有任何输出。

正确修改方案

既然已经用MPI_Type_contiguous定义好了包含4个double的连续类型,收发时count参数传1即可,代表传递1个完整的自定义类型实例:

  • 0号进程发送代码调整为:
    MPI_Send(mat, 1, type, 1, 100, MPI_COMM_WORLD);
  • 1号进程接收代码调整为:
    MPI_Recv(&recv_buf[6], 1, type, 0, 100, MPI_COMM_WORLD, &status[0]);

修改后通信总数据量刚好是4个double,从recv_buf的下标6位置开始存放,正好占用6-9的下标空间,既不会越界,也能正确完成通信匹配。

冗余代码说明

你代码中定义的snd_buf、buf、position、长度为r的status数组全程没有实际作用,属于无意义的冗余声明,不影响运行但会增加理解成本,可以按需删除。MPI的接收状态变量只需要单个MPI_Status实例即可,不需要开辟数组。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 12:06:10