CANN SHMEM 中基于 ACLGraph 的 RDMA AllGather 同步机制与运行实战:rdma_aclgraph_demo 全解析 📅 发布时间:2026/9/19 2:50:11 👁 浏览次数: CANN SHMEM 中基于 ACLGraph 的 RDMA AllGather 同步机制与运行实战rdma_aclgraph_demo 全解析【免费下载链接】shmemCANN SHMEM 是面向昇腾平台的多机多卡内存通信库基于OpenSHMEM 标准协议实现跨设备的高效内存访问与数据同步。项目地址: https://gitcode.com/cann/shmemCANN SHMEM 是面向昇腾平台的多机多卡内存通信库基于 OpenSHMEM 标准协议实现跨设备的高效内存访问与数据同步。本文以仓库中的 examples/rdma_aclgraph_demo 为对象剖析在 ACLGraphAscend 图执行模型中嵌入 RDMA AllGather 通信算子的关键技术——即通过aclshmemx_roce_barrier_all屏障接口解决AllGather 仅发出 Write 操作、无法保证图执行到相同阶段的同步问题。读完本文你将掌握该样例的 ACLGraph 图结构设计、环境准备、单机/跨机运行方式、命令行参数含义以及从源码层面理解其同步原理与精度校验逻辑。样例场景为什么 ACLGraph 中的 AllGather 需要显式同步rdma_aclgraph_demo的目标是在一张 ACLGraph 图中编排add allGather allGather add的计算序列并验证在 RDMAROCE传输下 AllGather 算子嵌入图执行后的功能正确性。该场景的核心难点在于RDMA AllGather 只发送 Write 操作。与传统的读-改-写通信方式不同aclshmemx_roce_put_nbi这类单边 PUT 操作将数据直接写入远端对称内存不会主动通知对端写入已完成。因此如果没有额外同步所有 PE 上的图执行进度可能不一致某些 PE 已经开始消费数据而另一些 PE 的数据尚未到达导致 AllGather 结果错误进而使 ACLGraphmodel的精度异常。解决办法是在 rdma allgather 算子中显式加入 aclshmemx_roce_barrier_all 接口进行全量屏障同步确保所有 PE 上的图均已执行到相应阶段后再进行数据交换从而保证 ACLGraph 模型的精度。ACLGraph 图结构与数据流完整的图结构如下其中allGather为 RDMA 后端实现add → allGather → allGather → add具体数据流对应 rdma_aclgraph_demo_kernel.cpp 与 main.cpp每个 PE 生成一组长度为TRANS_SIZE16 个 int32的本地输入input[i] pe_id 10通过aclrtMemcpy写入对称内存ptr和b_ptr的本地分片第一次addrun_vector_addint对ptr与add_ptr做向量加结果写回temp_ptr再经aclrtMemcpyAsync拷回ptr两次allgather_demo分别对ptr与b_ptr执行 RDMA AllGather将各 PE 的数据片汇聚成完整数组第二次add对两个 AllGather 的输出ptr与b_ptr求和得到c_ptr通过aclmdlRICaptureBegin/End将上述整条序列捕获为 ACLGraph 模型model之后每轮循环仅执行aclmdlRIExecuteAsync(model, stream)重放每一轮结束后把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; doneAscend950 平台使用ibv_devinfo检查 RDMA 设备XSCALE 网卡ibv_devinfo | grep xscaleHNS 1825 网卡ibv_devinfo | grep hrn注意HNS 1825 网卡同端口通信时若交换机未开启端口桥port bridgeRDMA 收发可能失败相关配置可参考 调试手册 - 同端口通信需开启端口桥。IBV_EXTEND_DRIVERS 环境变量Ascend950 必设Ascend950 平台运行前需将IBV_EXTEND_DRIVERS设置为对应网卡的用户态 Verbs provider 插件库路径XSCALE 网卡export IBV_EXTEND_DRIVERSpath_to_libxscale_nda.soHNS 1825 网卡export IBV_EXTEND_DRIVERSpath_to_libhrn5-rdmav34.solibxscale_nda.so与libhrn5-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 0与rdma_aclgraph_demo 2 1 tcp://127.0.0.1:8899 2 0 0并等待全部进程结束任一进程返回非 0 时脚本以非 0 退出便于在 CI 中判断样例是否通过。注Ascend950 平台必须预先设置IBV_EXTEND_DRIVERS环境变量见上文。方式二手动启动跨机多卡样例支持任意规模扩展。以双机 8 卡为例总 PE 数n_pes8每机启动 4 个 PEg_npus4第 1 机 PE 号为 0–3f_pe0第 2 机 PE 号为 4–7f_pe4。将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在容器中执行跨机测试启动容器需指定--nethost模式。命令行参数说明程序入口 main.cpp 要求恰好 6 个参数格式为./rdma_aclgraph_demo n_pes pe_id ipport g_npus f_pe f_npu参数含义说明n_pes全局 PE 数量参与本次通信的总进程数如单机双卡为 2、双机 8 卡为 8pe_id当前 PE 号全局唯一取值[0, n_pes)ipportSHMEM 初始化地址格式tcp://IP:端口号跨机测试时 IP 须为 PE0 所在主机的 IPg_npus当前机器上启动的 NPU 数量用于pe_id % g_npus f_npu计算本进程使用的设备号f_pe当前机器使用的第一个 PE 号第 1 机通常为 0第 2 机为 4f_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.cppACL 环境初始化aclInit→aclrtSetDevice(pe_id % g_npus f_npu)→aclrtCreateStream完成设备绑定与 Stream 创建SHMEM 初始化填充aclshmemx_init_attr_t attributes含pe_id、n_pes、local_mem_size 1 GB、ipport并设置attributes.option_attr.data_op_engine_type ACLSHMEM_DATA_OP_ROCE以指定 ROCE 数据通路随后调用aclshmemx_init_attr(ACLSHMEMX_INIT_WITH_DEFAULT, attributes)对称内存分配通过aclshmem_malloc(SYMMETRIC_MEM_SIZE)1024 字节分配 AllGather 所需的对称内存分片远端进程可通过对称地址直接访问退出流程aclshmem_free/aclrtFree释放资源 →aclmdlRIDestroy销毁模型 →aclshmem_finalize→aclrtDestroyStream/aclrtResetDevice/aclFinalize。结果验证与退出码每轮图执行后Host 端比对y_host[TRANS_SIZE * i j]与期望值(10 i) * (3 zz)任一不一致即打印ERROR loop: ...并将status置为-1全部通过则打印check transport result success, relative pepe_idmain以状态码返回成功输出[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_demoROCE 后端编译参数与平台差异docs/compilation_build_guide_en.md同端口通信端口桥等常见问题docs/debug/Troubleshooting_FAQs_en.md。【免费下载链接】shmemCANN SHMEM 是面向昇腾平台的多机多卡内存通信库基于OpenSHMEM 标准协议实现跨设备的高效内存访问与数据同步。项目地址: https://gitcode.com/cann/shmem创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考