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