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