news 2026/9/19 2:50:08

CANN SHMEM 中基于 ACLGraph 的 RDMA AllGather 同步机制与运行实战:rdma_aclgraph_demo 全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANN SHMEM 中基于 ACLGraph 的 RDMA AllGather 同步机制与运行实战:rdma_aclgraph_demo 全解析

CANN SHMEM 中基于 ACLGraph 的 RDMA AllGather 同步机制与运行实战:rdma_aclgraph_demo 全解析

【免费下载链接】shmemCANN SHMEM 是面向昇腾平台的多机多卡内存通信库,基于OpenSHMEM 标准协议,实现跨设备的高效内存访问与数据同步。项目地址: https://gitcode.com/cann/shmem

CANN SHMEM 是面向昇腾平台的多机多卡内存通信库,基于 OpenSHMEM 标准协议实现跨设备的高效内存访问与数据同步。本文以仓库中的 examples/rdma_aclgraph_demo 为对象,剖析在 ACLGraph(Ascend 图执行模型)中嵌入 RDMA AllGather 通信算子的关键技术——即通过aclshmemx_roce_barrier_all屏障接口解决"AllGather 仅发出 Write 操作、无法保证图执行到相同阶段"的同步问题。读完本文,你将掌握该样例的 ACLGraph 图结构设计、环境准备、单机/跨机运行方式、命令行参数含义,以及从源码层面理解其同步原理与精度校验逻辑。

样例场景:为什么 ACLGraph 中的 AllGather 需要显式同步

rdma_aclgraph_demo的目标是在一张 ACLGraph 图中编排add + allGather + allGather + add的计算序列,并验证在 RDMA(ROCE)传输下 AllGather 算子嵌入图执行后的功能正确性。

该场景的核心难点在于:RDMA AllGather 只发送 Write 操作。与传统的读-改-写通信方式不同,aclshmemx_roce_put_nbi这类单边 PUT 操作将数据直接写入远端对称内存,不会主动通知对端"写入已完成"。因此,如果没有额外同步,所有 PE 上的图执行进度可能不一致:某些 PE 已经开始消费数据,而另一些 PE 的数据尚未到达,导致 AllGather 结果错误,进而使 ACLGraph(model)的精度异常。

解决办法是在 rdma allgather 算子中显式加入 aclshmemx_roce_barrier_all 接口进行全量屏障同步,确保所有 PE 上的图均已执行到相应阶段后再进行数据交换,从而保证 ACLGraph 模型的精度。

ACLGraph 图结构与数据流

完整的图结构如下(其中allGather为 RDMA 后端实现):

add → allGather → allGather → add

具体数据流(对应 rdma_aclgraph_demo_kernel.cpp 与 main.cpp):

  1. 每个 PE 生成一组长度为TRANS_SIZE(16 个 int32)的本地输入input[i] = pe_id + 10,通过aclrtMemcpy写入对称内存ptrb_ptr的本地分片;
  2. 第一次addrun_vector_add<int>ptradd_ptr做向量加,结果写回temp_ptr,再经aclrtMemcpyAsync拷回ptr
  3. 两次allgather_demo:分别对ptrb_ptr执行 RDMA AllGather,将各 PE 的数据片汇聚成完整数组;
  4. 第二次add:对两个 AllGather 的输出ptrb_ptr求和,得到c_ptr
  5. 通过aclmdlRICaptureBegin/End将上述整条序列捕获为 ACLGraph 模型model,之后每轮循环仅执行aclmdlRIExecuteAsync(model, stream)重放;
  6. 每一轮结束后,把c_ptr拷回 Host,逐元素与期望值(10 + i) * (3 + zz)zz为循环轮次)比对,任一元素不等即报错退出。

循环共执行LOOP_TIMES = 3轮:第 0 轮负责图捕获,第 1、2 轮为图重放。通过每轮校验第二次add的输出,即可判断 AllGather 算子在 ACLGraph 中是否工作正常。

设备端内核的同步实现

设备端内核device_all_gather_test(见 rdma_aclgraph_demo_kernel.cpp)直观展示了"屏障—写入—屏障"的完整模式:

aclshmemx_roce_barrier_all(); // 图执行阶段同步:确保所有 PE 都到达该点 for (int i = 0; i < pe_size; i++) { if (i == my_rank) { continue; } aclshmemx_roce_put_nbi( gva + message_length * my_rank, gva + message_length * my_rank, (__ubuf__ uint8_t*)ubLocal.GetPhyAddr(), message_length, i, 0); } aclshmemx_roce_barrier_all(); // 数据写入完成同步:确保所有 PUT 均已被远端接收
  • 第一次aclshmemx_roce_barrier_all()保证进入数据交换前,所有 PE 的图都已经执行到 AllGather 阶段,这是"精度正常"的前提;
  • 中间的aclshmemx_roce_put_nbi将自己对称内存分片广播给其它 PE;
  • 第二次aclshmemx_roce_barrier_all()保证所有 PUT 完成后才继续后续add,避免读到未完成写入的远端数据。

aclshmemx_roce_barrier_all在设备侧声明见 include/device/gm2gm/engine/shmem_device_rdma.h,其实现位于 src/device/gm2gm/engine/shmem_device_rdma.hpp,并同样被 rdma_demo、rdma_aggregate_demo、rdma_sync_barrier_demo 及多个单测内核(如 tests/unittest/device/sync/rdma_sync_barrier_kernel.cpp)复用,可见该屏障是 ROCE 后端示例与测试的公共原语。

环境要求

rdma_aclgraph_demo的环境要求与 rdma_demo 一致,主要包括:

  • RDMA 环境可用:RDMA 网卡及驱动已正确安装并配置。
  • Ascend950 平台需 CANN 9.1.0 包:RDMA 相关样例在 Ascend950 平台上要求 CANN 9.1.0,其它版本目前不支持。

检查 RDMA 环境

A2/A3 平台:使用hccn_tool检查网卡 IP 与网络健康状态(数字 7 按实际设备数调整):

for i in {0..7}; do hccn_tool -i $i -ip -g; done for i in {0..7}; do hccn_tool -i $i -net_health -g; done

Ascend950 平台:使用ibv_devinfo检查 RDMA 设备:

  • XSCALE 网卡:ibv_devinfo | grep xscale
  • HNS 1825 网卡:ibv_devinfo | grep hrn

注意:HNS 1825 网卡同端口通信时,若交换机未开启端口桥(port bridge),RDMA 收发可能失败,相关配置可参考 调试手册 - 同端口通信需开启端口桥。

IBV_EXTEND_DRIVERS 环境变量(Ascend950 必设)

Ascend950 平台运行前需将IBV_EXTEND_DRIVERS设置为对应网卡的用户态 Verbs provider 插件库路径:

  • XSCALE 网卡

    export IBV_EXTEND_DRIVERS=<path_to_libxscale_nda.so>
  • HNS 1825 网卡

    export IBV_EXTEND_DRIVERS=<path_to_libhrn5-rdmav34.so>

libxscale_nda.solibhrn5-rdmav34.so由对应网卡驱动安装包提供(而非 SHMEM 项目构建产物)。驱动安装后可用find / -name "libhrn5-rdmav34.so"find / -name "libxscale_nda.so"定位库路径并设置。IBV_EXTEND_DRIVERS是 libibverbs 的环境变量,用于加载默认搜索路径之外的 Verbs provider 插件。

编译构建

shmem/根目录按平台选择编译参数(RDMA 后端参数详见 编译与构建指南 - RDMA 参数使用说明):

# A2/A3 平台 bash scripts/build.sh -enable_rdma -examples # Ascend950 + XSCALE 网卡 bash scripts/build.sh -soc_type Ascend950 -enable_rdma -rdma_backend XSCALE -examples # Ascend950 + HNS 1825 网卡 bash scripts/build.sh -soc_type Ascend950 -enable_rdma -rdma_backend HNS_1825 -examples

构建目标由 examples/rdma_aclgraph_demo/CMakeLists.txt 中的aclshmem_add_collective_example(rdma_aclgraph_demo)声明,产物为./build/bin/rdma_aclgraph_demo

运行方式

方式一:直接运行脚本(单机双卡)

shmem/examples/rdma_aclgraph_demo目录下执行:

bash run.sh # 单机双卡用例

run.sh 的行为要点:

  • 自动将PROJECT_ROOT指向仓库根目录,并把${PROJECT_ROOT}/build/lib加入LD_LIBRARY_PATH
  • 清理旧输出目录后,通过msprof --application=...分别启动 PE 0 与 PE 1 两个进程(rdma_aclgraph_demo 2 0 tcp://127.0.0.1:8899 2 0 0rdma_aclgraph_demo 2 1 tcp://127.0.0.1:8899 2 0 0),并等待全部进程结束;
  • 任一进程返回非 0 时脚本以非 0 退出,便于在 CI 中判断样例是否通过。

注:Ascend950 平台必须预先设置IBV_EXTEND_DRIVERS环境变量(见上文)。

方式二:手动启动(跨机多卡)

样例支持任意规模扩展。以双机 8 卡为例:总 PE 数n_pes=8,每机启动 4 个 PE(g_npus=4);第 1 机 PE 号为 0–3(f_pe=0),第 2 机 PE 号为 4–7(f_pe=4)。将run.sh中对应的启动命令替换为如下形式(注意第 2 机命令行中的f_pe从 0 改为 4,并将tcp://{IP}:{Port}统一填 PE0 所在主机地址):

# Server 1 pids=() msprof --application="./build/bin/rdma_aclgraph_demo 8 0 tcp://{IP address of server 1}:{Port number} 4 0 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 0 pid=$! pids+=("$pid") msprof --application="./build/bin/rdma_aclgraph_demo 8 1 tcp://{IP address of server 1}:{Port number} 4 0 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 1 pid=$! pids+=("$pid") msprof --application="./build/bin/rdma_aclgraph_demo 8 2 tcp://{IP address of server 1}:{Port number} 4 0 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 2 pid=$! pids+=("$pid") msprof --application="./build/bin/rdma_aclgraph_demo 8 3 tcp://{IP address of server 1}:{Port number} 4 0 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 3 pid=$! pids+=("$pid") # Server 2 pids=() msprof --application="./build/bin/rdma_aclgraph_demo 8 4 tcp://{IP address of server 1}:{Port number} 4 4 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 4 pid=$! pids+=("$pid") msprof --application="./build/bin/rdma_aclgraph_demo 8 5 tcp://{IP address of server 1}:{Port number} 4 4 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 5 pid=$! pids+=("$pid") msprof --application="./build/bin/rdma_aclgraph_demo 8 6 tcp://{IP address of server 1}:{Port number} 4 4 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 6 pid=$! pids+=("$pid") msprof --application="./build/bin/rdma_aclgraph_demo 8 7 tcp://{IP address of server 1}:{Port number} 4 4 0" --output=${PROJECT_ROOT}/examples/rdma_aclgraph_demo/output/ & # pe 7 pid=$! pids+=("$pid")

提示:跨机测试时,tcp://中的 IP 必须为 PE0 所在主机的 IP;在容器中执行跨机测试,启动容器需指定--net=host模式。

命令行参数说明

程序入口 main.cpp 要求恰好 6 个参数,格式为:

./rdma_aclgraph_demo <n_pes> <pe_id> <ipport> <g_npus> <f_pe> <f_npu>
参数含义说明
n_pes全局 PE 数量参与本次通信的总进程数,如单机双卡为 2、双机 8 卡为 8
pe_id当前 PE 号全局唯一,取值[0, n_pes)
ipportSHMEM 初始化地址格式tcp://<IP>:<端口号>;跨机测试时 IP 须为 PE0 所在主机的 IP
g_npus当前机器上启动的 NPU 数量用于pe_id % g_npus + f_npu计算本进程使用的设备号
f_pe当前机器使用的第一个 PE 号第 1 机通常为 0,第 2 机为 4
f_npu当前机器使用的第一个 NPU 卡号物理设备起始偏移,通常为 0

以双机 8 卡为例:第 1 机的 4 个进程参数为8 0..3 tcp://ip1:port 4 0 0,第 2 机的 4 个进程参数为8 4..7 tcp://ip1:port 4 4 0

初始化与内存分配要点

从源码可进一步确认样例内部的关键初始化步骤(见 main.cpp):

  1. ACL 环境初始化aclInitaclrtSetDevice(pe_id % g_npus + f_npu)aclrtCreateStream,完成设备绑定与 Stream 创建;
  2. SHMEM 初始化:填充aclshmemx_init_attr_t attributes(含pe_idn_peslocal_mem_size = 1 GBipport),并设置attributes.option_attr.data_op_engine_type = ACLSHMEM_DATA_OP_ROCE以指定 ROCE 数据通路,随后调用aclshmemx_init_attr(ACLSHMEMX_INIT_WITH_DEFAULT, &attributes)
  3. 对称内存分配:通过aclshmem_malloc(SYMMETRIC_MEM_SIZE)(1024 字节)分配 AllGather 所需的对称内存分片,远端进程可通过对称地址直接访问;
  4. 退出流程aclshmem_free/aclrtFree释放资源 →aclmdlRIDestroy销毁模型 →aclshmem_finalizeaclrtDestroyStream/aclrtResetDevice/aclFinalize

结果验证与退出码

  • 每轮图执行后,Host 端比对y_host[TRANS_SIZE * i + j]与期望值(10 + i) * (3 + zz),任一不一致即打印ERROR loop: ...并将status置为-1
  • 全部通过则打印check transport result success, relative pe=<pe_id>
  • main以状态码返回:成功输出[SUCCESS] demo run success in relative pe <pe_id>,失败输出[FAILED] demo run failed in relative pe <pe_id>并以EXIT_FAILURE退出,供上层脚本判断。

延伸阅读

  • 非 RDMA 版本的 ACLGraph 样例(AscendC 通路 + AllGather 图捕获):examples/aclgraph_demo,其内核 aclgraph_demo_kernel.cpp 展示了通过aclshmemx_signal_op/aclshmem_signal_wait_until完成同步的另一种实现,可与本文的 ROCE 屏障方案对比;
  • RDMA 基础样例及完整环境准备:examples/rdma_demo;
  • ROCE 后端编译参数与平台差异:docs/compilation_build_guide_en.md;
  • 同端口通信端口桥等常见问题:docs/debug/Troubleshooting_FAQs_en.md。

【免费下载链接】shmemCANN SHMEM 是面向昇腾平台的多机多卡内存通信库,基于OpenSHMEM 标准协议,实现跨设备的高效内存访问与数据同步。项目地址: https://gitcode.com/cann/shmem

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/19 2:48:17

CANN GroupNorm 使用指南:分组标准化一步讲清原理与用法

CANN GroupNorm 使用指南&#xff1a;分组标准化一步讲清原理与用法 【免费下载链接】BabelDOC Yet Another Document Translator 项目地址: https://gitcode.com/GitHub_Trending/ba/BabelDOC CANN GroupNorm 是昇腾 AI Core 提供的分组标准化算子&#xff1a;它沿通道…

作者头像 李华
网站建设 2026/9/19 2:47:39

灰狼优化算法结合GRU:时序预测超参数自动搜索实战

做时间序列预测的人&#xff0c;应该都有过这种体验&#xff1a;明明GRU模型结构不复杂&#xff0c;可换一组数据、改一个窗口长度&#xff0c;效果就天差地别。更气人的是&#xff0c;GRU的超参数之间并不是独立起作用的&#xff0c;学习率、隐藏层节点数、层数、时间步长、正…

作者头像 李华
网站建设 2026/9/19 2:45:42

基于二手分析仪器改造的PMT荧光检测电路设计与信号链路实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/19 2:43:42

AI写作工具的正确用法:从代写到教练,掌握写作方法论

写作这行当&#xff0c;说穿了就两条路&#xff1a;要么替人写&#xff0c;要么教人写。替人写是体力活&#xff0c;写一篇没一篇&#xff0c;读者拿走了鱼&#xff0c;下次饿了还得来找你&#xff1b;教人写是手艺活&#xff0c;把拆解、构思、打磨的门道交到对方手里&#xf…

作者头像 李华