从Device到Host的数据传输

对于Device到Host的数据传输,是通过调用内存复制接口实现的。

同步内存复制实现数据传输

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

// 1. 申请内存
uint64_t size = 1 * 1024 * 1024;
void* devPtrA = NULL;
void* hostPtrB = NULL;
aclrtMalloc(&devPtrA, size, ACL_MEM_MALLOC_NORMAL_ONLY);
aclrtMallocHost(&hostPtrB, size);

// 2. 申请内存后,可向内存中读入数据,该自定义函数ReadFile由用户实现
ReadFile(fileName, devPtrA, size);

// 3. 内存复制,可以选择同步或异步
// 同步内存复制,devPtrA表示Device上源内存地址指针,hostPtrB表示Host上目的内存地址指针,size表示内存大小
aclrtMemcpy(hostPtrB, size, devPtrA, size, ACL_MEMCPY_DEVICE_TO_HOST);

// 4. 使用完内存中的数据后,需及时释放资源
aclrtFree(devPtrA);
aclrtFreeHost(hostPtrB);

// ......

异步内存复制实现数据传输

调用接口后,需增加异常处理的分支,并记录报错日志、提示日志,此处不一一列举。以下是关键步骤的代码示例,不可以直接拷贝编译运行,仅供参考。

// 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. 申请内存后,可向内存中读入数据,该自定义函数ReadFile由用户实现
ReadFile(fileName, devAddr, size);

// 3. 异步内存复制
aclrtStream stream = NULL;
aclrtCreateStream(&stream);
// 获取到64字节对齐的地址
char *hostAlignAddr =(char *)hostAddr + 64 - ((uintptr_t)hostAddr % 64);
aclrtMemcpyAsync(hostAlignAddr, size, devAddr, size, ACL_MEMCPY_DEVICE_TO_HOST, stream);
aclrtSynchronizeStream(stream);

// 4. 释放资源
aclrtDestroyStream(stream);
aclrtFreeHost(hostAddr);
aclrtFree(devAddr);

// ......