十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CANN Runtime 跨进程物理内存共享实战:关闭进程白名单校验的 Device 内双进程共享方案(基于 8_physical_memory_sharing_withoutpid 样例)

CANN Runtime 跨进程物理内存共享实战:关闭进程白名单校验的 Device 内双进程共享方案(基于 8_physical_memory_sharing_withoutpid 样例) CANN Runtime 跨进程物理内存共享实战关闭进程白名单校验的 Device 内双进程共享方案基于 8_physical_memory_sharing_withoutpid 样例【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime导读本文围绕 CANN runtime 仓库中 8_physical_memory_sharing_withoutpid 样例 展开讲解如何在同一个 Device 上的两个独立进程之间共享物理内存且共享时关闭进程白名单PID whitelist校验。读者将掌握从aclrtMallocPhysical申请物理内存、导出可共享句柄、跨进程导入句柄、映射虚拟内存并读取数据的完整调用链理解虚拟内存/物理内存分离管理模型以及ACL_RT_VMM_EXPORT_FLAG_DISABLE_PID_VALIDATION这一标志的语义与适用场景。一、样例背景与核心思想在多进程编程中两个进程虽然各自拥有独立的地址空间但可以通过共享同一块物理内存来高效交换数据从而避免进程间数据拷贝的开销。CANN Runtime 为此提供了一套物理内存句柄 虚拟内存映射的内存管理原语一个进程申请物理内存并获得句柄handle把句柄导出为可共享句柄shareable handle传递给另一个进程另一个进程导入该句柄后在自己的地址空间中预留并映射一段虚拟内存即可访问同一块物理内存。本样例8_physical_memory_sharing_withoutpid演示的正是这一过程其特殊之处在于两个进程运行在**同一个 Devicedevice 0**上导出共享句柄时使用ACL_RT_VMM_EXPORT_FLAG_DISABLE_PID_VALIDATION标志关闭进程白名单校验即不限定哪些进程可以使用该共享句柄进程间通过file/目录下的临时文件交换共享句柄与完成标志不依赖任何第三方案例框架。样例由两个可执行程序组成进程 Aproc_a.cpp负责申请物理内存、写入数据、导出句柄进程 Bproc_b.cpp负责导入句柄、映射虚拟内存、读取并校验数据。二、样例目录结构与进程职责example/1_basic_features/memory/8_physical_memory_sharing_withoutpid/ ├── CMakeLists.txt # 构建脚本编译 proc_a 与 proc_b ├── README.md # 中文说明 ├── README_en.md # 英文说明 ├── proc_a.cpp # 进程 A分配物理内存 → 写数据 → 导出共享句柄 ├── proc_b.cpp # 进程 B导入共享句柄 → 映射 → 读数据 └── run.sh # 编译并同时启动两个进程自动校验结果从 CMakeLists.txt 可以看出proc_a链接了ascendcl与自定义 AscendC 算子库kernels由 write_read_value.cpp 编译而来进程 A 需要它向 Device 内存写入数值而proc_b仅链接ascendcl只做读取。两个进程的分工与合作关系如下表所示步骤进程 Aproducer进程 Bconsumer1初始化、设置 Device、创建 Stream初始化、设置 Device、创建 Stream2申请物理内存导出共享句柄—3把共享句柄写入file/handle.bin从file/handle.bin读取共享句柄并导入4向映射的虚拟地址写入值 123将 Device 数据拷贝到 Host读到值 1235等待完成标志写入完成标志file/flag.bin6解除映射、释放内存、收尾解除映射、释放内存、收尾三、环境准备与编译运行3.1 前提条件已安装 CANN 软件包的环境运行环境满足样例支持的产品要求见本文最后一节。3.2 编译与运行步骤切换到样例目录cd ${git_clone_path}/example/1_basic_features/memory/8_physical_memory_sharing_withoutpid设置环境变量# 将 ${install_root} 替换为 CANN 安装根目录默认安装在 /usr/local/Ascend source ${install_root}/cann/set_env.sh # 自动识别 SOC_VERSION 与 ASCENDC_CMAKE_DIR # SOC_VERSIONAscend AI 处理器型号如 Ascend910_9362、Ascend910B2 等 # ASCENDC_CMAKE_DIR样例涉及调用 AscendC 算子需配置 AscendC 编译器 ascendc.cmake 路径 # 例如 /usr/local/Ascend/cann/x86_64-linux/tikcpp/ascendc_kernel_cmake source ${git_clone_path}/example/set_sample_env.sh其中 set_sample_env.sh 会自动识别SOC_VERSION和ASCENDC_CMAKE_DIR避免手工填写。执行样例bash run.sh3.3 run.sh 内部机制run.sh 完成的工作可以拆解为以下几步环境检查校验ASCEND_HOME_PATH是否已设置即是否已 source CANN 的set_env.sh并加载${ASCEND_CANN_PATH}/bin/setenv.bash编译创建build/目录通过cmake -B build -DASCEND_CANN_PACKAGE_PATH...配置项目并执行cmake --build build -j与cmake --install build创建临时文件目录清空并重建file/目录用于进程间交换句柄与标志并行启动两个进程proc_a与proc_b同时以后台方式启动输出分别通过tee保存到output_msg_proc_a.txt与output_msg_proc_b.txt自动校验结果分别从两份输出中提取Source data:与Destination data:的数值并比较若相等则打印[SUCCESS]否则打印[FAILURE]并返回非零退出码。注意样例运行会产生build/、file/、output_msg_*.txt、out/等目录与文件属于运行产物不属于源码本身。四、进程 A物理内存分配、写入与句柄导出进程 A 的完整流程位于 proc_a.cpp核心步骤为初始化 → 查询申请粒度 → 分配物理内存 → 预留虚拟内存 → 映射 → 设置访问权限 → 写数据 → 导出句柄 → 等待标志 → 释放资源。4.1 初始化与 Stream 创建aclInit(nullptr); int32_t deviceId 0; aclrtSetDevice(deviceId); aclrtStream stream nullptr; aclrtCreateStream(stream);aclInit完成运行时的初始化配置aclrtSetDevice指定参与计算的 Device本例固定为 0aclrtCreateStream创建用于下发任务的 Stream。4.2 查询内存申请粒度并分配物理内存const size_t dataSize 1024 * sizeof(float); aclrtPhysicalMemProp prop {}; prop.handleType ACL_MEM_HANDLE_TYPE_NONE; prop.allocationType ACL_MEM_ALLOCATION_TYPE_PINNED; prop.location.type ACL_MEM_LOCATION_TYPE_DEVICE; prop.location.id 0; prop.memAttr ACL_HBM_MEM_NORMAL; size_t granularity 0UL; CHECK_ERROR(aclrtMemGetAllocationGranularity(prop, ACL_RT_MEM_ALLOC_GRANULARITY_MINIMUM, granularity)); size_t alignedSize ((dataSize granularity - 1U) / granularity) * granularity; aclrtDrvMemHandle handle nullptr; CHECK_ERROR(aclrtMallocPhysical(handle, alignedSize, prop, 0));这里体现了 CANN Runtime 物理内存管理的关键约束物理内存必须按申请粒度对齐。代码先用aclrtMemGetAllocationGranularity查询最小粒度ACL_RT_MEM_ALLOC_GRANULARITY_MINIMUM再向上取整得到alignedSize最后调用aclrtMallocPhysical完成分配。从 acl_rt.h 的接口注释可知该接口返回物理内存句柄aclrtDrvMemHandle后续对该内存的所有操作都通过该句柄进行flags参数当前未使用、必须传 0。aclrtPhysicalMemProp中的关键字段含义如下字段样例取值含义handleTypeACL_MEM_HANDLE_TYPE_NONE内存句柄类型导出/导入接口要求该值为NONEallocationTypeACL_MEM_ALLOCATION_TYPE_PINNED固定页锁定分配类型location.typeACL_MEM_LOCATION_TYPE_DEVICE物理内存位于 Device 侧location.id0Device 编号memAttrACL_HBM_MEM_NORMAL使用 HBM 普通内存属性4.3 预留虚拟内存、映射并设置访问权限物理内存本身不能直接被 CPU 或算子访问需要先预留一段虚拟地址空间再建立虚拟地址 ↔ 物理句柄的映射最后显式设置访问权限void* virPtr; CHECK_ERROR(aclrtReserveMemAddress(virPtr, granularity, 0, nullptr, 0)); CHECK_ERROR(aclrtMapMem(virPtr, granularity, 0, handle, 0)); aclrtMemAccessDesc accessDesc {}; accessDesc.flags ACL_RT_MEM_ACCESS_FLAGS_READWRITE; accessDesc.location.type ACL_MEM_LOCATION_TYPE_DEVICE; accessDesc.location.id deviceId; CHECK_ERROR(aclrtMemSetAccess(virPtr, granularity, accessDesc, 1));三步对应的接口语义依据 acl_rt.h 与 acl_rt.haclrtReserveMemAddress预留虚拟地址范围expectPtr期望固定起始地址必须为nullptr由系统分配地址aclrtMapMem把预留的虚拟地址范围与物理内存句柄绑定offset表示从句柄对应内存的起始偏移处开始映射flags必须为 0aclrtMemSetAccess为映射后的虚拟地址设置访问权限读/写因为aclrtMapMem本身不授予任何访问权限必须显式设置后才能访问该段内存。4.4 写入数据并导出共享句柄constexpr uint32_t blockDim 1; int writeValue 123; WriteDo(blockDim, stream, (int*)virPtr, writeValue); uint64_t shareableHandle 0ULL; CHECK_ERROR(aclrtMemExportToShareableHandle(handle, ACL_MEM_HANDLE_TYPE_NONE, 1, shareableHandle));进程 A 通过自定义的 AscendC 算子WriteDo见 write_read_value.cpp在 Stream 上把整数值 123 写入映射的虚拟地址。随后调用aclrtMemExportToShareableHandle导出共享句柄。依据 acl_rt.h 的接口说明其参数为handle由aclrtMallocPhysical创建的内存句柄handleType保留参数必须为ACL_MEM_HANDLE_TYPE_NONEflags合法的取值包括ACL_RT_VMM_EXPORT_FLAG_DEFAULT默认行为与ACL_RT_VMM_EXPORT_FLAG_DISABLE_PID_VALIDATION关闭 PID 白名单校验。本样例传入数值 1即关闭白名单校验——这正是目录名withoutpid的含义shareableHandle输出参数得到可跨进程共享的句柄值。4.5 通过文件交换句柄与完成标志memory::WriteFile(file/handle.bin, file/handle.bin.done, shareableHandle, sizeof(shareableHandle)); int32_t flag 0; memory::ReadFile(file/flag.bin, file/flag.bin.done, flag, sizeof(flag));进程间通过file/目录下的临时文件交换信息文件读写封装见 mem_utils.h实现在 file_ops.cpp。WriteFile/ReadFile均带一个.done哨兵文件用于标识数据文件已写完/已可读从而在无共享内存的前提下实现进程间握手同步。4.6 资源释放CHECK_ERROR(aclrtUnmapMem(virPtr)); CHECK_ERROR(aclrtReleaseMemAddress(virPtr)); CHECK_ERROR(aclrtFreePhysical(handle)); aclrtDestroyStreamForce(stream); aclrtResetDeviceForce(deviceId); aclFinalize();释放顺序与分配顺序严格相反先解除映射aclrtUnmapMem再释放预留的虚拟地址aclrtReleaseMemAddress最后释放物理内存句柄aclrtFreePhysical。aclrtDestroyStreamForce强制销毁 Stream 并丢弃所有任务aclrtResetDeviceForce强制复位 Device 并回收 Device 资源最后aclFinalize完成去初始化。五、进程 B句柄导入、映射与数据读取进程 B 的流程位于 proc_b.cpp它与进程 A 在物理内存的获得方式上不同不再自行分配而是导入进程 A 导出的共享句柄。5.1 导入共享句柄uint64_t shareableHandle 0ULL; aclrtDrvMemHandle handle nullptr; memory::ReadFile(file/handle.bin, file/handle.bin.done, shareableHandle, sizeof(shareableHandle)); CHECK_ERROR(aclrtMemImportFromShareableHandle(shareableHandle, deviceId, handle));aclrtMemImportFromShareableHandle依据 acl_rt.h 的说明输入共享句柄与deviceId用于在指定 Device 上生成句柄输出当前进程可用的物理内存句柄handle。此后进程 B 拿到的handle与进程 A 的handle指向同一块物理内存。5.2 映射、设置访问权限并读取数据进程 B 随后执行与进程 A 相同的查询粒度 → 预留虚拟内存 → 映射 → 设置访问权限序列然后直接把 Device 数据拷贝到 HostCHECK_ERROR(aclrtMemcpy(hostPtrA, granularity, virPtr, granularity, ACL_MEMCPY_DEVICE_TO_HOST)); int readValue *hostPtrA; INFO_LOG(Destination data: %d, readValue);Host 侧内存通过aclrtMallocHost申请读取完毕后由aclrtFreeHost释放。由于进程 A 已向该物理内存写入 123进程 B 读到的readValue必然也是 123从而验证了共享的有效性。5.3 通知完成并释放资源int32_t flag 1; memory::WriteFile(file/flag.bin, file/flag.bin.done, flag, sizeof(flag));进程 B 写完成标志通知进程 A 可以释放资源随后以与进程 A 相同的逆序释放映射、虚拟地址与物理句柄并释放 Host 内存、销毁 Stream、复位 Device、调用aclFinalize。六、关键 API 全景与调用关系本样例涉及的 CANN Runtime API 及其在样例中的职责可汇总如下类别API作用样例调用位置初始化aclInit/aclFinalize运行时初始化 / 去初始化两进程均调用Device 管理aclrtSetDevice指定运算 Device进程 A进程 B 封装在memory::InitDeviceAndCreateStream中Device 管理aclrtResetDeviceForce强制复位 Device回收资源两进程收尾Stream 管理aclrtCreateStream创建 Stream进程 A进程 B 在初始化封装中Stream 管理aclrtDestroyStreamForce强制销毁 Stream两进程收尾内存管理aclrtMemGetAllocationGranularity查询物理内存申请粒度两进程内存管理aclrtMallocPhysical/aclrtFreePhysical分配 / 释放物理内存句柄进程 A 分配、B 释放导入的句柄内存管理aclrtReserveMemAddress/aclrtReleaseMemAddress预留 / 释放虚拟地址两进程内存管理aclrtMapMem/aclrtUnmapMem建立 / 解除虚拟-物理映射两进程内存管理aclrtMemSetAccess设置映射内存访问权限两进程内存管理aclrtMemExportToShareableHandle导出可共享句柄可关闭 PID 白名单校验进程 A内存管理aclrtMemImportFromShareableHandle导入共享句柄为本地物理句柄进程 B内存管理aclrtMallocHost/aclrtFreeHost申请 / 释放 Host 内存进程 B 读取数据数据传输aclrtMemcpy内存拷贝D2H进程 B值得强调的是样例同时展示了接口的成对使用约束aclrtReserveMemAddress与aclrtReleaseMemAddress配对、aclrtMapMem与aclrtUnmapMem配对、aclrtMallocPhysical与aclrtFreePhysical配对、aclrtMallocHost与aclrtFreeHost配对且释放顺序必须与分配顺序相反否则可能导致资源泄漏或接口返回错误。七、进程白名单校验机制与withoutpid的意义CANN Runtime 的物理内存共享默认带有进程白名单PID whitelist校验机制从 acl_rt.h 可以看到系统提供设置进程白名单的接口只有白名单中配置的进程才能使用导出的共享句柄从而限定共享范围、防止未经授权的进程访问共享内存。而本样例特意通过ACL_RT_VMM_EXPORT_FLAG_DISABLE_PID_VALIDATION标志关闭了该校验见 4.4 节对应目录名withoutpid。这种做法的适用前提与注意点适用场景在可信环境内的快速共享例如同机多进程协作、共享数据传递场景省去维护白名单列表的开销安全提示关闭白名单校验后持有该共享句柄的进程均可访问对应物理内存因此在多租户或不可信环境中应使用默认的ACL_RT_VMM_EXPORT_FLAG_DEFAULT行为并配置白名单。如果读者需要带白名单校验的版本可以对照参考仓库中同目录族的 7_physical_memory_sharing_withpid 样例进行对比学习。八、运行结果与自动验证8.1 进程 A 的典型输出[INFO] Process A: allocate physical memory successfully [INFO] Process A: reserve virtual memory successfully [INFO] Process A: export a shareable handle successfully, shareable handle ... Source data: 123 [INFO] Process A: receive the completion signal from Process B, completion signal 1 [INFO] Process A: release the virtual and physical memory successfully8.2 进程 B 的典型输出[INFO] Process B: get a shareable handle successfully, shareable handle ... [INFO] Process B: map virtual memory address to physical memory handle [INFO] Process B: copy memory from device address 0x... to host address 0x... Destination data: 123 [INFO] Process B: complete the physical memory sharing [INFO] Process B: release the virtual and physical memory successfully8.3 run.sh 的自动校验逻辑run.sh 会从两份进程输出中提取Source data与Destination data的数值并比较source_value$(awk -F: /Source data:/ {gsub(/^ | $/, , $2); print $2; exit} ${file_path_proc_a}) destination_value$(awk -F: /Destination data:/ {gsub(/^ | $/, , $2); print $2; exit} ${file_path_proc_b})若两值相等打印[SUCCESS] Memory sharing successfully. Values at source and destination are equal: 123若任一进程退出码非 0 或数值不一致则打印[FAILURE]并以非零退出码结束。这一设计使得样例可以一键自检共享是否成功完全取决于进程 B 能否读到进程 A 写入的值即物理内存共享是否真实生效。九、产品支持情况与使用前提本样例支持的硬件产品如下与 README_en.md 保持一致产品是否支持Ascend 950PR / Ascend 950DT是Atlas A3 训练系列产品 / Atlas A3 推理系列产品是Atlas A2 训练系列产品 / Atlas A2 推理系列产品是使用前提总结环境已安装对应版本的 CANN 软件并已执行source ${install_root}/cann/set_env.sh需按 3.2 节配置SOC_VERSION与ASCENDC_CMAKE_DIR可借助 set_sample_env.sh 自动识别样例默认使用 Device 0多卡场景如需调整可修改proc_a.cpp与proc_b.cpp中的deviceId该内存共享为同 Device 内共享跨 Device 或跨服务器的物理内存共享属于另一类使用场景可参考仓库中 7_physical_memory_sharing_withpid、12_cross_server_physical_memory_sharing_withoutpid 等样例。十、小结通过8_physical_memory_sharing_withoutpid样例可以完整掌握 CANN Runtime 物理内存共享的编程模型物理内存与虚拟内存分离管理aclrtMallocPhysicalaclrtReserveMemAddressaclrtMapMemaclrtMemSetAccess、句柄的导出与导入aclrtMemExportToShareableHandleaclrtMemImportFromShareableHandle、进程白名单校验的开与关ACL_RT_VMM_EXPORT_FLAG_DISABLE_PID_VALIDATION以及资源按逆序释放的规范。这套原语为多进程共享 Device 内存、减少数据拷贝的高效协作提供了底层支撑也建议读者结合 11-07_IPC_memory_sharing.md 与 07_inter_process_communication.md 进一步阅读更完整的接口说明与设计背景。【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表