CANN运行时数据复制指南
数据复制【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtimeHost和Device拥有独立内存空间。Host侧准备的数据需要复制到Device内存后Device上的算子才能以更高性能访问计算结果也通常需要从Device复制回Host侧。Runtime提供同步、异步、批量、二维和描述符等多种复制接口用于覆盖不同的数据搬运场景。复制方向常见复制方向如下场景复制方向常用接口说明Host到DeviceACL_MEMCPY_HOST_TO_DEVICEaclrtMemcpy、aclrtMemcpyAsync常用于输入数据搬运。异步接口要获得真正异步效果Host内存建议使用锁页内存。Device到HostACL_MEMCPY_DEVICE_TO_HOSTaclrtMemcpy、aclrtMemcpyAsync常用于取回算子输出。读取Host结果前需要保证复制任务已完成。Device到Device复制ACL_MEMCPY_DEVICE_TO_DEVICEaclrtMemcpy、aclrtMemcpyAsync表示同Device内或跨Device的数据复制。这类接口可根据源、目的地址判断实际复制路径不需要用户显式区分同Device或跨Device。Device内描述符复制ACL_MEMCPY_INNER_DEVICE_TO_DEVICEaclrtMemcpyAsyncWithDesc表示同Device内的数据复制。描述符方式需要显式指定该枚举。Host内复制ACL_MEMCPY_HOST_TO_HOSTaclrtMemcpy一般Host侧内存复制可直接使用标准C/C接口。使用Runtime异步接口进行Host内复制时需关注产品支持限制。同步接口aclrtMemcpy会在复制完成后返回。异步接口aclrtMemcpyAsync会把复制任务下发到指定Stream接口返回只表示任务下发完成不表示复制任务已完成读取目的内存前需要调用aclrtSynchronizeStream、aclrtSynchronizeDevice或通过Event等机制确认任务完成。Host与Device复制Host与Device之间的数据复制是最常见的输入、输出搬运方式。典型流程为申请Host内存和Device内存将输入从Host复制到Device在Stream上下发算子最后将输出从Device复制回Host。aclrtStream stream nullptr; aclrtCreateStream(stream); void *hostIn nullptr; void *hostOut nullptr; void *devIn nullptr; void *devOut nullptr; aclrtMallocHost(hostIn, size); aclrtMallocHost(hostOut, size); aclrtMalloc(devIn, size, ACL_MEM_MALLOC_HUGE_FIRST); aclrtMalloc(devOut, size, ACL_MEM_MALLOC_HUGE_FIRST); // 输入数据从Host复制到Device。 aclrtMemcpyAsync(devIn, size, hostIn, size, ACL_MEMCPY_HOST_TO_DEVICE, stream); // 下发计算任务和前序复制任务在同一Stream中保序执行。 myKernelnumBlocks, nullptr, stream(devIn, devOut); // 输出数据从Device复制回Host。 aclrtMemcpyAsync(hostOut, size, devOut, size, ACL_MEMCPY_DEVICE_TO_HOST, stream); // 等待同一Stream上复制和计算全部完成再读取hostOut。 aclrtSynchronizeStream(stream);若使用同步复制接口接口内部会等待本次复制完成后返回但不会对其它Stream做隐式同步。若复制前后还有其它异步任务需要通过Stream顺序、Event或显式同步保证数据依赖关系。非锁页Host内存的异步复制通过malloc、mmap等传统接口申请的Host内存是非锁页内存。aclrtMemcpyAsync、aclrtMemcpy2dAsync、aclrtMemcpyBatchAsync等异步接口支持非锁页Host内存但这类场景需要单独关注当参与复制的Host内存是锁页内存时异步复制接口只下发复制任务并返回Host线程可以继续执行其它工作复制任务在Stream中按序完成。当参与复制的Host内存是非锁页内存时异步复制接口会在内存复制任务完成后才返回。此时接口名虽然带Async但Host线程无法与本次复制并行执行数据传输也难以与计算充分重叠。若需要稳定获得复制与计算重叠效果建议通过aclrtMallocHost申请锁页内存或在支持的系统上使用aclrtHostRegisterV2将已有Host内存注册为锁页内存。ACL Graph捕获异步内存复制任务时若复制涉及Host内存Host内存需要使用Runtime接口申请的锁页内存否则捕获过程中会返回错误。因此非锁页Host内存更适合低频、临时、对并发性能不敏感的数据搬运性能敏感的输入输出通路应使用锁页Host内存。Device内复制使用aclrtMemcpy、aclrtMemcpyAsync进行Device到Device复制时复制类型使用ACL_MEMCPY_DEVICE_TO_DEVICE即可。该枚举表示同Device内或跨Device的数据复制Runtime会根据源地址和目的地址判断实际复制路径用户不需要显式指定ACL_MEMCPY_INNER_DEVICE_TO_DEVICE或ACL_MEMCPY_INTER_DEVICE_TO_DEVICE。ACL_MEMCPY_INNER_DEVICE_TO_DEVICE只表示同Device内复制需要在描述符复制场景中显式指定例如aclrtMemcpyAsyncWithDesc接口。描述符方式适合复制参数可复用的场景。用户先获取描述符大小并设置源地址、目的地址和长度再在Stream上使用描述符下发复制任务。跨Device复制跨Device复制用于同一进程内不同Device之间的数据搬运。调用复制接口前应先确认两个Device之间是否支持数据交互并按访问方向开启Peer Accessint32_t canAccess 0; aclrtDeviceCanAccessPeer(canAccess, srcDeviceId, dstDeviceId); if (canAccess ! 0) { aclrtSetDevice(dstDeviceId); aclrtDeviceEnablePeerAccess(srcDeviceId, 0); }用于跨Device复制的Device内存建议结合内存管理中带P2P后缀的内存分配策略申请例如ACL_MEM_MALLOC_HUGE_FIRST_P2P。更多多Device资源管理和复制示例请参见多设备编程。二维和批量复制二维复制接口aclrtMemcpy2d、aclrtMemcpy2dAsync适用于矩阵、图像或带pitch的二维数据。调用时需要分别指定源和目的内存中相邻两列向量的地址距离以及待复制区域的宽度和高度。异步二维复制涉及Host内存时同样遵循“锁页Host内存才是真正异步”的规则。批量复制接口aclrtMemcpyBatch、aclrtMemcpyBatchAsync及其V2版本适用于一次下发多段Host到Device或Device到Host复制。批量复制需要注意批次内的复制操作不保证按照数组顺序执行。每个复制操作的目的地址、源地址和复制大小数组长度必须一致。同一个批次中的复制方向仅支持Host到Device或Device到Host中的一种。相关接口属于试验特性时应以API参考中的产品说明和约束为准。内存设置aclrtMemset、aclrtMemsetAsync用于初始化Device内存。同步接口在设置完成后返回异步接口把内存设置任务下发到指定Stream。对于作为同步标记或计算输入的Device内存建议在使用前显式初始化避免读取到未定义数据。【免费下载链接】runtime本项目提供CANN运行时组件和维测功能组件。项目地址: https://gitcode.com/cann/runtime创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考