ARTICLE DETAIL

资讯详情

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

CANN Runtime 实战:同 Device 双进程 IPC 共享 Device 内存(关闭进程白名单校验)

CANN Runtime 实战:同 Device 双进程 IPC 共享 Device 内存(关闭进程白名单校验) CANN Runtime 实战同 Device 双进程 IPC 共享 Device 内存关闭进程白名单校验【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime本文基于 CANN Runtime 官方样例11_ipc_memory_withoutpid讲解如何在同一个 Device 上的两个独立进程之间通过 IPC 机制共享 Device 内存并且在导出共享内存时关闭进程白名单PID校验。文章完整覆盖样例的运行步骤、进程 A/进程 B 的源码级实现、跨进程 key 传递的文件交换机制以及aclrtIpcMemGetExportKey、aclrtIpcMemImportByKey、aclrtIpcMemClose等接口的参数含义与调用顺序约束帮助读者掌握 CANN Runtime 进程间 Device 内存共享的完整实战方案。场景说明与样例组成本样例展示同一个 Device、两个进程间通过 IPC 共享 Device 内存并在内存共享时关闭进程白名单校验进程 A源进程申请 Device 内存用 AscendC 算子向其中写入数值 123调用aclrtIpcMemGetExportKey导出共享内存 key并通过临时文件把 key 传给进程 B最后等待进程 B 的完成信号进程 B目的进程从临时文件读取 key调用aclrtIpcMemImportByKey导入共享内存获得本进程可访问的 Device 内存地址用算子读取其中的数据并打印然后写回完成标志。两个进程不启用进程白名单校验因此进程 B无需调用aclrtIpcMemSetImportPid设置白名单流程比开启白名单的对照样例10_ipc_memory_withpid更简洁。样例目录下的文件职责如下见 example/1_basic_features/memory/11_ipc_memory_withoutpid文件作用proc_a.cpp进程 A分配内存、写入数据、导出 key、等待完成标志proc_b.cpp进程 B读取 key、导入内存、读取数据、写完成标志run.sh一键编译并并行拉起两个进程校验结果CMakeLists.txtCMake 构建脚本编译proc_a、proc_b及算子库复用文件文件交换工具 file_ops.cpp实现 mem_utils.h 中的接口、算子 write_read_value.cpp产品支持情况来自 README.md产品是否支持Ascend 950PR/Ascend 950DT√Atlas A3 训练系列产品/Atlas A3 推理系列产品√Atlas A2 训练系列产品/Atlas A2 推理系列产品√编译与运行下载样例代码至安装 CANN 软件的环境切换到样例目录cd ${git_clone_path}/example/1_basic_features/memory/11_ipc_memory_withoutpid设置环境变量# ${install_root} 替换为 CANN 安装根目录默认安装在/usr/local/Ascend目录 source ${install_root}/cann/set_env.sh # 自动识别 SOC_VERSION 和 ASCEND_CMAKE_DIR source ${git_clone_path}/example/set_sample_env.sh执行以下命令运行样例bash run.shrun.sh 的完整执行逻辑可以拆解为四步环境检查与编译检查ASCEND_HOME_PATH是否已设置未设置则提示先 source CANN 的set_env.sh并退出随后 source${ASCEND_HOME_PATH}/bin/setenv.bash获取SOC_VERSION再用 CMake 完成配置、构建与安装准备交换目录清理并创建file/目录作为两个进程间交换 key 和完成标志的临时文件区并行启动双进程以子 shell 后台方式同时运行./build/proc_a与./build/proc_b各自输出通过tee落盘到output_msg_proc_a.txt/output_msg_proc_b.txt并wait收集两者的退出码结果自动校验用awk分别从两个输出文件中提取Source data:进程 A 侧写入值与Destination data:进程 B 侧读到的值并比对相等则打印[SUCCESS]否则打印[FAILURE]并以非零码退出。CMakeLists.txt 要求 CMake ≥ 3.16.0从环境变量读取SOC_VERSION与ASCENDC_CMAKE_DIR通过ascendc_library把 write_read_value.cpp 编译成静态算子库kernels再将proc_a.cpp、proc_b.cpp与公共的../file_ops.cpp一起链接ascendcl和kernels两个库安装前缀指向样例本地out/目录。进程 A分配内存、写入数据并导出 keyproc_a.cpp 的执行流程如下aclInit(nullptr); int32_t deviceId 0; aclrtSetDevice(deviceId); aclrtStream stream nullptr; aclrtCreateStream(stream); // Allocate memory on the device uint64_t size 1 * 1024 * 1024; int* devPtr; CHECK_ERROR(aclrtMalloc((void**)devPtr, size, ACL_MEM_MALLOC_HUGE_FIRST)); constexpr uint32_t blockDim 1; int writeValue 123; WriteDo(blockDim, stream, devPtr, writeValue); // 算子写入 123 // Export the shareable memory identifier char memName[256] name; size_t lenName 65; CHECK_ERROR(aclrtIpcMemGetExportKey(devPtr, size, memName, lenName, 1));关键点说明通过aclrtMalloc申请 1MB Device 内存分配策略为ACL_MEM_MALLOC_HUGE_FIRST优先使用大页内存WriteDo是 write_read_value.cpp 中的封装其内部启动 AscendC 算子DeviceWrite在 AI Core 上执行devPtr[block_idx] value并通过AscendC::printf在设备侧打印Source data: 123这就是后续 run.sh 校验的源数据调用aclrtIpcMemGetExportKey(devPtr, size, memName, lenName, 1)将刚分配的 Device 内存标记为 IPC 共享内存并导出 key。各参数含义参见头文件声明 acl_rt.h 与接口文档 11-07_IPC_memory_sharing.mddevPtr待共享的 Device 内存地址必须与aclrtMalloc返回的地址一致size内存大小Byte应与申请内存时的 size 一致本例为 1MBkey输出的共享内存 key样例中用 256 字节缓冲承接lenkey 长度固定配置为65flags白名单开关。宏定义中ACL_RT_IPC_MEM_EXPORT_FLAG_DEFAULT0x0UL为默认值启用进程白名单校验ACL_RT_IPC_MEM_EXPORT_FLAG_DISABLE_PID_VALIDATION0x1UL关闭白名单校验。本样例传1即关闭校验所以进程 B 不需要走aclrtIpcMemSetImportPid设置白名单——这正是本样例与 withpid 对照样例的核心差异。导出 key 之后进程 A 通过文件把 key 交给进程 B并等待完成标志// Transfer the shareable memory identifier to Process B by writing it to the file memory::WriteFile(file/memName.bin, file/memName.bin.done, memName, strlen(memName)); // Read the completion flag from the file int32_t flag 0; memory::ReadFile(file/flag.bin, file/flag.bin.done, flag, sizeof(flag));最后释放资源aclrtIpcMemClose(memName)关闭 IPC 共享内存再依次aclrtDestroyStreamForce、aclrtFree、aclrtResetDeviceForce、aclFinalize。进程 B导入 key 并读取共享内存proc_b.cpp 的执行流程如下const int32_t deviceId 0; aclrtStream stream nullptr; CHECK_ERROR(memory::InitDeviceAndCreateStream(deviceId, stream)); // Get the shareable memory identifier from the file char memName[256] name; memory::ReadFile(file/memName.bin, file/memName.bin.done, memName, sizeof(memName)); // Return a device memory pointer accessible to Process B void* devPtr nullptr; uint64_t size 1 * 1024 * 1024; CHECK_ERROR(aclrtIpcMemImportByKey(devPtr, memName, 0)); constexpr uint32_t blockDim 1; ReadDo(blockDim, stream, static_castint*(devPtr)); // 算子读值并打印 // Write the completion flag to the file int32_t flag 1; memory::WriteFile(file/flag.bin, file/flag.bin.done, flag, sizeof(flag));关键点说明memory::InitDeviceAndCreateStream是 memory_runtime_utils.h 中的内联封装内部完成 Runtime 初始化、aclrtSetDevice与aclrtCreateStream进程 B 从文件读回与进程 A 相同的 key调用aclrtIpcMemImportByKey(devPtr, memName, 0)导入共享内存。第三个参数flags传0即ACL_RT_IPC_MEM_IMPORT_FLAG_DEFAULT默认行为头文件 acl_rt.h 中另定义了ACL_RT_IPC_MEM_IMPORT_FLAG_ENABLE_PEER_ACCESS用于跨 Device 场景下启用对对端 Device 内存的直接访问本样例为同 Device 共享不需要该标志导入成功后devPtr指向的是本进程地址空间中可访问该共享物理内存的 Device 地址进程 B 用它执行ReadDo对应算子DeviceRead读取devPtr[0]并通过AscendC::printf打印Destination data: 123读值完成后写入flag 1作为完成信号随后aclrtIpcMemClose(memName)、销毁 Stream、aclrtFree(devPtr)、aclrtResetDeviceForce、aclFinalize退出流程与进程 A 对称。跨进程交换机制临时文件 完成标志由于 key 只能由导出进程产生两个进程之间需要一个带外通道。样例选择最简单的文件交换方式实现在公共文件 file_ops.cpp接口声明于 mem_utils.hmemory::WriteFile(filePath, doneFile, data, size)先把数据完整写入filePath本例为file/memName.bin或file/flag.bin写成功后再创建一个同名的.done标记文件如file/memName.bin.done以此告知对端数据已写完避免读到半截内容memory::ReadFile(filePath, doneFile, data, bufferSize)先轮询等待doneFile出现每次usleep(1000000)纳秒级休眠最多重试约 10 亿次确认写入完成后再fstat校验文件大小不超出缓冲最后读取数据。这套数据文件 .done标志文件的模式让两个异步并发的进程无需共享内存之外的同步设施也能可靠地完成 key 与完成信号的交接。IPC 接口调用顺序与约束结合 acl_rt.h 的接口声明与接口文档 11-07_IPC_memory_sharing.md 中的配合使用说明两进程内存共享的完整调用顺序为进程 A导出方aclrtMalloc申请内存aclrtIpcMemGetExportKey导出 keyflags0启用白名单时需再调aclrtIpcMemSetImportPid设置 B 进程白名单flags1关闭白名单则无需aclrtIpcMemClose关闭 IPC 共享内存——注意顺序要求B 进程先关闭A 进程再关闭否则可能导致异常aclrtFree释放内存。进程 B导入方调用aclrtIpcMemImportByKey导入 key返回本进程可用的 Device 内存地址指针。导入前需确保待共享内存仍然存在、未被提前释放调用aclrtIpcMemClose关闭 IPC 共享内存。每成功调用一次aclrtIpcMemImportByKey均需调用一次aclrtIpcMemClose且两个接口传入的 key 必须相同即必须成对调用。本样例中两侧都严格执行了上述顺序并且都在使用完共享内存后才依次执行aclrtFree/aclrtIpcMemClose保证了共享关系的干净退出。示例输出运行成功后两个进程的输出合并展示如下[INFO] Process B: get the shareable memory identifier successfully, shareable identifier ... [INFO] Process B: complete ipc memory sharing Destination data: 123 [INFO] Allocate memory on the device 0x... successfully [INFO] Write data 123 to the device address 0x... [INFO] Process A: get the shareable memory identifier ... successfully Source data: 123 [INFO] Process A: receive the completion signal from Process B, completion signal 1 [SUCCESS] IPC memory sharing successfully. Values at source and destination are equal: 123其中Source data: 123由进程 A 侧的设备端算子打印Destination data: 123由进程 B 侧的设备端算子打印run.sh比对两者相等后输出[SUCCESS]即验证了进程 B 通过 IPC 导入的地址确实读到了进程 A 写入的数据。小结样例涉及的关键接口功能域关键接口作用初始化aclInit/aclFinalizeRuntime 初始化与去初始化Device 管理aclrtSetDevice指定用于运算的 Device本例 Device 0Device 管理aclrtResetDeviceForce强制复位 Device回收 Device 上的资源Stream 管理aclrtCreateStream/aclrtDestroyStreamForce创建 Stream / 强制销毁 Stream 并丢弃所有任务内存管理aclrtMalloc/aclrtFree申请 / 释放 Device 内存内存管理aclrtIpcMemGetExportKey将 Device 内存设置为 IPC 共享内存并返回 keyflags1关闭 PID 白名单校验内存管理aclrtIpcMemImportByKey导入 key返回本进程可使用的 Device 内存地址内存管理aclrtIpcMemClose关闭 IPC 共享内存导出方与导入方均需调用且成对使用如果要在此基础上扩展为开启白名单校验的共享方式可参考同一 memory 样例集中的 10_ipc_memory_withpid导出时flags传0ACL_RT_IPC_MEM_EXPORT_FLAG_DEFAULT导入进程需先通过aclrtDeviceGetBareTgid获取进程 ID再由导出方调用aclrtIpcMemSetImportPid将其加入白名单。接口细节均可在 docs/zh/api_ref/11-07_IPC_memory_sharing.md 中查阅。【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表