# 进程间通信【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime由某个主机线程创建的任意设备内存、Event资源或Notify资源都可以在同一进程内被该进程中的其他线程直接引用。但这些指针或句柄在进程之外是无效的因此不能被其他进程的线程直接使用。若要在不同进程之间共享设备内存、Event资源或Notify资源需要应用程序使用Runtime提供的进程间通信相关API以实现如下典型场景由一个主进程生成一批输入数据并将这些数据提供给多个从属进程使用而无需在每个进程中重新生成或复制数据。不同资源涉及的IPCInter-Process Communication接口不同可查看下文中的调用示例。需要注意的是通过aclrtMalloc接口分配设备内存时出于性能考虑可能会从更大的底层内存块中切分出来。在这种情况下IPC接口会检查共享内存是否页表对齐若未对齐API将拦截并报错以防止跨进程多映射内存导致的信息泄露风险。因此建议使用aclrtMalloc接口根据内存分配规则申请内存。申请不同类型的内存时其页表大小会有所不同普通页内存的页表大小为4K大页内存的页表大小支持2M或1G。进程间共享内存此处以A进程内存出借方、B进程内存借入方为例说明两个进程间的内存共享接口调用流程以下为A、B进程之间共享内存的示例代码不可以直接拷贝编译运行仅供参考。完整样例代码请参见Link。在A进程中分配内存生成共享keyuint keyLen 65; char[keyLen] key; void *ptrA nullptr; aclrtSetDevice(0); // 进程A使用Device 0 aclrtMalloc(ptrA, size); aclrtIpcMemGetExportKey(ptrA, size, key, keyLen, ACL_RT_IPC_MEM_EXPORT_FLAG_DISABLE_PID_VALIDATION); // 跨进程通信交换key以写文件方式交互) writeFile(file/ipc_mem, key, keyLen); // 对共享内存进行读写操作 ...... // 待共享内存使用完成后借出方关闭IPC共享内存 aclrtIpcMemClose(key); aclrtFree(ptrA); aclrtResetDeviceForce(0);在B进程中通过共享key导入共享内存uint keyLen 65; char[keyLen] key; void *ptrB; // 跨进程通信交换key以写文件方式交互) readFile(file/ipc_mem, key, keyLen); aclrtSetDevice(1); // 进程B使用Device 1 // AB进程使用不同的Device导入共享内存访问要开启两个Device之间的数据交互 aclrtIpcMemImportByKey(ptrB, key, ACL_RT_IPC_MEM_IMPORT_FLAG_ENABLE_PEER_ACCESS); // 对ptrB内存读写操作 ...... // 使用完成后借入方关闭IPC共享内存 aclrtIpcMemClose(key); aclrtResetDeviceForce(1);进程间共享Event进程之间通过共享Event可以实现进程间的事件同步。此处以A进程创建Event共享给B进程为例说明两个进程间任务同步的示例代码不可以直接拷贝编译运行仅供参考。在A进程中创建Event生成共享handleaclrtEvent event; aclrtStream stream; aclrtIpcEventHandle handle; aclrtSetDevice(0); // 进程A使用Device 0 aclrtCreateEventExWithFlag(event, ACL_EVENT_IPC); // 创建IPC Event aclrtCreateStream(stream); // 创建Stream // 导出进程间共享handle aclrtIpcGetEventHandle(event, handle); // 跨进程通信交换key以写文件方式交互) writeFile(file/ipc_event, handle, ACL_IPC_EVENT_HANDLE_SIZE); // 下发record任务 aclrtEventRecord(event, stream); // Event使用完, 销毁共享Event aclrtDestroyEvent(event); aclrtResetDeviceForce(0);在B进程中通过共享handle导入共享EventaclrtStream stream; aclrtEvent event; aclrtIpcEventHandle handle; aclrtCreateStream(stream); // 创建Stream // 跨进程获取共享handle以写文件方式交互) readFile(file/ipc_event, handle, ACL_IPC_EVENT_HANDLE_SIZE); aclrtSetDevice(1); //进程B使用Device 1 // 导入handle返回共享event // AB进程使用不同的Device aclrtIpcOpenEventHandle(handle, event); // 下发wait任务 aclrtStreamWaitEvent(stream, event); // 同步Stream上的任务 aclrtSynchonizeStream(stream); // Event使用完销毁共享Event aclrtDestroyEvent(event); aclrtResetDeviceForce(1);进程间共享Notify进程之间通过共享Notify可以实现进程间的通知。此处以A进程创建Notify共享给B进程为例说明两个进程间任务同步的示例代码不可以直接拷贝编译运行仅供参考。完整样例代码请参见Link。注意创建端会分配Notify硬件资源因此只能由创建端硬件进行Wait。为此共享Notify有使用约束只能在创建端调aclrtNotifyWait进行Wait不能在共享端Wait。在A进程中创建Notify生成共享keyuint keyLen 65; char key[keyLen]; aclrtNotify notify; aclrtStream stream; // 进程A使用Device 0 aclrtSetDevice(0); aclrtCreateStream(stream); aclrtNotifyCreate(notify); // 导出key即Notify共享名称 aclrtNotifyGetExportKey(notify, key, keyLen, ACL_RT_NOTIFY_EXPORT_FLAG_DISABLE_PID_VALIDATION); // 跨进程通信交换key以写文件方式交互) writeFile(file/ipc_notify, key, keyLen); // 下发wait任务 aclrtNotifyWait(notify, stream); // Notify使用完, 销毁共享Notify aclrtNotifyDestroy(notify); aclrtResetDeviceForce(0);在B进程中通过共享key导入共享Notifyuint keyLen 65; char key[keyLen]; aclrtNotify notify; aclrtStream stream; // 跨进程通信交换key以写文件方式交互) readFile(file/ipc_notify, key, keyLen); //进程B使用Device 1 aclrtSetDevice(1); aclrtCreateStream(stream); // 导入key返回共享Notify // AB进程使用不同的Device导入共享Notify要开启两个Device之间的数据交互 aclrtNotifyImportByKey(notify, key, ACL_RT_NOTIFY_IMPORT_FLAG_ENABLE_PEER_ACCESS); // 下发record任务 aclrtNotifyRecord (notify, stream); // Notify使用完销毁共享Notify aclrtNotifyDestroy(notify); aclrtResetDeviceForce(1);通过VMM接口实现进程间共享内存除IPC Mem共享内存外Runtime还提供了另外一套内存管理和内存共享接口。VMMVirtual Memory Management这套接口提供更灵活的功能支持虚拟地址申请、物理内存申请和跨进程物理内存共享还支持虚拟地址与物理内存之间的映射操作。此处以A、B进程为例说明一个Device上、两个进程间的物理内存共享的示例代码不可以直接拷贝编译运行仅供参考完整样例代码请参见Link。若A、B进程使用不同的Device还需配合使用aclrtDeviceEnablePeerAccess接口开启跨Device的数据交互详细描述请参见跨Device的数据交互。在A进程中// 查询内存申请粒度 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; aclrtMemGetAllocationGranularity(prop, ACL_RT_MEM_ALLOC_GRANULARITY_MINIMUM, granularity); // 基于内存申请粒度申请物理内存 size_t alignedSize ((dataSize granularity - 1U) / granularity) * granularity; aclrtDrvMemHandle handle nullptr; aclrtMallocPhysical(handle, alignedSize, prop, 0); // 预留虚拟内存 void *virPtr; aclrtReserveMemAddress(virPtr, alignedSize, 0, nullptr, 0); // 将虚拟内存映射到物理内存 aclrtMapMem(virPtr, alignedSize, 0, handle, 0); aclrtMemAccessDesc desc {}; desc.flags ACL_RT_MEM_ACCESS_FLAGS_READWRITE; desc.location.id 0; desc.location.type ACL_MEM_LOCATION_TYPE_DEVICE; aclrtMemSetAccess(virPtr, alignedSize, desc, 1); // 使用virPtr进行复制、读、写等操作 ...... // 导入共享handle uint64_t shareableHandle 0ULL; aclrtMemExportToShareableHandle(handle, ACL_MEM_HANDLE_TYPE_NONE, ACL_RT_VMM_EXPORT_FLAG_DISABLE_PID_VALIDATION , shareableHandle); // 将共享handle传递给进程B writeFile(file/vmm_mem, shareableHandle, sizeof(shareableHandle)); // 取消虚拟内存与物理内存之间的映射关系 aclrtUnmapMem(virPtr); // 释放虚拟内存和物理内存 aclrtReleaseMemAddress(virPtr); aclrtFreePhysical(handle);在B进程中uint64_t shareableHandle 0ULL; // 从文件中获取共享handle readFile(file/vmm_mem, shareableHandle, sizeof(shareableHandle)); aclrtDrvMemHandle handle nullptr; int32_t deviceId0; aclrtMemImportFromShareableHandle(shareableHandle, deviceId, handle); // 查询内存申请粒度 const size_t data_size 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; aclrtMemGetAllocationGranularity(prop, ACL_RT_MEM_ALLOC_GRANULARITY_MINIMUM, granularity); size_t alignedSize ((dataSize granularity - 1U) / granularity) * granularity; // 基于内存申请粒度预留虚拟内存 void *virPtr nullptr; aclrtReserveMemAddress(virPtr, alignedSize, 0, nullptr, 0); // 将虚拟内存映射到物理内存 aclrtMapMem(virPtr, alignedSize, 0, handle, 0); aclrtMemAccessDesc desc {}; desc.flags ACL_RT_MEM_ACCESS_FLAGS_READWRITE; desc.location.id 0; desc.location.type ACL_MEM_LOCATION_TYPE_DEVICE; aclrtMemSetAccess(virPtr,alignedSize, desc, 1); // 使用virPtr进行复制、读、写等操作 ...... // 取消虚拟内存与物理内存之间的映射关系 aclrtUnmapMem(virPtr); // 释放虚拟内存和物理内存 aclrtReleaseMemAddress(virPtr); aclrtFreePhysical(handle);【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考