当前位置: 首页 > news >正文

MPI_Win_allocate_shared介绍和使用

文章目录

  • MPI_Win_allocate_shared 详解 + 幽灵单元(Ghost Cell)交换完整示例
    • 一、核心概念
      • 1. 函数作用
      • 2. 函数原型
      • 3. 关键特性
    • 二、幽灵单元(Ghost Cell)交换场景
      • 1. 场景说明
      • 2. 优势
    • 三、完整代码实现(C语言)
      • 代码逻辑
    • 四、代码关键细节解析
      • 1. 共享通信域创建
      • 2. 共享内存分配
      • 3. 邻居地址查询
      • 4. 窗口同步
    • 五、编译与运行
      • 编译(MPI编译器)
      • 运行(同节点运行3个进程)
      • 输出示例
    • 六、核心优势与适用场景
      • 优势
      • 适用场景
      • 限制
      • 总结

MPI_Win_allocate_shared 详解 + 幽灵单元(Ghost Cell)交换完整示例

MPI_Win_allocate_sharedMPI-3 标准引入的单边通信(RMA)核心函数,专门用于同节点共享内存场景,能让同一计算节点上的 MPI 进程直接读写彼此的内存,无需消息传递,性能远高于传统MPI_Send/Recv

一、核心概念

1. 函数作用

为**共享内存通信域(通常是同一节点)**内的所有进程,集体分配一段内存:

  • 调用进程拥有本地内存段(可直接读写)
  • 同节点其他进程可通过MPI 单边RMA操作直接访问这段内存
  • 无需拷贝数据,直接内存访问,极致高效

2. 函数原型

intMPI_Win_allocate_shared(MPI_Aint size,// 本地分配的内存大小(字节)intdisp_unit,// 地址偏移单位(通常=1,字节对齐)MPI_Info info,// 优化信息(通常MPI_INFO_NULL)MPI_Comm comm,// 共享内存通信域(必须是节点内共享子通信域)void*baseptr,// 输出:本地内存段起始地址MPI_Win*win// 输出:创建的共享内存窗口对象);

3. 关键特性

  1. 集体操作:共享通信域内所有进程必须同时调用
  2. 节点内有效:只能在同一NUMA节点/计算节点的进程间共享
  3. 零拷贝:直接访问物理内存,无中间缓冲区
  4. 配套APIMPI_Win_shared_query(查询其他进程的共享内存地址)

二、幽灵单元(Ghost Cell)交换场景

1. 场景说明

一维区域分解

  • 每个进程负责一段主数据(data[1]~data[size]
  • 左右各1个幽灵单元data[0]=左幽灵,data[size+1]=右幽灵)
  • 需求:左幽灵 ← 左邻居的最后一个主数据;右幽灵 ← 右邻居的第一个主数据

2. 优势

传统MPI需要Send/Recv收发数据,而MPI_Win_allocate_shared

  • 直接内存读写,无消息开销
  • 代码更简洁,适合同节点并行

三、完整代码实现(C语言)

代码逻辑

  1. 创建节点内共享内存通信域comm_shm
  2. MPI_Win_allocate_shared分配带幽灵单元的共享数组
  3. MPI_Win_shared_query获取邻居的共享内存地址
  4. 直接内存赋值完成幽灵单元交换(无MPI收发)
  5. 同步窗口、释放资源
#include<stdio.h>#include<stdlib.h>#include<mpi.h>// 每个进程的主数据长度(不含幽灵单元)#defineDATA_SIZE4intmain(intargc,char**argv){MPI_Init(&argc,&argv);intrank,size;MPI_Comm_rank(MPI_COMM_WORLD,&rank);MPI_Comm_size(MPI_COMM_WORLD,&size);// ===================== 步骤1:创建节点内共享内存通信域 =====================MPI_Comm comm_shm;// 按物理节点拆分通信域,同节点进程在同一个comm_shm中MPI_Comm_split_type(MPI_COMM_WORLD,MPI_COMM_TYPE_SHARED,// 按共享内存节点拆分rank,MPI_INFO_NULL,&comm_shm);intshm_rank,shm_size;MPI_Comm_rank(comm_shm,&shm_rank);MPI_Comm_size(comm_shm,&shm_size);// ===================== 步骤2:分配共享内存(含2个幽灵单元) =====================// 总长度:左幽灵(1) + 主数据(DATA_SIZE) + 右幽灵(1)inttotal_len=DATA_SIZE+2;MPI_Aint shm_size_bytes=total_len*sizeof(int);// 总字节数int*local_data;// 本地共享内存指针MPI_Win shm_win;// 共享内存窗口// 集体分配共享内存MPI_Win_allocate_shared(shm_size_bytes,// 本地内存大小sizeof(int),// 偏移单位:按int对齐MPI_INFO_NULL,comm_shm,&local_data,// 输出本地内存地址&shm_win// 输出窗口);// ===================== 步骤3:初始化本地数据 =====================// local_data[0] = 左幽灵单元// local_data[1~DATA_SIZE] = 主数据// local_data[DATA_SIZE+1] = 右幽灵单元for(inti=1;i<=DATA_SIZE;i++){local_data[i]=rank*10+i;// 方便识别数据归属}local_data[0]=-1;// 初始左幽灵local_data[DATA_SIZE+1]=-1;// 初始右幽灵// ===================== 步骤4:获取左右邻居的共享内存地址 =====================intleft_rank=(shm_rank-1+shm_size)%shm_size;// 左邻居intright_rank=(shm_rank+1)%shm_size;// 右邻居int*left_neigh_data=NULL;// 左邻居共享内存地址int*right_neigh_data=NULL;// 右邻居共享内存地址MPI_Aint query_size;intquery_disp_unit;// 查询左邻居的共享内存基地址MPI_Win_shared_query(shm_win,left_rank,&query_size,&query_disp_unit,&left_neigh_data);// 查询右邻居的共享内存基地址MPI_Win_shared_query(shm_win,right_rank,&query_size,&query_disp_unit,&right_neigh_data);// ===================== 步骤5:直接内存交换幽灵单元(核心!) =====================// 开启RMA访问窗口MPI_Win_fence(0,shm_win);// 1. 左幽灵 = 左邻居的最后一个主数据local_data[0]=left_neigh_data[DATA_SIZE];// 2. 右幽灵 = 右邻居的第一个主数据local_data[DATA_SIZE+1]=right_neigh_data[1];// 同步所有进程的内存访问MPI_Win_fence(0,shm_win);// ===================== 步骤6:打印结果 =====================printf("[进程 %d] 数据:幽灵左=%d, 主数据=[%d,%d,%d,%d], 幽灵右=%d\n",rank,local_data[0],local_data[1],local_data[2],local_data[3],local_data[4],local_data[DATA_SIZE+1]);// ===================== 步骤7:释放资源 =====================MPI_Win_free(&shm_win);MPI_Comm_free(&comm_shm);MPI_Finalize();return0;}

四、代码关键细节解析

1. 共享通信域创建

MPI_Comm_split_type(..., MPI_COMM_TYPE_SHARED, ...)

  • 自动将全局通信域拆分为物理节点内的子通信域
  • 只有同节点进程能共享内存,跨节点不支持

2. 共享内存分配

MPI_Win_allocate_shared

  • 第二个参数disp_unit=sizeof(int):地址偏移按int单位计算,更安全
  • local_data本地直接可用的指针,和普通数组无区别

3. 邻居地址查询

MPI_Win_shared_query

  • 输入窗口+目标进程rank
  • 输出目标进程的共享内存起始指针
  • 拿到指针后,直接赋值即可交换数据,无任何MPI收发

4. 窗口同步

MPI_Win_fence

  • 集体同步函数,确保所有进程的内存访问完成
  • 必须在共享内存读写前后调用,保证数据一致性

五、编译与运行

编译(MPI编译器)

mpicc-oshm_ghost shm_ghost.c

运行(同节点运行3个进程)

mpirun-n3./shm_ghost

输出示例

[进程 0] 数据:幽灵左=24, 主数据=[1,2,3,4], 幽灵右=11 [进程 1] 数据:幽灵左=4, 主数据=[11,12,13,14], 幽灵右=21 [进程 2] 数据:幽灵左=14, 主数据=[21,22,23,24], 幽灵右=1
  • 进程0的左幽灵=进程2的最后一个主数据(24)
  • 进程0的右幽灵=进程1的第一个主数据(11)
  • 幽灵单元交换完成!

六、核心优势与适用场景

优势

  1. 性能极高:零拷贝、直接内存访问,比Send/Recv快5~10倍
  2. 代码简洁:无需处理消息收发、标签、匹配问题
  3. 原生支持:MPI-3标准,主流MPI库(OpenMPI、MPICH)全支持

适用场景

  1. 同节点多进程并行(CPU多核、节点内并行)
  2. 数值模拟:幽灵单元交换、边界数据更新
  3. 共享内存架构下的高频数据交互

限制

  • 仅支持同一物理节点的进程,跨节点必须配合传统MPI通信
  • 必须集体调用,不能单独执行

总结

  1. MPI_Win_allocate_shared节点内共享内存+单边通信的最优方案
  2. 幽灵单元交换:查询邻居地址 → 直接内存赋值 → 窗口同步,无收发
  3. 代码可直接用于一维/二维/三维数值模拟的边界数据交换
  4. 同节点场景下,性能远超传统MPI点对点通信
http://www.jsqmd.com/news/868167/

相关文章:

  • ops-softmax:Transformer 推理中的概率归一化引擎
  • 贴片晶振的广泛应用与768kHz晶振的优势
  • 阿里巴巴与厦门大学联手打造“时装变色龙“
  • OpenClaw:高效管理分布式Agent开发团队
  • Claude Code 国内替代方案:基于百炼的配置与实践
  • Newman安装之nodejs下载安装
  • ops-reduce:ReduceMax 与 ReduceMean 的并行优化
  • 把大脑交给自己,而非交给 AI —— Files.md 的“极简知识管理“哲学
  • RK3588下位机程序无响应问题排查
  • 百度网盘提取码终极查询指南:10秒告别手动搜索的烦恼
  • 北大等研究揭示:AI答题正确背后存在可被捕捉的作弊行为漏洞
  • python文化旅游服务系统 小程序系统
  • 私有化 IM vs 公有云 IM:3 个维度告诉你该怎么选
  • 为什么你的 AI 应用做不成 Agent
  • 抖音下载神器:免费批量下载视频、图集、音乐和直播回放完整指南
  • 基于TinyEngine低代码引擎的AI Agent开发完整指南
  • 长沙短视频拍摄引流哪家更值得信赖
  • python新能源汽车4s店车辆管理系统
  • 5分钟搞定Windows 11区域语言模拟:Locale Remulator终极指南
  • 2026年4月正规的接待台定制源头厂家推荐,创意接待台定制吸引目光 - 品牌推荐师
  • 有限域算术:GF(2^n) 运算与在 AES/ECC 中的应用
  • Python/JS/Go三语言生成质量对比,错误率、可维护性、安全漏洞全维度打分,开发者速查清单!
  • 2026年IEEE TEVC,面向城市电缆布线优化的双层多精度搜索框架
  • 2026现阶段合肥养老中心怎么选?聚焦专业护理价值的深度指南 - 2026年企业推荐榜
  • 2026大模型安全评估报告|一键通关撰写攻略(备案专用)
  • ElevenLabs方言支持白皮书(2024Q2):安徽话覆盖度仅61.7%?我们逆向解析其phoneme inventory并开源替代音素映射表
  • 搞定环境一致性神器:Linux 环境下 Docker 新手入门全攻略
  • 2026年Q2简阳冷库安装市场:专业本地服务商的价值凸显 - 2026年企业推荐榜
  • 2026年4月行业内评价好的挡车球实力厂家推荐,迎宾石/马路牙子/标识石/路缘石/彩色水磨石,挡车球直销厂家口碑推荐 - 品牌推荐师
  • 语音克隆怎么弄?2026 最新零基础全流程教程(3 分钟上手)