已合并
Xlog1py示例改用C++ RAII资源管理,与IsFinite/IsInf示例风格对齐 #4850
Xlog1py示例改用C++ RAII资源管理,与IsFinite/IsInf示例风格对齐 #4850
已合并
chendunyang创建于 22 天前
1 个文件变更+103-67
@@ -8,7 +8,6 @@
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 * @file test_aclnn_xlog1py.cpp12 * @file test_aclnn_xlog1py.cpp
14 * @brief aclnn xlog1py 算子 NPU 调用示例13 * @brief aclnn xlog1py 算子 NPU 调用示例
@@ -18,17 +17,19 @@
18 */17 */
19 18 
20#include <iostream>19#include <iostream>
20+#include <memory>
21+#include <type_traits>
21#include <vector>22#include <vector>
22#include <cmath>23#include <cmath>
23#include "acl/acl.h"24#include "acl/acl.h"
24#include "aclnnop/aclnn_xlog1py.h"25#include "aclnnop/aclnn_xlog1py.h"
25 26 
26-#define CHECK_RET(cond, msg) \27+#define CHECK_RET(cond, msg) \
27- do { \28+ do { \
28- if (!(cond)) { \29+ if (!(cond)) { \
29 printf("[FAIL] " msg "\n"); \30 printf("[FAIL] " msg "\n"); \
30- return -1; \31+ return -1; \
31- } \32+ } \
32 } while (0)33 } while (0)
33 34 
34#define LOG_PRINT(msg, ...) printf(msg "\n", ##__VA_ARGS__)35#define LOG_PRINT(msg, ...) printf(msg "\n", ##__VA_ARGS__)
@@ -36,13 +37,17 @@
36int64_t GetShapeSize(const std::vector<int64_t>& shape)37int64_t GetShapeSize(const std::vector<int64_t>& shape)
37{38{
38 int64_t size = 1;39 int64_t size = 1;
39- for (auto i : shape) size *= i;40+ for (auto i : shape)
41+ size *= i;
40 return size;42 return size;
41}43}
42 44 
45+using StreamPtr = std::unique_ptr<std::remove_pointer<aclrtStream>::type, decltype(&aclrtDestroyStream)>;
46+using DeviceMemPtr = std::unique_ptr<void, decltype(&aclrtFree)>;
47+using TensorPtr = std::unique_ptr<aclTensor, decltype(&aclDestroyTensor)>;
48+ 
43// Broadcast index: map flat index in output to flat index in input49// Broadcast index: map flat index in output to flat index in input
44-static int64_t BroadcastIdx(int64_t flat, const std::vector<int64_t>& inShape,50+static int64_t BroadcastIdx(int64_t flat, const std::vector<int64_t>& inShape, const std::vector<int64_t>& outShape)
45- const std::vector<int64_t>& outShape)
46{51{
47 int inRank = (int)inShape.size();52 int inRank = (int)inShape.size();
48 int outRank = (int)outShape.size();53 int outRank = (int)outShape.size();
@@ -55,17 +60,17 @@ static int64_t BroadcastIdx(int64_t flat, const std::vector<int64_t>& inShape,
55 int64_t inDim = (inDimIdx >= 0) ? inShape[inDimIdx] : 1;60 int64_t inDim = (inDimIdx >= 0) ? inShape[inDimIdx] : 1;
56 int64_t inCoord = (inDim == 1) ? 0 : coord;61 int64_t inCoord = (inDim == 1) ? 0 : coord;
57 int inStride = 1;62 int inStride = 1;
58- for (int dd = inRank - 1; dd > inDimIdx; dd--) inStride *= inShape[dd];63+ for (int dd = inRank - 1; dd > inDimIdx; dd--)
64+ inStride *= inShape[dd];
59 outIdx += inCoord * inStride;65 outIdx += inCoord * inStride;
60 outStride *= dim;66 outStride *= dim;
61 }67 }
62 return outIdx;68 return outIdx;
63}69}
64 70 
65-std::vector<float> ComputeGolden(71+std::vector<float> ComputeGolden(const std::vector<float>& x, const std::vector<int64_t>& shapeX,
66- const std::vector<float>& x, const std::vector<int64_t>& shapeX,72+ const std::vector<float>& y, const std::vector<int64_t>& shapeY,
67- const std::vector<float>& y, const std::vector<int64_t>& shapeY,73+ const std::vector<int64_t>& outShape)
68- const std::vector<int64_t>& outShape)
69{74{
70 int64_t n = GetShapeSize(outShape);75 int64_t n = GetShapeSize(outShape);
71 std::vector<float> result(n);76 std::vector<float> result(n);
@@ -82,9 +87,9 @@ std::vector<float> ComputeGolden(
82 return result;87 return result;
83}88}
84 89 
85-template<typename T>90+template <typename T>
86-bool CompareResult(const std::vector<float>& golden, const std::vector<T>& npuResult,91+bool CompareResult(const std::vector<float>& golden, const std::vector<T>& npuResult, const std::vector<int64_t>& shape,
87- const std::vector<int64_t>& shape, const std::string& tag)92+ const std::string& tag)
88{93{
89 int64_t n = GetShapeSize(shape);94 int64_t n = GetShapeSize(shape);
90 bool allPass = true;95 bool allPass = true;
@@ -98,7 +103,8 @@ bool CompareResult(const std::vector<float>& golden, const std::vector<T>& npuRe
98 } else {103 } else {
99 mere = std::fabs(static_cast<double>(r - g));104 mere = std::fabs(static_cast<double>(r - g));
100 }105 }
101- if (mere > maxMere) maxMere = mere;106+ if (mere > maxMere)
107+ maxMere = mere;
102 if (mere > 0.001) {108 if (mere > 0.001) {
103 LOG_PRINT(" [FAIL][%s][%ld] golden=%.6f npu=%.6f mere=%.6e", tag.c_str(), i, g, r, mere);109 LOG_PRINT(" [FAIL][%s][%ld] golden=%.6f npu=%.6f mere=%.6e", tag.c_str(), i, g, r, mere);
104 allPass = false;110 allPass = false;
@@ -110,40 +116,46 @@ bool CompareResult(const std::vector<float>& golden, const std::vector<T>& npuRe
110 return allPass;116 return allPass;
111}117}
112 118 
113-int Init(int32_t deviceId, aclrtStream* stream)119+int Init(int32_t deviceId, StreamPtr& stream, bool& initialized, bool& deviceSet)
114{120{
115 auto ret = aclInit(nullptr);121 auto ret = aclInit(nullptr);
116 CHECK_RET(ret == ACL_SUCCESS, "aclInit failed");122 CHECK_RET(ret == ACL_SUCCESS, "aclInit failed");
123+ initialized = true;
117 ret = aclrtSetDevice(deviceId);124 ret = aclrtSetDevice(deviceId);
118 CHECK_RET(ret == ACL_SUCCESS, "aclrtSetDevice failed");125 CHECK_RET(ret == ACL_SUCCESS, "aclrtSetDevice failed");
119- ret = aclrtCreateStream(stream);126+ deviceSet = true;
127+ aclrtStream rawStream = nullptr;
128+ ret = aclrtCreateStream(&rawStream);
120 CHECK_RET(ret == ACL_SUCCESS, "aclrtCreateStream failed");129 CHECK_RET(ret == ACL_SUCCESS, "aclrtCreateStream failed");
130+ stream.reset(rawStream);
121 return 0;131 return 0;
122}132}
123 133 
124-template<typename T>134+template <typename T>
125-int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape,135+int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, aclDataType dataType,
126- void** deviceAddr, aclDataType dataType, aclTensor** tensor)136+ DeviceMemPtr& deviceAddr, TensorPtr& tensor)
127{137{
128 auto size = GetShapeSize(shape) * sizeof(T);138 auto size = GetShapeSize(shape) * sizeof(T);
129- auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);139+ void* rawDeviceAddr = nullptr;
140+ auto ret = aclrtMalloc(&rawDeviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST);
130 CHECK_RET(ret == ACL_SUCCESS, "aclrtMalloc failed");141 CHECK_RET(ret == ACL_SUCCESS, "aclrtMalloc failed");
131- ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);142+ deviceAddr.reset(rawDeviceAddr);
143+ ret = aclrtMemcpy(deviceAddr.get(), size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
132 CHECK_RET(ret == ACL_SUCCESS, "aclrtMemcpy H2D failed");144 CHECK_RET(ret == ACL_SUCCESS, "aclrtMemcpy H2D failed");
133 145 
134 std::vector<int64_t> strides(shape.size(), 1);146 std::vector<int64_t> strides(shape.size(), 1);
135 for (int64_t i = shape.size() - 2; i >= 0; i--) {147 for (int64_t i = shape.size() - 2; i >= 0; i--) {
136 strides[i] = shape[i + 1] * strides[i + 1];148 strides[i] = shape[i + 1] * strides[i + 1];
137 }149 }
138- *tensor = aclCreateTensor(shape.data(), shape.size(), dataType,150+ aclTensor* rawTensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0,
139- strides.data(), 0, aclFormat::ACL_FORMAT_ND,151+ aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), deviceAddr.get());
140- shape.data(), shape.size(), *deviceAddr);152+ CHECK_RET(rawTensor != nullptr, "aclCreateTensor failed");
153+ tensor.reset(rawTensor);
141 return 0;154 return 0;
142}155}
143 156 
144-int RunXlog1py(const std::vector<int64_t>& shapeX, const std::vector<float>& dataX,157+int RunXlog1py(const std::vector<int64_t>& shapeX, const std::vector<float>& dataX, const std::vector<int64_t>& shapeY,
145- const std::vector<int64_t>& shapeY, const std::vector<float>& dataY,158+ const std::vector<float>& dataY, const std::string& tag, StreamPtr& stream)
146- const std::string& tag, aclrtStream stream)
147{159{
148 LOG_PRINT("--- Test %s ---", tag.c_str());160 LOG_PRINT("--- Test %s ---", tag.c_str());
149 161 
@@ -159,68 +171,78 @@ int RunXlog1py(const std::vector<int64_t>& shapeX, const std::vector<float>& dat
159 }171 }
160 int64_t outSize = GetShapeSize(outShape);172 int64_t outSize = GetShapeSize(outShape);
161 173 
162- LOG_PRINT(" shapeX in=%ld outShape=[%ld,%ld,%ld,%ld]",174+ LOG_PRINT(" shapeX in=%ld outShape=[%ld,%ld,%ld,%ld]", dataX.size(), outShape[0], outShape[1], outShape[2],
163- dataX.size(), outShape[0], outShape[1], outShape[2], outShape[3]);175+ outShape[3]);
164 176 
165 // Compute golden177 // Compute golden
166 auto golden = ComputeGolden(dataX, shapeX, dataY, shapeY, outShape);178 auto golden = ComputeGolden(dataX, shapeX, dataY, shapeY, outShape);
167 179 
168 // Allocate device tensors180 // Allocate device tensors
169- aclTensor* aclX = nullptr; void* devX = nullptr;181+ TensorPtr aclX(nullptr, &aclDestroyTensor);
170- auto ret = CreateAclTensor(dataX, shapeX, &devX, aclDataType::ACL_FLOAT, &aclX);182+ DeviceMemPtr devX(nullptr, &aclrtFree);
183+ auto ret = CreateAclTensor(dataX, shapeX, aclDataType::ACL_FLOAT, devX, aclX);
171 CHECK_RET(ret == 0, "create tensor X failed");184 CHECK_RET(ret == 0, "create tensor X failed");
172 185 
173- aclTensor* aclY = nullptr; void* devY = nullptr;186+ TensorPtr aclY(nullptr, &aclDestroyTensor);
174- ret = CreateAclTensor(dataY, shapeY, &devY, aclDataType::ACL_FLOAT, &aclY);187+ DeviceMemPtr devY(nullptr, &aclrtFree);
188+ ret = CreateAclTensor(dataY, shapeY, aclDataType::ACL_FLOAT, devY, aclY);
175 CHECK_RET(ret == 0, "create tensor Y failed");189 CHECK_RET(ret == 0, "create tensor Y failed");
176 190 
177 std::vector<float> outHostData(outSize, 0);191 std::vector<float> outHostData(outSize, 0);
178- aclTensor* aclOut = nullptr; void* devOut = nullptr;192+ TensorPtr aclOut(nullptr, &aclDestroyTensor);
179- ret = CreateAclTensor(outHostData, outShape, &devOut, aclDataType::ACL_FLOAT, &aclOut);193+ DeviceMemPtr devOut(nullptr, &aclrtFree);
194+ ret = CreateAclTensor(outHostData, outShape, aclDataType::ACL_FLOAT, devOut, aclOut);
180 CHECK_RET(ret == 0, "create tensor Out failed");195 CHECK_RET(ret == 0, "create tensor Out failed");
181 196 
182 // Phase 1: GetWorkspaceSize197 // Phase 1: GetWorkspaceSize
183 uint64_t workspaceSize = 0;198 uint64_t workspaceSize = 0;
184 aclOpExecutor* executor = nullptr;199 aclOpExecutor* executor = nullptr;
185- ret = aclnnXlog1pyGetWorkspaceSize(aclX, aclY, aclOut, &workspaceSize, &executor);200+ ret = aclnnXlog1pyGetWorkspaceSize(aclX.get(), aclY.get(), aclOut.get(), &workspaceSize, &executor);
186 CHECK_RET(ret == ACL_SUCCESS, "aclnnXlog1pyGetWorkspaceSize failed");201 CHECK_RET(ret == ACL_SUCCESS, "aclnnXlog1pyGetWorkspaceSize failed");
187 202 
188- void* workspaceAddr = nullptr;203+ DeviceMemPtr workspaceAddr(nullptr, &aclrtFree);
189- if (workspaceSize > 0) {204+ if (workspaceSize > static_cast<uint64_t>(0)) {
190- ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);205+ void* rawWorkspaceAddr = nullptr;
206+ ret = aclrtMalloc(&rawWorkspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
191 CHECK_RET(ret == ACL_SUCCESS, "allocate workspace failed");207 CHECK_RET(ret == ACL_SUCCESS, "allocate workspace failed");
208+ workspaceAddr.reset(rawWorkspaceAddr);
192 }209 }
193 210 
194 // Phase 2: Execute211 // Phase 2: Execute
195- ret = aclnnXlog1py(workspaceAddr, workspaceSize, executor, stream);212+ ret = aclnnXlog1py(workspaceAddr.get(), workspaceSize, executor, stream.get());
196 CHECK_RET(ret == ACL_SUCCESS, "aclnnXlog1py execute failed");213 CHECK_RET(ret == ACL_SUCCESS, "aclnnXlog1py execute failed");
197 214 
198- ret = aclrtSynchronizeStream(stream);215+ ret = aclrtSynchronizeStream(stream.get());
199 CHECK_RET(ret == ACL_SUCCESS, "aclrtSynchronizeStream failed");216 CHECK_RET(ret == ACL_SUCCESS, "aclrtSynchronizeStream failed");
200 217 
201 // Copy result back218 // Copy result back
202 std::vector<float> npuResult(outSize, 0);219 std::vector<float> npuResult(outSize, 0);
203- ret = aclrtMemcpy(npuResult.data(), outSize * sizeof(float), devOut,220+ ret = aclrtMemcpy(npuResult.data(), outSize * sizeof(float), devOut.get(), outSize * sizeof(float),
204- outSize * sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST);221+ ACL_MEMCPY_DEVICE_TO_HOST);
205 CHECK_RET(ret == ACL_SUCCESS, "copy result D2H failed");222 CHECK_RET(ret == ACL_SUCCESS, "copy result D2H failed");
206 223 
207 // Compare224 // Compare
208 bool pass = CompareResult(golden, npuResult, outShape, tag);225 bool pass = CompareResult(golden, npuResult, outShape, tag);
209 226 
210- // Cleanup
211- aclDestroyTensor(aclX); aclDestroyTensor(aclY); aclDestroyTensor(aclOut);
212- aclrtFree(devX); aclrtFree(devY); aclrtFree(devOut);
213- if (workspaceSize > 0) aclrtFree(workspaceAddr);
214- 
215 return pass ? 0 : -1;227 return pass ? 0 : -1;
216}228}
217 229 
218int main()230int main()
219{231{
220 int32_t deviceId = 0;232 int32_t deviceId = 0;
221- aclrtStream stream;233+ bool initialized = false;
222- auto ret = Init(deviceId, &stream);234+ bool deviceSet = false;
223- CHECK_RET(ret == 0, "Init failed");235+ std::shared_ptr<void> aclGuard(nullptr, [&](void*) {
236+ if (deviceSet) {
237+ aclrtResetDevice(deviceId);
238+ }
239+ if (initialized) {
240+ aclFinalize();
241+ }
242+ });
243+ StreamPtr stream(nullptr, &aclrtDestroyStream);
244+ auto ret = Init(deviceId, stream, initialized, deviceSet);
245+ CHECK_RET(ret == ACL_SUCCESS, "Init failed");
224 246 
225 int numPass = 0, numFail = 0;247 int numPass = 0, numFail = 0;
226 248 
@@ -228,8 +250,14 @@ int main()
228 {250 {
229 std::vector<int64_t> shape = {1, 2, 4, 4};251 std::vector<int64_t> shape = {1, 2, 4, 4};
230 std::vector<float> x(32), y(32);252 std::vector<float> x(32), y(32);
231- for (int i = 0; i < 32; i++) { x[i] = 2.0f; y[i] = 1.0f; }253+ for (int i = 0; i < 32; i++) {
232- if (RunXlog1py(shape, x, shape, y, "same_shape", stream) == 0) numPass++; else numFail++;254+ x[i] = 2.0f;
255+ y[i] = 1.0f;
256+ }
257+ if (RunXlog1py(shape, x, shape, y, "same_shape", stream) == 0)
258+ numPass++;
259+ else
260+ numFail++;
233 }261 }
234 262 
235 // Test 2: broadcast x=[1,2,1,4] y=[1,2,4,4]263 // Test 2: broadcast x=[1,2,1,4] y=[1,2,4,4]
@@ -237,9 +265,14 @@ int main()
237 std::vector<int64_t> shapeX = {1, 2, 1, 4};265 std::vector<int64_t> shapeX = {1, 2, 1, 4};
238 std::vector<int64_t> shapeY = {1, 2, 4, 4};266 std::vector<int64_t> shapeY = {1, 2, 4, 4};
239 std::vector<float> x(8), y(32);267 std::vector<float> x(8), y(32);
240- for (int i = 0; i < 8; i++) x[i] = 3.0f;268+ for (int i = 0; i < 8; i++)
241- for (int i = 0; i < 32; i++) y[i] = 2.0f;269+ x[i] = 3.0f;
242- if (RunXlog1py(shapeX, x, shapeY, y, "broadcast", stream) == 0) numPass++; else numFail++;270+ for (int i = 0; i < 32; i++)
271+ y[i] = 2.0f;
272+ if (RunXlog1py(shapeX, x, shapeY, y, "broadcast", stream) == 0)
273+ numPass++;
274+ else
275+ numFail++;
243 }276 }
244 277 
245 // Test 3: x == 0 boundary case278 // Test 3: x == 0 boundary case
@@ -247,7 +280,10 @@ int main()
247 std::vector<int64_t> shape = {1, 1, 8, 8};280 std::vector<int64_t> shape = {1, 1, 8, 8};
248 std::vector<float> x(64, 0.0f);281 std::vector<float> x(64, 0.0f);
249 std::vector<float> y(64, 100.0f);282 std::vector<float> y(64, 100.0f);
250- if (RunXlog1py(shape, x, shape, y, "x_eq_0", stream) == 0) numPass++; else numFail++;283+ if (RunXlog1py(shape, x, shape, y, "x_eq_0", stream) == 0)
284+ numPass++;
285+ else
286+ numFail++;
251 }287 }
252 288 
253 // Test 4: scalar broadcast x=scalar, y=[4,8,16,16]289 // Test 4: scalar broadcast x=scalar, y=[4,8,16,16]
@@ -257,17 +293,17 @@ int main()
257 std::vector<float> x(1, 2.5f);293 std::vector<float> x(1, 2.5f);
258 int64_t n = 8192;294 int64_t n = 8192;
259 std::vector<float> y(n);295 std::vector<float> y(n);
260- for (int64_t i = 0; i < n; i++) y[i] = 1.0f + 0.1f * (i % 5);296+ for (int64_t i = 0; i < n; i++)
261- if (RunXlog1py(shapeX, x, shapeY, y, "scalar_broadcast", stream) == 0) numPass++; else numFail++;297+ y[i] = 1.0f + 0.1f * (i % 5);
298+ if (RunXlog1py(shapeX, x, shapeY, y, "scalar_broadcast", stream) == 0)
299+ numPass++;
300+ else
301+ numFail++;
262 }302 }
263 303 
264 LOG_PRINT("========================================");304 LOG_PRINT("========================================");
265 LOG_PRINT("ACLNN Xlog1py NPU results: PASS=%d FAIL=%d", numPass, numFail);305 LOG_PRINT("ACLNN Xlog1py NPU results: PASS=%d FAIL=%d", numPass, numFail);
266 LOG_PRINT("========================================");306 LOG_PRINT("========================================");
267 307 
268- aclrtDestroyStream(stream);
269- aclrtResetDevice(deviceId);
270- aclFinalize();
271- 
272 return (numFail == 0) ? 0 : -1;308 return (numFail == 0) ? 0 : -1;
273}309}