已合并
IsClose示例改用C++ RAII资源管理,与IsFinite/IsInf示例风格对齐 #4696
IsClose示例改用C++ RAII资源管理,与IsFinite/IsInf示例风格对齐 #4696
已合并
sunday创建于 6 天前
1 个文件变更+54-42
Mmath/is_close/examples/test_aclnn_isclose.cpp+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#include <iostream>10#include <iostream>
11+#include <memory>
12+#include <type_traits>
11#include <vector>13#include <vector>
12#include "acl/acl.h"14#include "acl/acl.h"
13#include "aclnnop/aclnn_isclose.h"15#include "aclnnop/aclnn_isclose.h"
@@ -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 
48template <typename T>58template <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的strides73 // 计算连续tensor的strides
@@ -65,8 +77,10 @@ int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>&
65 }77 }
66 78 
67 // 调用aclCreateTensor接口创建aclTensor79 // 调用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填写deviceId90 // 根据自己的实际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 aclTensor122 // 创建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 aclTensor125 // 创建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 aclTensor128 // 创建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,需要修改为具体的API132 // 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}