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