对于Host和Device间的数据传输,是通过调用内存复制接口实现的。
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
// 1. 申请内存 uint64_t size = 1 * 1024 * 1024; void* hostPtrA = NULL; void* devPtrB = NULL; aclrtMallocHost(&hostPtrA, size); aclrtMalloc(&devPtrB, size, ACL_MEM_MALLOC_NORMAL_ONLY); // 2. 申请内存后,可向内存中读入数据,该自定义函数ReadFile由用户实现 ReadFile(fileName, hostPtrA, size); // 3. 内存复制,可以选择同步或异步 // 同步内存复制,hostPtrA表示Host上源内存地址指针,devPtrB表示Device上目的内存地址指针,size表示内存大小 aclrtMemcpy(devPtrB, size, hostPtrA, size, ACL_MEMCPY_HOST_TO_DEVICE); // 4. 使用完内存中的数据后,需及时释放资源 aclrtFreeHost(hostPtrA); aclrtFree(devPtrB); // ......
调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。
// 1. 申请内存 uint64_t size = 1 * 1024 * 1024; void* hostAddr = NULL; void* devAddr = NULL; // 由于异步内存复制时,要求首地址64字节对齐,因此申请内存时,size需加64 aclrtMallocHost(&hostAddr, size + 64); // 通过aclrtMalloc接口申请的内存,系统已保证内存地址64字节对齐,无需用户处理对齐的逻辑 aclrtMalloc(&devAddr, size, ACL_MEM_MALLOC_NORMAL_ONLY); // 2. 异步内存复制 aclrtStream stream = NULL; aclrtCreateStream(&stream); // 获取到64字节对齐的地址 char *hostAlignAddr =(char *)hostAddr + 64 - ((uintptr_t)hostAddr % 64); // 申请内存后,可向内存中读入数据,该自定义函数ReadFile由用户实现 ReadFile(fileName, hostAlignAddr, size); aclrtMemcpyAsync(devAddr, size, hostAlignAddr, size, ACL_MEMCPY_HOST_TO_DEVICE, stream); aclrtSynchronizeStream(stream); // 3. 释放资源 aclrtDestroyStream(stream); aclrtFreeHost(hostAddr); aclrtFree(devAddr); // ......