已合并
IsClose示例改用C++ RAII资源管理,与IsFinite/IsInf示例风格对齐 #4696
sunday创建于 6 天前
IsClose示例改用C++ RAII资源管理,与IsFinite/IsInf示例风格对齐 #4696
已合并
共 1 个文件变更+54-42
| @@ -8,6 +8,8 @@ | |||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | 8 | * See LICENSE in the root of the software repository for the full text of the License. |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | + | ||
| 12 | + | ||
| 11 | 13 | ||
| 12 | 14 | ||
| 13 | 15 | ||
| @@ -33,29 +35,39 @@ int64_t GetShapeSize(const std::vector<int64_t>& shape) | |||
| 33 | return shape_size; | 35 | return shape_size; |
| 34 | } | 36 | } |
| 35 | 37 | ||
| 36 | -int Init(int32_t deviceId, aclrtStream* stream) | 38 | +using StreamPtr = std::unique_ptr<std::remove_pointer<aclrtStream>::type, decltype(&aclrtDestroyStream)>; |
| 39 | +using DeviceMemPtr = std::unique_ptr<void, decltype(&aclrtFree)>; | ||
| 40 | +using TensorPtr = std::unique_ptr<aclTensor, decltype(&aclDestroyTensor)>; | ||
| 41 | + | ||
| 42 | +int Init(int32_t deviceId, StreamPtr& stream, bool& initialized, bool& deviceSet) | ||
| 37 | { | 43 | { |
| 38 | // 固定写法,资源初始化 | 44 | // 固定写法,资源初始化 |
| 39 | auto ret = aclInit(nullptr); | 45 | auto ret = aclInit(nullptr); |
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 46 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 47 | + initialized = true; | ||
| 41 | ret = aclrtSetDevice(deviceId); | 48 | ret = aclrtSetDevice(deviceId); |
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 49 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 43 | - ret = aclrtCreateStream(stream); | 50 | + deviceSet = true; |
| 51 | + aclrtStream rawStream = nullptr; | ||
| 52 | + ret = aclrtCreateStream(&rawStream); | ||
| 44 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 53 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 54 | + stream.reset(rawStream); | ||
| 45 | return 0; | 55 | return 0; |
| 46 | } | 56 | } |
| 47 | 57 | ||
| 48 | template <typename T> | 58 | template <typename T> |
| 49 | -int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 59 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, aclDataType dataType, |
| 50 | - aclDataType dataType, aclTensor** tensor) | 60 | + DeviceMemPtr& deviceAddr, TensorPtr& tensor) |
| 51 | { | 61 | { |
| 52 | auto size = GetShapeSize(shape) * sizeof(T); | 62 | auto size = GetShapeSize(shape) * sizeof(T); |
| 53 | // 调用aclrtMalloc申请device侧内存 | 63 | // 调用aclrtMalloc申请device侧内存 |
| 54 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 64 | + void* rawDeviceAddr = nullptr; |
| 65 | + auto ret = aclrtMalloc(&rawDeviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 66 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); |
| 67 | + deviceAddr.reset(rawDeviceAddr); | ||
| 56 | 68 | ||
| 57 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 69 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 58 | - ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 70 | + ret = aclrtMemcpy(deviceAddr.get(), size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 59 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 71 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); |
| 60 | 72 | ||
| 61 | // 计算连续tensor的strides | 73 | // 计算连续tensor的strides |
| @@ -65,8 +77,10 @@ int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& | |||
| 65 | } | 77 | } |
| 66 | 78 | ||
| 67 | // 调用aclCreateTensor接口创建aclTensor | 79 | // 调用aclCreateTensor接口创建aclTensor |
| 68 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | 80 | + aclTensor* rawTensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, |
| 69 | - shape.data(), shape.size(), *deviceAddr); | 81 | + aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), deviceAddr.get()); |
| 82 | + CHECK_RET(rawTensor != nullptr, LOG_PRINT("aclCreateTensor failed.\n"); return ACL_ERROR_FAILURE); | ||
| 83 | + tensor.reset(rawTensor); | ||
| 70 | return 0; | 84 | return 0; |
| 71 | } | 85 | } |
| 72 | 86 | ||
| @@ -75,20 +89,30 @@ int main() | |||
| 75 | // 1. (固定写法)device/stream初始化, 参考acl API手册 | 89 | // 1. (固定写法)device/stream初始化, 参考acl API手册 |
| 76 | // 根据自己的实际device填写deviceId | 90 | // 根据自己的实际device填写deviceId |
| 77 | int32_t deviceId = 0; | 91 | int32_t deviceId = 0; |
| 78 | - aclrtStream stream; | 92 | + bool initialized = false; |
| 79 | - auto ret = Init(deviceId, &stream); | 93 | + bool deviceSet = false; |
| 94 | + std::shared_ptr<void> aclGuard(nullptr, [&](void*) { | ||
| 95 | + if (deviceSet) { | ||
| 96 | + aclrtResetDevice(deviceId); | ||
| 97 | + } | ||
| 98 | + if (initialized) { | ||
| 99 | + aclFinalize(); | ||
| 100 | + } | ||
| 101 | + }); | ||
| 102 | + StreamPtr stream(nullptr, &aclrtDestroyStream); | ||
| 103 | + auto ret = Init(deviceId, stream, initialized, deviceSet); | ||
| 80 | // check根据自己的需要处理 | 104 | // check根据自己的需要处理 |
| 81 | - CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 105 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); |
| 82 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | 106 | // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 83 | std::vector<int64_t> selfShape = {4, 2}; | 107 | std::vector<int64_t> selfShape = {4, 2}; |
| 84 | std::vector<int64_t> otherShape = {4, 2}; | 108 | std::vector<int64_t> otherShape = {4, 2}; |
| 85 | std::vector<int64_t> outShape = {4, 2}; | 109 | std::vector<int64_t> outShape = {4, 2}; |
| 86 | - void* selfDeviceAddr = nullptr; | 110 | + DeviceMemPtr selfDeviceAddr(nullptr, &aclrtFree); |
| 87 | - void* otherDeviceAddr = nullptr; | 111 | + DeviceMemPtr otherDeviceAddr(nullptr, &aclrtFree); |
| 88 | - void* outDeviceAddr = nullptr; | 112 | + DeviceMemPtr outDeviceAddr(nullptr, &aclrtFree); |
| 89 | - aclTensor* self = nullptr; | 113 | + TensorPtr self(nullptr, &aclDestroyTensor); |
| 90 | - aclTensor* other = nullptr; | 114 | + TensorPtr other(nullptr, &aclDestroyTensor); |
| 91 | - aclTensor* out = nullptr; | 115 | + TensorPtr out(nullptr, &aclDestroyTensor); |
| 92 | std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | 116 | std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; |
| 93 | std::vector<float> otherHostData = {1, 1, 1, 2, 1, 2, 3, 3}; | 117 | std::vector<float> otherHostData = {1, 1, 1, 2, 1, 2, 3, 3}; |
| 94 | std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | 118 | std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; |
| @@ -96,57 +120,45 @@ int main() | |||
| 96 | double atol = 1.0; | 120 | double atol = 1.0; |
| 97 | bool equal_nan = false; | 121 | bool equal_nan = false; |
| 98 | // 创建gradOutput aclTensor | 122 | // 创建gradOutput aclTensor |
| 99 | - ret = CreateAclTensor(otherHostData, otherShape, &otherDeviceAddr, aclDataType::ACL_FLOAT, &other); | 123 | + ret = CreateAclTensor(otherHostData, otherShape, aclDataType::ACL_FLOAT, otherDeviceAddr, other); |
| 100 | CHECK_RET(ret == ACL_SUCCESS, return ret); | 124 | CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 101 | // 创建self aclTensor | 125 | // 创建self aclTensor |
| 102 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 126 | + ret = CreateAclTensor(selfHostData, selfShape, aclDataType::ACL_FLOAT, selfDeviceAddr, self); |
| 103 | CHECK_RET(ret == ACL_SUCCESS, return ret); | 127 | CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 104 | // 创建out aclTensor | 128 | // 创建out aclTensor |
| 105 | - ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_BOOL, &out); | 129 | + ret = CreateAclTensor(outHostData, outShape, aclDataType::ACL_BOOL, outDeviceAddr, out); |
| 106 | CHECK_RET(ret == ACL_SUCCESS, return ret); | 130 | CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 107 | 131 | ||
| 108 | // 3. 调用CANN算子库API,需要修改为具体的API | 132 | // 3. 调用CANN算子库API,需要修改为具体的API |
| 109 | uint64_t workspaceSize = 0; | 133 | uint64_t workspaceSize = 0; |
| 110 | aclOpExecutor* executor; | 134 | aclOpExecutor* executor; |
| 111 | // 调用aclnnIsClose第一段接口 | 135 | // 调用aclnnIsClose第一段接口 |
| 112 | - ret = aclnnIsCloseGetWorkspaceSize(self, other, rtol, atol, equal_nan, out, &workspaceSize, &executor); | 136 | + ret = aclnnIsCloseGetWorkspaceSize(self.get(), other.get(), rtol, atol, equal_nan, out.get(), &workspaceSize, |
| 137 | + &executor); | ||
| 113 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnIsCloseGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | 138 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnIsCloseGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); |
| 114 | // 根据第一段接口计算出的workspaceSize申请device内存 | 139 | // 根据第一段接口计算出的workspaceSize申请device内存 |
| 115 | - void* workspaceAddr = nullptr; | 140 | + DeviceMemPtr workspaceAddr(nullptr, &aclrtFree); |
| 116 | - if (workspaceSize > 0) { | 141 | + if (workspaceSize > static_cast<uint64_t>(0)) { |
| 117 | - ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | 142 | + void* rawWorkspaceAddr = nullptr; |
| 143 | + ret = aclrtMalloc(&rawWorkspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 118 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | 144 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); |
| 145 | + workspaceAddr.reset(rawWorkspaceAddr); | ||
| 119 | } | 146 | } |
| 120 | // 调用aclnnIsClose第二段接口 | 147 | // 调用aclnnIsClose第二段接口 |
| 121 | - ret = aclnnIsClose(workspaceAddr, workspaceSize, executor, stream); | 148 | + ret = aclnnIsClose(workspaceAddr.get(), workspaceSize, executor, stream.get()); |
| 122 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnIsClose failed. ERROR: %d\n", ret); return ret); | 149 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnIsClose failed. ERROR: %d\n", ret); return ret); |
| 123 | // 4. (固定写法)同步等待任务执行结束 | 150 | // 4. (固定写法)同步等待任务执行结束 |
| 124 | - ret = aclrtSynchronizeStream(stream); | 151 | + ret = aclrtSynchronizeStream(stream.get()); |
| 125 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | 152 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); |
| 126 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | 153 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 |
| 127 | auto size = GetShapeSize(outShape); | 154 | auto size = GetShapeSize(outShape); |
| 128 | std::vector<uint8_t> resultData(size, 0); | 155 | std::vector<uint8_t> resultData(size, 0); |
| 129 | - ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | 156 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr.get(), |
| 130 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | 157 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); |
| 131 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | 158 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); |
| 132 | for (int64_t i = 0; i < size; i++) { | 159 | for (int64_t i = 0; i < size; i++) { |
| 133 | LOG_PRINT("result[%ld] is: %d\n", i, resultData[i]); | 160 | LOG_PRINT("result[%ld] is: %d\n", i, resultData[i]); |
| 134 | } | 161 | } |
| 135 | 162 | ||
| 136 | - // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 137 | - aclDestroyTensor(other); | ||
| 138 | - aclDestroyTensor(self); | ||
| 139 | - aclDestroyTensor(out); | ||
| 140 | - | ||
| 141 | - // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 142 | - aclrtFree(otherDeviceAddr); | ||
| 143 | - aclrtFree(selfDeviceAddr); | ||
| 144 | - aclrtFree(outDeviceAddr); | ||
| 145 | - if (workspaceSize > 0) { | ||
| 146 | - aclrtFree(workspaceAddr); | ||
| 147 | - } | ||
| 148 | - aclrtDestroyStream(stream); | ||
| 149 | - aclrtResetDevice(deviceId); | ||
| 150 | - aclFinalize(); | ||
| 151 | return 0; | 163 | return 0; |
| 152 | } | 164 | } |