已合并
aclnn_example_opapi_ut #260
佐助大王创建于 2025年11月13日
aclnn_example_opapi_ut #260
已合并
共 59 个文件变更+3186-755
| @@ -0,0 +1,160 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请Device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | |||
| 54 | // 调用aclrtMemcpy将Host侧数据拷贝到Device侧内存上 | ||
| 55 | ret = aclrtMemcpy(*deviceAddr, 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); | ||
| 57 | |||
| 58 | // 计算连续tensor的strides | ||
| 59 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 60 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 61 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 62 | } | ||
| 63 | |||
| 64 | // 调用aclCreateTensor接口创建aclTensor | ||
| 65 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 66 | shape.data(), shape.size(), *deviceAddr); | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | int main() { | ||
| 71 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 72 | // 根据自己的实际device填写deviceId | ||
| 73 | int32_t deviceId = 0; | ||
| 74 | aclrtStream stream; | ||
| 75 | auto ret = Init(deviceId, &stream); | ||
| 76 | // check根据自己的需要处理 | ||
| 77 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 78 | |||
| 79 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 80 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 81 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 82 | std::vector<int64_t> weightShape = {2, 2}; | ||
| 83 | std::vector<int64_t> outShape = {2, 2}; | ||
| 84 | void* selfDeviceAddr = nullptr; | ||
| 85 | void* targetDeviceAddr = nullptr; | ||
| 86 | void* weightDeviceAddr = nullptr; | ||
| 87 | void* outDeviceAddr = nullptr; | ||
| 88 | aclTensor* self = nullptr; | ||
| 89 | aclTensor* target = nullptr; | ||
| 90 | aclTensor* weight = nullptr; | ||
| 91 | aclTensor* out = nullptr; | ||
| 92 | std::vector<float> selfHostData = {0.3, 0.3, 0.3, 0.3}; | ||
| 93 | std::vector<float> targetHostData = {0.5, 0.5, 0.5, 0.5}; | ||
| 94 | std::vector<float> weightHostData = {1, 1, 1, 1}; | ||
| 95 | std::vector<float> outHostData = {0, 0, 0, 0}; | ||
| 96 | int64_t reduction = 0; | ||
| 97 | // 创建self aclTensor | ||
| 98 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 99 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 100 | // 创建target aclTensor | ||
| 101 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 102 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 103 | // 创建weight aclTensor | ||
| 104 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 105 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 106 | // 创建out aclTensor | ||
| 107 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 108 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 109 | |||
| 110 | uint64_t workspaceSize = 0; | ||
| 111 | aclOpExecutor* executor; | ||
| 112 | |||
| 113 | // aclnnBinaryCrossEntropy接口调用示例 | ||
| 114 | // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 115 | // 调用aclnnBinaryCrossEntropy第一段接口 | ||
| 116 | ret = aclnnBinaryCrossEntropyGetWorkspaceSize(self, target, weight, reduction, out, &workspaceSize, &executor); | ||
| 117 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropyGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 118 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 119 | void* workspaceAddr = nullptr; | ||
| 120 | if (workspaceSize > 0) { | ||
| 121 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 122 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 123 | } | ||
| 124 | // 调用aclnnBinaryCrossEntropy第二段接口 | ||
| 125 | ret = aclnnBinaryCrossEntropy(workspaceAddr, workspaceSize, executor, stream); | ||
| 126 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropy failed. ERROR: %d\n", ret); return ret); | ||
| 127 | |||
| 128 | // 4. (固定写法)同步等待任务执行结束 | ||
| 129 | ret = aclrtSynchronizeStream(stream); | ||
| 130 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 131 | |||
| 132 | // 5. 获取输出的值,将Device侧内存上的结果拷贝至Host侧,需要根据具体API的接口定义修改 | ||
| 133 | auto size = GetShapeSize(outShape); | ||
| 134 | std::vector<float> resultData(size, 0); | ||
| 135 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 136 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 137 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 138 | for (int64_t i = 0; i < size; i++) { | ||
| 139 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 140 | } | ||
| 141 | |||
| 142 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 143 | aclDestroyTensor(self); | ||
| 144 | aclDestroyTensor(target); | ||
| 145 | aclDestroyTensor(weight); | ||
| 146 | aclDestroyTensor(out); | ||
| 147 | |||
| 148 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 149 | aclrtFree(selfDeviceAddr); | ||
| 150 | aclrtFree(targetDeviceAddr); | ||
| 151 | aclrtFree(weightDeviceAddr); | ||
| 152 | aclrtFree(outDeviceAddr); | ||
| 153 | if (workspaceSize > 0) { | ||
| 154 | aclrtFree(workspaceAddr); | ||
| 155 | } | ||
| 156 | aclrtDestroyStream(stream); | ||
| 157 | aclrtResetDevice(deviceId); | ||
| 158 | aclFinalize(); | ||
| 159 | return 0; | ||
| 160 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_binary_cross_entropy") | 11 | message(STATUS "=== Debug: target_sources add test_binary_cross_entropy") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
Rloss/binary_cross_entropy/tests/ut/op_host/op_api/test_binary_cross_entropy.cpp→loss/binary_cross_entropy/tests/ut/op_host/op_api/test_aclnn_binary_cross_entropy.cpp+1-300
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | #include "level2/aclnn_binary_cross_entropy.h" | 18 | #include "../../../../op_host/op_api/aclnn_binary_cross_entropy.h" |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| @@ -162,23 +162,6 @@ TEST_F(l2_binary_cross_entropy_test, case_reduction_3) { | |||
| 162 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 162 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | //异常输入数据2 | ||
| 166 | TEST_F(l2_binary_cross_entropy_test, case_reduction_1) { | ||
| 167 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 168 | auto target = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 169 | auto weight = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 170 | auto out = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 171 | int64_t reduction = 1; | ||
| 172 | |||
| 173 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 174 | INPUT(self, target, weight, reduction), | ||
| 175 | OUTPUT(out)); | ||
| 176 | |||
| 177 | uint64_t workspace_size = 0; | ||
| 178 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 179 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 180 | } | ||
| 181 | |||
| 182 | //输入shape不一致 | 165 | //输入shape不一致 |
| 183 | TEST_F(l2_binary_cross_entropy_test, case_shape_abnormal) { | 166 | TEST_F(l2_binary_cross_entropy_test, case_shape_abnormal) { |
| 184 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | 167 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); |
| @@ -196,176 +179,6 @@ TEST_F(l2_binary_cross_entropy_test, case_shape_abnormal) { | |||
| 196 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 179 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 197 | } | 180 | } |
| 198 | 181 | ||
| 199 | //数据覆盖 float Reduction::None | ||
| 200 | TEST_F(l2_binary_cross_entropy_test, case_float_reduction_none) { | ||
| 201 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 202 | auto target = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 203 | auto weight = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 204 | auto out = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 205 | int64_t reduction = Reduction::None; | ||
| 206 | |||
| 207 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 208 | INPUT(self, target, weight, reduction), | ||
| 209 | OUTPUT(out)); | ||
| 210 | |||
| 211 | uint64_t workspace_size = 0; | ||
| 212 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 213 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 214 | |||
| 215 | //ut.TestPrecision(); | ||
| 216 | } | ||
| 217 | |||
| 218 | //数据覆盖 float Reduction::None weight为nullptr也支持 | ||
| 219 | TEST_F(l2_binary_cross_entropy_test, case_float_reduction_none_weight_nullptr) { | ||
| 220 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 221 | auto target = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 222 | auto weight = nullptr; | ||
| 223 | auto out = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 224 | int64_t reduction = Reduction::None; | ||
| 225 | |||
| 226 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, INPUT(self, target, weight, reduction), OUTPUT(out)); | ||
| 227 | |||
| 228 | uint64_t workspace_size = 0; | ||
| 229 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 230 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 231 | |||
| 232 | //ut.TestPrecision(); | ||
| 233 | } | ||
| 234 | |||
| 235 | |||
| 236 | //数据覆盖 float Reduction::Sum | ||
| 237 | TEST_F(l2_binary_cross_entropy_test, case_float_reduction_sum) { | ||
| 238 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 239 | auto target = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 240 | auto weight = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 241 | auto out = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 242 | int64_t reduction = Reduction::Sum; | ||
| 243 | |||
| 244 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 245 | INPUT(self, target, weight, reduction), | ||
| 246 | OUTPUT(out)); | ||
| 247 | |||
| 248 | uint64_t workspace_size = 0; | ||
| 249 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 250 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 251 | |||
| 252 | //ut.TestPrecision(); | ||
| 253 | } | ||
| 254 | |||
| 255 | //数据覆盖 float Reduction::Sum | ||
| 256 | TEST_F(l2_binary_cross_entropy_test, case_float_reduction_sum_weight_nullptr) { | ||
| 257 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 258 | auto target = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 259 | auto weight = nullptr; | ||
| 260 | auto out = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 261 | int64_t reduction = Reduction::Sum; | ||
| 262 | |||
| 263 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 264 | INPUT(self, target, weight, reduction), | ||
| 265 | OUTPUT(out)); | ||
| 266 | |||
| 267 | uint64_t workspace_size = 0; | ||
| 268 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 269 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 270 | |||
| 271 | //ut.TestPrecision(); | ||
| 272 | } | ||
| 273 | |||
| 274 | //数据覆盖 float Reduction::Mean | ||
| 275 | TEST_F(l2_binary_cross_entropy_test, case_float_reduction_mean) { | ||
| 276 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 277 | auto target = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 278 | auto weight = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 279 | auto out = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 280 | int64_t reduction = Reduction::Mean; | ||
| 281 | |||
| 282 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 283 | INPUT(self, target, weight, reduction), | ||
| 284 | OUTPUT(out)); | ||
| 285 | |||
| 286 | uint64_t workspace_size = 0; | ||
| 287 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 288 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 289 | |||
| 290 | //ut.TestPrecision(); | ||
| 291 | } | ||
| 292 | |||
| 293 | //数据覆盖 float Reduction::Mean | ||
| 294 | TEST_F(l2_binary_cross_entropy_test, case_float_reduction_mean_weight_nullptr) { | ||
| 295 | auto self = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 296 | auto target = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 297 | auto weight = nullptr; | ||
| 298 | auto out = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 299 | int64_t reduction = Reduction::Mean; | ||
| 300 | |||
| 301 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 302 | INPUT(self, target, weight, reduction), | ||
| 303 | OUTPUT(out)); | ||
| 304 | |||
| 305 | uint64_t workspace_size = 0; | ||
| 306 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 307 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 308 | |||
| 309 | //ut.TestPrecision(); | ||
| 310 | } | ||
| 311 | |||
| 312 | //数据覆盖 float16 Reduction::Mean | ||
| 313 | TEST_F(l2_binary_cross_entropy_test, case_float16_reduction_none) { | ||
| 314 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 315 | auto target = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 316 | auto weight = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 317 | auto out = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 318 | int64_t reduction = Reduction::None; | ||
| 319 | |||
| 320 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 321 | INPUT(self, target, weight, reduction), | ||
| 322 | OUTPUT(out)); | ||
| 323 | |||
| 324 | uint64_t workspace_size = 0; | ||
| 325 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 326 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 327 | |||
| 328 | //ut.TestPrecision(); | ||
| 329 | } | ||
| 330 | |||
| 331 | //数据覆盖 float16 Reduction::Sum | ||
| 332 | TEST_F(l2_binary_cross_entropy_test, case_float16_reduction_sum) { | ||
| 333 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 334 | auto target = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 335 | auto weight = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 336 | auto out = TensorDesc({1}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 337 | int reduction = Reduction::Sum; | ||
| 338 | |||
| 339 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 340 | INPUT(self, target, weight, reduction), | ||
| 341 | OUTPUT(out)); | ||
| 342 | |||
| 343 | uint64_t workspace_size = 0; | ||
| 344 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 345 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 346 | |||
| 347 | //ut.TestPrecision(); | ||
| 348 | } | ||
| 349 | |||
| 350 | //数据覆盖 float16 Reduction::Mean | ||
| 351 | TEST_F(l2_binary_cross_entropy_test, case_float16_reduction_mean) { | ||
| 352 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 353 | auto target = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 354 | auto weight = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 355 | auto out = TensorDesc({1}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 356 | int reduction = Reduction::Mean; | ||
| 357 | |||
| 358 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 359 | INPUT(self, target, weight, reduction), | ||
| 360 | OUTPUT(out)); | ||
| 361 | |||
| 362 | uint64_t workspace_size = 0; | ||
| 363 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 364 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 365 | |||
| 366 | //ut.TestPrecision(); | ||
| 367 | } | ||
| 368 | |||
| 369 | //空tensor float Reduction::None | 182 | //空tensor float Reduction::None |
| 370 | TEST_F(l2_binary_cross_entropy_test, case_fp_empty_tensor_none) { | 183 | TEST_F(l2_binary_cross_entropy_test, case_fp_empty_tensor_none) { |
| 371 | auto self = TensorDesc({0, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | 184 | auto self = TensorDesc({0, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); |
| @@ -404,25 +217,6 @@ TEST_F(l2_binary_cross_entropy_test, case_fp16_empty_tensor_none) { | |||
| 404 | //ut.TestPrecision(); | 217 | //ut.TestPrecision(); |
| 405 | } | 218 | } |
| 406 | 219 | ||
| 407 | //非连续 | ||
| 408 | TEST_F(l2_binary_cross_entropy_test, case_not_contiguous) { | ||
| 409 | auto self = TensorDesc({5, 10}, ACL_FLOAT16, ACL_FORMAT_ND, {1, 5}, 0, {10, 5}).ValueRange(0, 1); | ||
| 410 | auto target = TensorDesc({5, 10}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 411 | auto weight = TensorDesc({5, 10}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 412 | auto out = TensorDesc({5, 10}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 413 | int reduction = Reduction::None; | ||
| 414 | |||
| 415 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 416 | INPUT(self, target, weight, reduction), | ||
| 417 | OUTPUT(out)); | ||
| 418 | |||
| 419 | uint64_t workspace_size = 0; | ||
| 420 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 421 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 422 | |||
| 423 | //ut.TestPrecision(); | ||
| 424 | } | ||
| 425 | |||
| 426 | //输入输出dtype不一致 | 220 | //输入输出dtype不一致 |
| 427 | TEST_F(l2_binary_cross_entropy_test, case_dtype_inconsistent) { | 221 | TEST_F(l2_binary_cross_entropy_test, case_dtype_inconsistent) { |
| 428 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | 222 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); |
| @@ -438,97 +232,4 @@ TEST_F(l2_binary_cross_entropy_test, case_dtype_inconsistent) { | |||
| 438 | uint64_t workspace_size = 0; | 232 | uint64_t workspace_size = 0; |
| 439 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | 233 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); |
| 440 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 234 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 441 | } | ||
| 442 | |||
| 443 | //输入输出format不一致 | ||
| 444 | TEST_F(l2_binary_cross_entropy_test, case_format_inconsistent) { | ||
| 445 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 446 | auto target = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 447 | auto weight = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 448 | auto out = TensorDesc({1}, ACL_FLOAT16, ACL_FORMAT_NCHW).Precision(0.001, 0.001); | ||
| 449 | int reduction = Reduction::Mean; | ||
| 450 | |||
| 451 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 452 | INPUT(self, target, weight, reduction), | ||
| 453 | OUTPUT(out)); | ||
| 454 | |||
| 455 | uint64_t workspace_size = 0; | ||
| 456 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 457 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 458 | |||
| 459 | //ut.TestPrecision(); | ||
| 460 | } | ||
| 461 | |||
| 462 | // format测试 | ||
| 463 | TEST_F(l2_binary_cross_entropy_test, case_format) | ||
| 464 | { | ||
| 465 | vector<aclFormat> ValidList = { | ||
| 466 | ACL_FORMAT_UNDEFINED, | ||
| 467 | ACL_FORMAT_NCHW, | ||
| 468 | ACL_FORMAT_NHWC, | ||
| 469 | ACL_FORMAT_ND, | ||
| 470 | ACL_FORMAT_NC1HWC0, | ||
| 471 | ACL_FORMAT_FRACTAL_Z, | ||
| 472 | ACL_FORMAT_NC1HWC0_C04, | ||
| 473 | ACL_FORMAT_HWCN, | ||
| 474 | ACL_FORMAT_NDHWC, | ||
| 475 | ACL_FORMAT_FRACTAL_NZ, | ||
| 476 | ACL_FORMAT_NCDHW, | ||
| 477 | ACL_FORMAT_NDC1HWC0, | ||
| 478 | ACL_FRACTAL_Z_3D}; | ||
| 479 | |||
| 480 | int length = ValidList.size(); | ||
| 481 | for (int i = 0; i < length; i++) { | ||
| 482 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 483 | auto target = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 484 | auto weight = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 485 | auto out = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).Precision(0.001, 0.001); | ||
| 486 | int reduction = Reduction::None; | ||
| 487 | |||
| 488 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 489 | INPUT(self, target, weight, reduction), | ||
| 490 | OUTPUT(out)); | ||
| 491 | |||
| 492 | uint64_t workspace_size = 0; | ||
| 493 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 494 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 495 | |||
| 496 | //ut.TestPrecision(); | ||
| 497 | } | ||
| 498 | |||
| 499 | for (int i = 0; i < length; i++) { | ||
| 500 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 501 | auto target = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 502 | auto weight = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 503 | auto out = TensorDesc({1}, ACL_FLOAT16, ValidList[i]).Precision(0.001, 0.001); | ||
| 504 | int reduction = Reduction::Mean; | ||
| 505 | |||
| 506 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 507 | INPUT(self, target, weight, reduction), | ||
| 508 | OUTPUT(out)); | ||
| 509 | |||
| 510 | uint64_t workspace_size = 0; | ||
| 511 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 512 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 513 | |||
| 514 | //ut.TestPrecision(); | ||
| 515 | } | ||
| 516 | |||
| 517 | for (int i = 0; i < length; i++) { | ||
| 518 | auto self = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 519 | auto target = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 520 | auto weight = TensorDesc({5, 5}, ACL_FLOAT16, ValidList[i]).ValueRange(0, 1); | ||
| 521 | auto out = TensorDesc({1}, ACL_FLOAT16, ValidList[i]).Precision(0.001, 0.001); | ||
| 522 | int reduction = Reduction::Sum; | ||
| 523 | |||
| 524 | auto ut = OP_API_UT(aclnnBinaryCrossEntropy, | ||
| 525 | INPUT(self, target, weight, reduction), | ||
| 526 | OUTPUT(out)); | ||
| 527 | |||
| 528 | uint64_t workspace_size = 0; | ||
| 529 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 530 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 531 | |||
| 532 | //ut.TestPrecision(); | ||
| 533 | } | ||
| 534 | } | 235 | } |
| @@ -0,0 +1,169 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请Device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | |||
| 54 | // 调用aclrtMemcpy将Host侧数据拷贝到Device侧内存上 | ||
| 55 | ret = aclrtMemcpy(*deviceAddr, 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); | ||
| 57 | |||
| 58 | // 计算连续tensor的strides | ||
| 59 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 60 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 61 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 62 | } | ||
| 63 | |||
| 64 | // 调用aclCreateTensor接口创建aclTensor | ||
| 65 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 66 | shape.data(), shape.size(), *deviceAddr); | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | int main() { | ||
| 71 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 72 | // 根据自己的实际device填写deviceId | ||
| 73 | int32_t deviceId = 0; | ||
| 74 | aclrtStream stream; | ||
| 75 | auto ret = Init(deviceId, &stream); | ||
| 76 | // check根据自己的需要处理 | ||
| 77 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 78 | |||
| 79 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 80 | std::vector<int64_t> gradOutputShape = {2, 2}; | ||
| 81 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 82 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 83 | std::vector<int64_t> weightShape = {2, 2}; | ||
| 84 | std::vector<int64_t> outShape = {2, 2}; | ||
| 85 | void* gradOutputDeviceAddr = nullptr; | ||
| 86 | void* selfDeviceAddr = nullptr; | ||
| 87 | void* targetDeviceAddr = nullptr; | ||
| 88 | void* weightDeviceAddr = nullptr; | ||
| 89 | void* outDeviceAddr = nullptr; | ||
| 90 | aclTensor* gradOutput = nullptr; | ||
| 91 | aclTensor* self = nullptr; | ||
| 92 | aclTensor* target = nullptr; | ||
| 93 | aclTensor* weight = nullptr; | ||
| 94 | aclTensor* out = nullptr; | ||
| 95 | std::vector<float> gradOutputHostData = {0.1, 0.1, 0.1, 0.1}; | ||
| 96 | std::vector<float> selfHostData = {0.3, 0.3, 0.3, 0.3}; | ||
| 97 | std::vector<float> targetHostData = {0.5, 0.5, 0.5, 0.5}; | ||
| 98 | std::vector<float> weightHostData = {1, 1, 1, 1}; | ||
| 99 | std::vector<float> outHostData = {0, 0, 0, 0}; | ||
| 100 | int64_t reduction = 0; | ||
| 101 | // 创建gradOutputaclTensor | ||
| 102 | ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput); | ||
| 103 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 104 | // 创建self aclTensor | ||
| 105 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 106 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 107 | // 创建target aclTensor | ||
| 108 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 109 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 110 | // 创建weight aclTensor | ||
| 111 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 112 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 113 | // 创建out aclTensor | ||
| 114 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 115 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 116 | |||
| 117 | uint64_t workspaceSize = 0; | ||
| 118 | aclOpExecutor* executor; | ||
| 119 | |||
| 120 | // aclnnBinaryCrossEntropyBackward接口调用示例 | ||
| 121 | // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 122 | // 调用aclnnBinaryCrossEntropyBackward第一段接口 | ||
| 123 | ret = aclnnBinaryCrossEntropyBackwardGetWorkspaceSize(gradOutput, self, target, weight, reduction, out, &workspaceSize, &executor); | ||
| 124 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropyBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 125 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 126 | void* workspaceAddr = nullptr; | ||
| 127 | if (workspaceSize > 0) { | ||
| 128 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 129 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 130 | } | ||
| 131 | // 调用aclnnBinaryCrossEntropyBackward第二段接口 | ||
| 132 | ret = aclnnBinaryCrossEntropyBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 133 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropyBackward failed. ERROR: %d\n", ret); return ret); | ||
| 134 | |||
| 135 | // 4. (固定写法)同步等待任务执行结束 | ||
| 136 | ret = aclrtSynchronizeStream(stream); | ||
| 137 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 138 | |||
| 139 | // 5. 获取输出的值,将Device侧内存上的结果拷贝至Host侧,需要根据具体API的接口定义修改 | ||
| 140 | auto size = GetShapeSize(outShape); | ||
| 141 | std::vector<float> resultData(size, 0); | ||
| 142 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 143 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 144 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 145 | for (int64_t i = 0; i < size; i++) { | ||
| 146 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 147 | } | ||
| 148 | |||
| 149 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 150 | aclDestroyTensor(gradOutput); | ||
| 151 | aclDestroyTensor(self); | ||
| 152 | aclDestroyTensor(target); | ||
| 153 | aclDestroyTensor(weight); | ||
| 154 | aclDestroyTensor(out); | ||
| 155 | |||
| 156 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 157 | aclrtFree(gradOutputDeviceAddr); | ||
| 158 | aclrtFree(selfDeviceAddr); | ||
| 159 | aclrtFree(targetDeviceAddr); | ||
| 160 | aclrtFree(weightDeviceAddr); | ||
| 161 | aclrtFree(outDeviceAddr); | ||
| 162 | if (workspaceSize > 0) { | ||
| 163 | aclrtFree(workspaceAddr); | ||
| 164 | } | ||
| 165 | aclrtDestroyStream(stream); | ||
| 166 | aclrtResetDevice(deviceId); | ||
| 167 | aclFinalize(); | ||
| 168 | return 0; | ||
| 169 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_binary_cross_entropy_grad") | 11 | message(STATUS "=== Debug: target_sources add test_binary_cross_entropy_grad") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
Rloss/binary_cross_entropy_grad/tests/ut/op_host/op_api/test_binary_cross_entropy_backward.cpp→loss/binary_cross_entropy_grad/tests/ut/op_host/op_api/test_aclnn_binary_cross_entropy_backward.cpp+1-1
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #include "level2/aclnn_binary_cross_entropy_backward.h" | 14 | #include "../../../../op_host/op_api/aclnn_binary_cross_entropy_backward.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| @@ -9,3 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 12 | if(UT_TEST_ALL OR OP_API_UT) | ||
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | #include "level2/aclnn_ctc_loss.h" | 13 | #include "../../../../op_host/op_api/aclnn_ctc_loss.h" |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| @@ -62,56 +62,6 @@ TEST_F(l2_ctc_loss_test, test_ctc_loss_logprobs_is_empty_tensor_normal) { | |||
| 62 | ut.TestPrecision(); | 62 | ut.TestPrecision(); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | // 正常情況double | ||
| 66 | TEST_F(l2_ctc_loss_test, test_ctc_loss_double_all_normal) { | ||
| 67 | auto logProbs = TensorDesc({T, N, C}, ACL_DOUBLE, ACL_FORMAT_ND) | ||
| 68 | .ValueRange(-4, 0); | ||
| 69 | auto targets = TensorDesc({N, S}, ACL_INT64, ACL_FORMAT_ND) | ||
| 70 | .ValueRange(1, 4); | ||
| 71 | |||
| 72 | auto inputLengths = IntArrayDesc(vector<int64_t>{5, 9, 7, 12}); | ||
| 73 | auto targetLengths = IntArrayDesc(vector<int64_t>{7, 5, 7, 1}); | ||
| 74 | |||
| 75 | int64_t blank = 0; | ||
| 76 | bool zeroInfinity = false; | ||
| 77 | |||
| 78 | auto negLogLikelihoodOut = TensorDesc({N}, ACL_DOUBLE, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 79 | auto logAlphaOut = TensorDesc({N, T, LOGALPHA_X}, ACL_DOUBLE, ACL_FORMAT_ND).Precision(0.0001, 0.0001).ValidCount(0); | ||
| 80 | |||
| 81 | auto ut = OP_API_UT(aclnnCtcLoss, INPUT(logProbs, targets, inputLengths, targetLengths, blank, zeroInfinity), OUTPUT(negLogLikelihoodOut, logAlphaOut)); | ||
| 82 | |||
| 83 | uint64_t workspaceSize = 0; | ||
| 84 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 85 | EXPECT_EQ(aclRet, ACLNN_SUCCESS); | ||
| 86 | // SAMPLE: precision simulate | ||
| 87 | ut.TestPrecision(); | ||
| 88 | } | ||
| 89 | |||
| 90 | // 正常情況double int32 | ||
| 91 | TEST_F(l2_ctc_loss_test, test_ctc_loss_double_and_int32_all_normal) { | ||
| 92 | auto logProbs = TensorDesc({T, N, C}, ACL_DOUBLE, ACL_FORMAT_ND) | ||
| 93 | .ValueRange(-4, 0); | ||
| 94 | auto targets = TensorDesc({N, S}, ACL_INT32, ACL_FORMAT_ND) | ||
| 95 | .ValueRange(1, 4); | ||
| 96 | |||
| 97 | auto inputLengths = IntArrayDesc(vector<int64_t>{5, 9, 7, 12}); | ||
| 98 | auto targetLengths = IntArrayDesc(vector<int64_t>{7, 5, 7, 1}); | ||
| 99 | |||
| 100 | int64_t blank = 0; | ||
| 101 | bool zeroInfinity = false; | ||
| 102 | |||
| 103 | auto negLogLikelihoodOut = TensorDesc({N}, ACL_DOUBLE, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 104 | auto logAlphaOut = TensorDesc({N, T, LOGALPHA_X}, ACL_DOUBLE, ACL_FORMAT_ND).Precision(0.0001, 0.0001).ValidCount(0); | ||
| 105 | |||
| 106 | auto ut = OP_API_UT(aclnnCtcLoss, INPUT(logProbs, targets, inputLengths, targetLengths, blank, zeroInfinity), OUTPUT(negLogLikelihoodOut, logAlphaOut)); | ||
| 107 | |||
| 108 | uint64_t workspaceSize = 0; | ||
| 109 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 110 | EXPECT_EQ(aclRet, ACLNN_SUCCESS); | ||
| 111 | // SAMPLE: precision simulate | ||
| 112 | ut.TestPrecision(); | ||
| 113 | } | ||
| 114 | |||
| 115 | // ============以下为异常拦截场景 | 65 | // ============以下为异常拦截场景 |
| 116 | // output is null | 66 | // output is null |
| 117 | TEST_F(l2_ctc_loss_test, test_ctc_loss_output_is_null) { | 67 | TEST_F(l2_ctc_loss_test, test_ctc_loss_output_is_null) { |
| @@ -8,4 +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 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 11 | if(UT_TEST_ALL OR OP_API_UT) |
| 12 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 13 | endif() | ||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | #include "level2/aclnn_ctc_loss_backward.h" | 13 | #include "../../../../op_host/op_api/aclnn_ctc_loss_backward.h" |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| @@ -159,42 +159,6 @@ TEST_F(l2_ctc_loss_backward_test, ascend910B2_test_ctc_loss_backward_float_v3_al | |||
| 159 | // ut.TestPrecision(); | 159 | // ut.TestPrecision(); |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | // 正常情況double | ||
| 163 | TEST_F(l2_ctc_loss_backward_test, test_ctc_loss_backward_double_all_normal) { | ||
| 164 | auto gradOut = TensorDesc({NN}, ACL_DOUBLE, ACL_FORMAT_ND) | ||
| 165 | .ValueRange(-10, 10) | ||
| 166 | .Value(vector<float>{1.0, 1.0, 1.0, 1.0}); | ||
| 167 | |||
| 168 | auto logProbs = TensorDesc({TT, NN, CC}, ACL_DOUBLE, ACL_FORMAT_ND) | ||
| 169 | .ValueRange(-10, 10); | ||
| 170 | |||
| 171 | auto targets = TensorDesc({NN, SS}, ACL_INT64, ACL_FORMAT_ND) | ||
| 172 | .ValueRange(-10, 10); | ||
| 173 | |||
| 174 | auto inputLengths = IntArrayDesc(vector<int64_t>{TT, TT, TT, TT}); | ||
| 175 | |||
| 176 | auto targetLengths = IntArrayDesc(vector<int64_t>{SS, SS, SS, SS}); | ||
| 177 | |||
| 178 | auto negLogLikelihood = TensorDesc({NN}, ACL_DOUBLE, ACL_FORMAT_ND) | ||
| 179 | .ValueRange(-10, 10); | ||
| 180 | |||
| 181 | auto logAlpha = TensorDesc({NN, TT, 15}, ACL_DOUBLE, ACL_FORMAT_ND) | ||
| 182 | .ValueRange(-10, 10); | ||
| 183 | |||
| 184 | int64_t blank = 0; | ||
| 185 | bool zeroInfinity = false; | ||
| 186 | |||
| 187 | auto out = TensorDesc({TT, NN, CC}, ACL_DOUBLE, ACL_FORMAT_ND); | ||
| 188 | |||
| 189 | auto ut = OP_API_UT(aclnnCtcLossBackward, INPUT(gradOut, logProbs, targets, inputLengths, targetLengths, negLogLikelihood, logAlpha, blank, zeroInfinity), OUTPUT(out)); | ||
| 190 | |||
| 191 | uint64_t workspaceSize = 0; | ||
| 192 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 193 | EXPECT_EQ(aclRet, ACLNN_SUCCESS); | ||
| 194 | // SAMPLE: precision simulate | ||
| 195 | // ut.TestPrecision(); | ||
| 196 | } | ||
| 197 | |||
| 198 | // output is null | 162 | // output is null |
| 199 | TEST_F(l2_ctc_loss_backward_test, test_ctc_loss_backward_output_is_null) { | 163 | TEST_F(l2_ctc_loss_backward_test, test_ctc_loss_backward_output_is_null) { |
| 200 | auto gradOut = TensorDesc({NN}, ACL_DOUBLE, ACL_FORMAT_ND) | 164 | auto gradOut = TensorDesc({NN}, ACL_DOUBLE, ACL_FORMAT_ND) |
| @@ -8,4 +8,4 @@ | |||
| 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 | add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE ctc_loss_v3 ACLNNTYPE aclnn_exclude) | 11 | add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE ctc_loss_v3 ACLNNTYPE aclnn_exclude DEPENDENCIES ctc_loss_v2) |
| @@ -8,4 +8,4 @@ | |||
| 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 | add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE ctc_loss_v3_grad ACLNNTYPE aclnn_exclude) | 11 | add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE ctc_loss_v3_grad ACLNNTYPE aclnn_exclude DEPENDENCIES ctc_loss_v2_grad) |
| @@ -0,0 +1,159 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | |||
| 54 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 55 | ret = aclrtMemcpy(*deviceAddr, 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); | ||
| 57 | |||
| 58 | // 计算连续tensor的strides | ||
| 59 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 60 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 61 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 62 | } | ||
| 63 | |||
| 64 | // 调用aclCreateTensor接口创建aclTensor | ||
| 65 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 66 | shape.data(), shape.size(), *deviceAddr); | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | int main() { | ||
| 71 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 72 | // 根据自己的实际device填写deviceId | ||
| 73 | int32_t deviceId = 0; | ||
| 74 | aclrtStream stream; | ||
| 75 | auto ret = Init(deviceId, &stream); | ||
| 76 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 77 | |||
| 78 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 79 | std::vector<int64_t> gradOutputShape = {2, 2}; | ||
| 80 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 81 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 82 | std::vector<int64_t> outShape = {2, 2}; | ||
| 83 | void* gradOutputDeviceAddr = nullptr; | ||
| 84 | void* selfDeviceAddr = nullptr; | ||
| 85 | void* targetDeviceAddr = nullptr; | ||
| 86 | void* outDeviceAddr = nullptr; | ||
| 87 | aclTensor* gradOutput = nullptr; | ||
| 88 | aclTensor* self = nullptr; | ||
| 89 | aclTensor* target = nullptr; | ||
| 90 | aclTensor* out = nullptr; | ||
| 91 | std::vector<float> gradOutputHostData = {2, 3, 5, 8}; | ||
| 92 | std::vector<float> selfHostData = {2, 3, 5, 8}; | ||
| 93 | std::vector<float> targetHostData = {2, 3, 5, 8}; | ||
| 94 | std::vector<float> outHostData = {2, 3, 5, 8}; | ||
| 95 | int64_t reduction = 0; | ||
| 96 | bool logTarget = false; | ||
| 97 | // 创建gradOutput aclTensor | ||
| 98 | ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput); | ||
| 99 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 100 | // 创建self aclTensor | ||
| 101 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 102 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 103 | // 创建target aclTensor | ||
| 104 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 105 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 106 | // 创建out aclTensor | ||
| 107 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 108 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 109 | |||
| 110 | // 3. 调用CANN算子库API | ||
| 111 | uint64_t workspaceSize = 0; | ||
| 112 | aclOpExecutor* executor; | ||
| 113 | // 调用aclnnKlDivBackward第一段接口 | ||
| 114 | ret = aclnnKlDivBackwardGetWorkspaceSize(gradOutput, self, target, reduction, logTarget, out, &workspaceSize, &executor); | ||
| 115 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnKlDivBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 116 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 117 | void* workspaceAddr = nullptr; | ||
| 118 | if (workspaceSize > 0) { | ||
| 119 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 120 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 121 | } | ||
| 122 | // 调用aclnnKlDivBackward第二段接口 | ||
| 123 | ret = aclnnKlDivBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 124 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnKlDivBackward failed. ERROR: %d\n", ret); return ret); | ||
| 125 | |||
| 126 | // 4. (固定写法)同步等待任务执行结束 | ||
| 127 | ret = aclrtSynchronizeStream(stream); | ||
| 128 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 129 | |||
| 130 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 131 | auto size = GetShapeSize(outShape); | ||
| 132 | std::vector<float> resultData(size, 0); | ||
| 133 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), | ||
| 134 | outDeviceAddr, size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 135 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy resultData from device to host failed. ERROR: %d\n", ret); | ||
| 136 | return ret); | ||
| 137 | for (int64_t i = 0; i < size; i++) { | ||
| 138 | LOG_PRINT("resultData[%ld] is: %f\n", i, resultData[i]); | ||
| 139 | } | ||
| 140 | |||
| 141 | // 6. 释放aclTensor,需要根据具体API的接口定义修改 | ||
| 142 | aclDestroyTensor(gradOutput); | ||
| 143 | aclDestroyTensor(self); | ||
| 144 | aclDestroyTensor(target); | ||
| 145 | aclDestroyTensor(out); | ||
| 146 | |||
| 147 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 148 | aclrtFree(gradOutputDeviceAddr); | ||
| 149 | aclrtFree(selfDeviceAddr); | ||
| 150 | aclrtFree(targetDeviceAddr); | ||
| 151 | aclrtFree(outDeviceAddr); | ||
| 152 | if (workspaceSize > 0) { | ||
| 153 | aclrtFree(workspaceAddr); | ||
| 154 | } | ||
| 155 | aclrtDestroyStream(stream); | ||
| 156 | aclrtResetDevice(deviceId); | ||
| 157 | aclFinalize(); | ||
| 158 | return 0; | ||
| 159 | } | ||
| @@ -9,3 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 12 | if(UT_TEST_ALL OR OP_API_UT) | ||
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | #include "level2/aclnn_kl_div_backward.h" | 13 | #include "../../../../op_host/op_api/aclnn_kl_div_backward.h" |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| @@ -0,0 +1,159 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造gradOutput | ||
| 78 | std::vector<int64_t> gradOutputShape = {2, 2}; | ||
| 79 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 80 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 81 | std::vector<int64_t> gradInputShape = {2, 2}; | ||
| 82 | void* gradOutputDeviceAddr = nullptr; | ||
| 83 | void* selfDeviceAddr = nullptr; | ||
| 84 | void* targetDeviceAddr = nullptr; | ||
| 85 | void* gradInputDeviceAddr = nullptr; | ||
| 86 | aclTensor* gradOutput = nullptr; | ||
| 87 | aclTensor* self = nullptr; | ||
| 88 | aclTensor* target = nullptr; | ||
| 89 | aclTensor* gradInput = nullptr; | ||
| 90 | std::vector<float> gradOutputHostData = {0, 1, 2, 3}; | ||
| 91 | std::vector<float> selfHostData = {0, 1, 2, 3}; | ||
| 92 | std::vector<float> targetHostData = {1, 1, 1, 1}; | ||
| 93 | std::vector<float> gradInputHostData(4, 0); | ||
| 94 | // 创建gradOutput aclTensor | ||
| 95 | ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, | ||
| 96 | aclDataType::ACL_FLOAT, &gradOutput); | ||
| 97 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 98 | // 创建self aclTensor | ||
| 99 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 100 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 101 | // 创建target aclTensor | ||
| 102 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 103 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 104 | // 创建gradInput aclTensor | ||
| 105 | ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput); | ||
| 106 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 107 | // 创建reduction | ||
| 108 | int64_t reduction = 1; | ||
| 109 | |||
| 110 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 111 | uint64_t workspaceSize = 0; | ||
| 112 | aclOpExecutor* executor; | ||
| 113 | // 调用aclnnL1LossBackward第一段接口 | ||
| 114 | ret = aclnnL1LossBackwardGetWorkspaceSize(gradOutput, self, target, reduction, gradInput, &workspaceSize, &executor); | ||
| 115 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnL1LossBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); | ||
| 116 | return ret); | ||
| 117 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 118 | void* workspaceAddr = nullptr; | ||
| 119 | if (workspaceSize > 0) { | ||
| 120 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 121 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 122 | } | ||
| 123 | // 调用aclnnL1LossBackward第二段接口 | ||
| 124 | ret = aclnnL1LossBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 125 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnL1LossBackward failed. ERROR: %d\n", ret); return ret); | ||
| 126 | |||
| 127 | // 4. (固定写法)同步等待任务执行结束 | ||
| 128 | ret = aclrtSynchronizeStream(stream); | ||
| 129 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 130 | |||
| 131 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 132 | auto size = GetShapeSize(gradInputShape); | ||
| 133 | std::vector<float> resultData(size, 0); | ||
| 134 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr, | ||
| 135 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 136 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 137 | for (int64_t i = 0; i < size; i++) { | ||
| 138 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 139 | } | ||
| 140 | |||
| 141 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 142 | aclDestroyTensor(gradOutput); | ||
| 143 | aclDestroyTensor(self); | ||
| 144 | aclDestroyTensor(target); | ||
| 145 | aclDestroyTensor(gradInput); | ||
| 146 | |||
| 147 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 148 | aclrtFree(gradOutputDeviceAddr); | ||
| 149 | aclrtFree(selfDeviceAddr); | ||
| 150 | aclrtFree(targetDeviceAddr); | ||
| 151 | aclrtFree(gradInputDeviceAddr); | ||
| 152 | if (workspaceSize > 0) { | ||
| 153 | aclrtFree(workspaceAddr); | ||
| 154 | } | ||
| 155 | aclrtDestroyStream(stream); | ||
| 156 | aclrtResetDevice(deviceId); | ||
| 157 | aclFinalize(); | ||
| 158 | return 0; | ||
| 159 | } | ||
| @@ -9,3 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 12 | if(UT_TEST_ALL OR OP_API_UT) | ||
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -10,7 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | #include "level2/aclnn_l1_loss_backward.h" | 13 | #include "../../../../op_host/op_api/aclnn_l1_loss_backward.h" |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | 16 | ||
| @@ -346,27 +346,6 @@ TEST_F(l2_l1_loss_backward_test, aclnnL1LossBackward_16_aclnnL1LossBackward_erro | |||
| 346 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 346 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | TEST_F(l2_l1_loss_backward_test, aclnnL1LossBackward_17_aclnnL1LossBackward_diff_input_dtype) | ||
| 350 | { | ||
| 351 | auto gradOutputDesc = TensorDesc({6, 2, 1, 2}, ACL_INT32, ACL_FORMAT_ND).ValueRange(-2, 2); | ||
| 352 | auto selfDesc = TensorDesc({6, 2, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-2, 2); | ||
| 353 | auto targetDesc = TensorDesc({6, 2, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-2, 2); | ||
| 354 | int64_t reduction = 0; | ||
| 355 | |||
| 356 | auto outDesc = TensorDesc({6, 2, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 357 | |||
| 358 | auto ut = OP_API_UT(aclnnL1LossBackward, INPUT(gradOutputDesc, selfDesc, targetDesc, reduction), OUTPUT(outDesc)); | ||
| 359 | // SAMPLE: only test GetWorkspaceSize | ||
| 360 | uint64_t workspace_size = 0; | ||
| 361 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 362 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 363 | |||
| 364 | auto ut_2 = OP_API_UT(aclnnL1LossBackward, INPUT(targetDesc, selfDesc, gradOutputDesc, reduction), OUTPUT(outDesc)); | ||
| 365 | // SAMPLE: only test GetWorkspaceSize | ||
| 366 | aclRet = ut_2.TestGetWorkspaceSize(&workspace_size); | ||
| 367 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 368 | } | ||
| 369 | |||
| 370 | TEST_F(l2_l1_loss_backward_test, aclnnL1LossBackward_18_aclnnL1LossBackward_input_error_shape_len) | 349 | TEST_F(l2_l1_loss_backward_test, aclnnL1LossBackward_18_aclnnL1LossBackward_input_error_shape_len) |
| 371 | { | 350 | { |
| 372 | auto tensorDesc9 = TensorDesc({2, 3, 4, 5, 6, 7, 8, 9, 10}, ACL_INT32, ACL_FORMAT_ND).ValueRange(-2, 2); | 351 | auto tensorDesc9 = TensorDesc({2, 3, 4, 5, 6, 7, 8, 9, 10}, ACL_INT32, ACL_FORMAT_ND).ValueRange(-2, 2); |
| @@ -0,0 +1,148 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 79 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 80 | std::vector<int64_t> outShape = {}; | ||
| 81 | void* selfDeviceAddr = nullptr; | ||
| 82 | void* targetDeviceAddr = nullptr; | ||
| 83 | void* outDeviceAddr = nullptr; | ||
| 84 | aclTensor* self = nullptr; | ||
| 85 | aclTensor* target = nullptr; | ||
| 86 | aclTensor* out = nullptr; | ||
| 87 | std::vector<float> selfHostData = {0, 1, 2, 3}; | ||
| 88 | std::vector<float> targetHostData = {1, 1, 1, 1}; | ||
| 89 | std::vector<float> outHostData = {0}; | ||
| 90 | // 创建self aclTensor | ||
| 91 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 92 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 93 | // 创建target aclTensor | ||
| 94 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 95 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 96 | // 创建out aclTensor | ||
| 97 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 98 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 99 | // 创建reduction | ||
| 100 | int64_t reduction = 1; | ||
| 101 | |||
| 102 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 103 | uint64_t workspaceSize = 0; | ||
| 104 | aclOpExecutor* executor; | ||
| 105 | // 调用aclnnL1Loss第一段接口 | ||
| 106 | ret = aclnnL1LossGetWorkspaceSize(self, target, reduction, out, &workspaceSize, &executor); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnL1LossGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 108 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 109 | void* workspaceAddr = nullptr; | ||
| 110 | if (workspaceSize > 0) { | ||
| 111 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 112 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 113 | } | ||
| 114 | // 调用aclnnL1Loss第二段接口 | ||
| 115 | ret = aclnnL1Loss(workspaceAddr, workspaceSize, executor, stream); | ||
| 116 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnL1Loss failed. ERROR: %d\n", ret); return ret); | ||
| 117 | |||
| 118 | // 4. (固定写法)同步等待任务执行结束 | ||
| 119 | ret = aclrtSynchronizeStream(stream); | ||
| 120 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 121 | |||
| 122 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 123 | auto size = GetShapeSize(outShape); | ||
| 124 | std::vector<float> resultData(size, 0); | ||
| 125 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 126 | size * sizeof(resultData[0]), 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); | ||
| 128 | for (int64_t i = 0; i < size; i++) { | ||
| 129 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 130 | } | ||
| 131 | |||
| 132 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 133 | aclDestroyTensor(self); | ||
| 134 | aclDestroyTensor(target); | ||
| 135 | aclDestroyTensor(out); | ||
| 136 | |||
| 137 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 138 | aclrtFree(selfDeviceAddr); | ||
| 139 | aclrtFree(targetDeviceAddr); | ||
| 140 | aclrtFree(outDeviceAddr); | ||
| 141 | if (workspaceSize > 0) { | ||
| 142 | aclrtFree(workspaceAddr); | ||
| 143 | } | ||
| 144 | aclrtDestroyStream(stream); | ||
| 145 | aclrtResetDevice(deviceId); | ||
| 146 | aclFinalize(); | ||
| 147 | return 0; | ||
| 148 | } | ||
| @@ -9,3 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 11 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 12 | if(UT_TEST_ALL OR OP_API_UT) | ||
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #include "level2/aclnn_l1_loss.h" | 14 | #include "../../../../op_host/op_api/aclnn_l1_loss.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| @@ -69,44 +69,6 @@ TEST_F(l2_l1_loss_test, aclnnL1Loss_02_float16_nd_mean) | |||
| 69 | ut.TestPrecision(); | 69 | ut.TestPrecision(); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | TEST_F(l2_l1_loss_test, aclnnL1Loss_03_float_float16_hd_sum) | ||
| 73 | { | ||
| 74 | auto selfDesc = TensorDesc({2, 2}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 75 | auto targetDesc = TensorDesc({2, 2}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 76 | int64_t reduction = 2; | ||
| 77 | |||
| 78 | auto outDesc = TensorDesc({}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 79 | |||
| 80 | auto ut = OP_API_UT(aclnnL1Loss, INPUT(selfDesc, targetDesc, reduction), OUTPUT(outDesc)); | ||
| 81 | |||
| 82 | // SAMPLE: only test GetWorkspaceSize | ||
| 83 | uint64_t workspace_size = 0; | ||
| 84 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 85 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 86 | |||
| 87 | // SAMPLE: precision simulate | ||
| 88 | ut.TestPrecision(); | ||
| 89 | } | ||
| 90 | |||
| 91 | TEST_F(l2_l1_loss_test, aclnnL1Loss_04_float16_float_hd_mean) | ||
| 92 | { | ||
| 93 | auto selfDesc = TensorDesc({2, 2}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 94 | auto targetDesc = TensorDesc({2, 2}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 95 | int64_t reduction = 1; | ||
| 96 | |||
| 97 | auto outDesc = TensorDesc({}, ACL_FLOAT, ACL_FORMAT_NDHWC).Precision(0.001, 0.001); | ||
| 98 | |||
| 99 | auto ut = OP_API_UT(aclnnL1Loss, INPUT(selfDesc, targetDesc, reduction), OUTPUT(outDesc)); | ||
| 100 | |||
| 101 | // SAMPLE: only test GetWorkspaceSize | ||
| 102 | uint64_t workspace_size = 0; | ||
| 103 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 104 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 105 | |||
| 106 | // SAMPLE: precision simulate | ||
| 107 | ut.TestPrecision(); | ||
| 108 | } | ||
| 109 | |||
| 110 | TEST_F(l2_l1_loss_test, aclnnL1Loss_05_float_nd_empty_tensor_none) | 72 | TEST_F(l2_l1_loss_test, aclnnL1Loss_05_float_nd_empty_tensor_none) |
| 111 | { | 73 | { |
| 112 | auto selfDesc = TensorDesc({1, 0, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND); | 74 | auto selfDesc = TensorDesc({1, 0, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND); |
| @@ -0,0 +1,148 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 79 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 80 | std::vector<int64_t> outShape = {}; | ||
| 81 | void* selfDeviceAddr = nullptr; | ||
| 82 | void* targetDeviceAddr = nullptr; | ||
| 83 | void* outDeviceAddr = nullptr; | ||
| 84 | aclTensor* self = nullptr; | ||
| 85 | aclTensor* target = nullptr; | ||
| 86 | aclTensor* out = nullptr; | ||
| 87 | std::vector<float> selfHostData = {0, 1, 2, 3}; | ||
| 88 | std::vector<float> targetHostData = {1, 1, 1, 1}; | ||
| 89 | std::vector<float> outHostData = {0}; | ||
| 90 | // 创建self aclTensor | ||
| 91 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 92 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 93 | // 创建target aclTensor | ||
| 94 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 95 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 96 | // 创建out aclTensor | ||
| 97 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 98 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 99 | // 创建reduction | ||
| 100 | int64_t reduction = 1; | ||
| 101 | |||
| 102 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 103 | uint64_t workspaceSize = 0; | ||
| 104 | aclOpExecutor* executor; | ||
| 105 | // 调用aclnnMseLoss第一段接口 | ||
| 106 | ret = aclnnMseLossGetWorkspaceSize(self, target, reduction, out, &workspaceSize, &executor); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMseLossGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 108 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 109 | void* workspaceAddr = nullptr; | ||
| 110 | if (workspaceSize > 0) { | ||
| 111 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 112 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 113 | } | ||
| 114 | // 调用aclnnMseLoss第二段接口 | ||
| 115 | ret = aclnnMseLoss(workspaceAddr, workspaceSize, executor, stream); | ||
| 116 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMseLoss failed. ERROR: %d\n", ret); return ret); | ||
| 117 | |||
| 118 | // 4. (固定写法)同步等待任务执行结束 | ||
| 119 | ret = aclrtSynchronizeStream(stream); | ||
| 120 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 121 | |||
| 122 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 123 | auto size = GetShapeSize(outShape); | ||
| 124 | std::vector<float> resultData(size, 0); | ||
| 125 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 126 | size * sizeof(resultData[0]), 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); | ||
| 128 | for (int64_t i = 0; i < size; i++) { | ||
| 129 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 130 | } | ||
| 131 | |||
| 132 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 133 | aclDestroyTensor(self); | ||
| 134 | aclDestroyTensor(target); | ||
| 135 | aclDestroyTensor(out); | ||
| 136 | |||
| 137 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 138 | aclrtFree(selfDeviceAddr); | ||
| 139 | aclrtFree(targetDeviceAddr); | ||
| 140 | aclrtFree(outDeviceAddr); | ||
| 141 | if (workspaceSize > 0) { | ||
| 142 | aclrtFree(workspaceAddr); | ||
| 143 | } | ||
| 144 | aclrtDestroyStream(stream); | ||
| 145 | aclrtResetDevice(deviceId); | ||
| 146 | aclFinalize(); | ||
| 147 | return 0; | ||
| 148 | } | ||
| @@ -0,0 +1,149 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 79 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 80 | std::vector<int64_t> outShape = {2}; | ||
| 81 | void* selfDeviceAddr = nullptr; | ||
| 82 | void* targetDeviceAddr = nullptr; | ||
| 83 | void* outDeviceAddr = nullptr; | ||
| 84 | aclTensor* self = nullptr; | ||
| 85 | aclTensor* target = nullptr; | ||
| 86 | aclTensor* out = nullptr; | ||
| 87 | std::vector<float> selfHostData = {0, 1, 2, 3}; | ||
| 88 | std::vector<float> targetHostData = {1, 1, 1, 1}; | ||
| 89 | std::vector<float> outHostData(2, 0); | ||
| 90 | // 创建self aclTensor | ||
| 91 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 92 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 93 | // 创建target aclTensor | ||
| 94 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 95 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 96 | // 创建out aclTensor | ||
| 97 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 98 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 99 | // 创建reduction | ||
| 100 | int64_t reduction = 1; | ||
| 101 | |||
| 102 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 103 | uint64_t workspaceSize = 0; | ||
| 104 | aclOpExecutor* executor; | ||
| 105 | // 调用aclnnMseLossOut第一段接口 | ||
| 106 | ret = aclnnMseLossOutGetWorkspaceSize(self, target, reduction, out, &workspaceSize, &executor); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMseLossOutGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 108 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 109 | void* workspaceAddr = nullptr; | ||
| 110 | if (workspaceSize > 0) { | ||
| 111 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 112 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 113 | } | ||
| 114 | // 调用aclnnMseLossOut第二段接口 | ||
| 115 | ret = aclnnMseLossOut(workspaceAddr, workspaceSize, executor, stream); | ||
| 116 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMseLossOut failed. ERROR: %d\n", ret); return ret); | ||
| 117 | |||
| 118 | // 4. (固定写法)同步等待任务执行结束 | ||
| 119 | ret = aclrtSynchronizeStream(stream); | ||
| 120 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 121 | |||
| 122 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 123 | auto size = GetShapeSize(outShape); | ||
| 124 | std::vector<float> resultData(size, 0); | ||
| 125 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 126 | size * sizeof(resultData[0]), 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); | ||
| 128 | for (int64_t i = 0; i < size; i++) { | ||
| 129 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 130 | } | ||
| 131 | |||
| 132 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 133 | aclDestroyTensor(self); | ||
| 134 | aclDestroyTensor(target); | ||
| 135 | aclDestroyTensor(out); | ||
| 136 | |||
| 137 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 138 | aclrtFree(selfDeviceAddr); | ||
| 139 | aclrtFree(targetDeviceAddr); | ||
| 140 | aclrtFree(outDeviceAddr); | ||
| 141 | if(workspaceSize > 0) { | ||
| 142 | aclrtFree(workspaceAddr); | ||
| 143 | } | ||
| 144 | aclrtDestroyStream(stream); | ||
| 145 | aclrtResetDevice(deviceId); | ||
| 146 | aclFinalize(); | ||
| 147 | |||
| 148 | return 0; | ||
| 149 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_mse_loss") | 11 | message(STATUS "=== Debug: target_sources add test_mse_loss") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
Rloss/mse_loss/tests/ut/op_host/op_api/test_mse_loss.cpp→loss/mse_loss/tests/ut/op_host/op_api/test_aclnn_mse_loss.cpp+1-16
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #include "level2/aclnn_mse_loss.h" | 14 | #include "../../../../op_host/op_api/aclnn_mse_loss.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| @@ -339,21 +339,6 @@ TEST_F(l2_mse_loss_test, aclnnMseLoss_21_aclnnMseLoss_output_error_shape_mean) { | |||
| 339 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 339 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| 342 | TEST_F(l2_mse_loss_test, aclnnMseLoss_bf16_nchw_mean) { | ||
| 343 | auto selfDesc = TensorDesc({2, 3, 2}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); | ||
| 344 | auto targetDesc = TensorDesc({2, 3, 2}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); | ||
| 345 | int64_t reduction = 1; | ||
| 346 | |||
| 347 | auto outDesc = TensorDesc({}, ACL_BF16, ACL_FORMAT_NCHW).Precision(0.001, 0.001); | ||
| 348 | |||
| 349 | auto ut = OP_API_UT(aclnnMseLoss, INPUT(selfDesc, targetDesc, reduction), OUTPUT(outDesc)); | ||
| 350 | |||
| 351 | // SAMPLE: only test GetWorkspaceSize | ||
| 352 | uint64_t workspaceSize = 0; | ||
| 353 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 354 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | ||
| 355 | } | ||
| 356 | |||
| 357 | TEST_F(l2_mse_loss_test, ascend910B2_aclnnMseLoss_bf16_nchw_mean) { | 342 | TEST_F(l2_mse_loss_test, ascend910B2_aclnnMseLoss_bf16_nchw_mean) { |
| 358 | auto selfDesc = TensorDesc({2, 3, 2}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); | 343 | auto selfDesc = TensorDesc({2, 3, 2}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); |
| 359 | auto targetDesc = TensorDesc({2, 3, 2}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); | 344 | auto targetDesc = TensorDesc({2, 3, 2}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); |
Rloss/mse_loss/tests/ut/op_host/op_api/test_mse_loss_out.cpp→loss/mse_loss/tests/ut/op_host/op_api/test_aclnn_mse_loss_out.cpp+1-16
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #include "level2/aclnn_mse_loss_out.h" | 14 | #include "../../../../op_host/op_api/aclnn_mse_loss_out.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| @@ -338,21 +338,6 @@ TEST_F(l2_mse_loss_out_test, aclnnMseLossOut_21_aclnnMseLossOut_output_error_sha | |||
| 338 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 338 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | TEST_F(l2_mse_loss_out_test, aclnnMseLossOut_bf16_float_nhwc_mean) { | ||
| 342 | auto selfDesc = TensorDesc({2, 2}, ACL_BF16, ACL_FORMAT_NDHWC).ValueRange(-1, 1); | ||
| 343 | auto targetDesc = TensorDesc({2, 2}, ACL_BF16, ACL_FORMAT_NDHWC).ValueRange(-1, 1); | ||
| 344 | int64_t reduction = 1; | ||
| 345 | |||
| 346 | auto outDesc = TensorDesc({2}, ACL_BF16, ACL_FORMAT_NDHWC).Precision(0.0001, 0.0001); | ||
| 347 | |||
| 348 | auto ut = OP_API_UT(aclnnMseLossOut, INPUT(selfDesc, targetDesc, reduction), OUTPUT(outDesc)); | ||
| 349 | |||
| 350 | // SAMPLE: only test GetWorkspaceSize | ||
| 351 | uint64_t workspaceSize = 0; | ||
| 352 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 353 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | ||
| 354 | } | ||
| 355 | |||
| 356 | TEST_F(l2_mse_loss_out_test, ascend910B2_aclnnMseLossOut_bf16_float_nhwc_mean) { | 341 | TEST_F(l2_mse_loss_out_test, ascend910B2_aclnnMseLossOut_bf16_float_nhwc_mean) { |
| 357 | auto selfDesc = TensorDesc({2, 2}, ACL_BF16, ACL_FORMAT_NDHWC).ValueRange(-1, 1); | 342 | auto selfDesc = TensorDesc({2, 2}, ACL_BF16, ACL_FORMAT_NDHWC).ValueRange(-1, 1); |
| 358 | auto targetDesc = TensorDesc({2, 2}, ACL_BF16, ACL_FORMAT_NDHWC).ValueRange(-1, 1); | 343 | auto targetDesc = TensorDesc({2, 2}, ACL_BF16, ACL_FORMAT_NDHWC).ValueRange(-1, 1); |
| @@ -21,4 +21,4 @@ foreach(SUB_DIR ${CURRENT_DIRS}) | |||
| 21 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | 21 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") |
| 22 | add_subdirectory(${SUB_DIR}) | 22 | add_subdirectory(${SUB_DIR}) |
| 23 | endif() | 23 | endif() |
| 24 | endforeach() | 24 | endforeach() |
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_upsample_bicubic2d_grad") | 11 | message(STATUS "=== Debug: target_sources add test_upsample_bicubic2d_grad") |
| 12 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
Rloss/mse_loss_grad_v2/tests/ut/op_host/op_api/test_mse_loss_backward.cpp→loss/mse_loss_grad_v2/tests/ut/op_host/op_api/test_aclnn_mse_loss_backward.cpp+1-1
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #include "level2/aclnn_mse_loss_backward.h" | 14 | #include "../../../../op_host/op_api/aclnn_mse_loss_backward.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| @@ -0,0 +1,166 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> selfShape = {2, 3}; | ||
| 79 | std::vector<int64_t> targetShape = {2, 3}; | ||
| 80 | std::vector<int64_t> outShape = {2}; | ||
| 81 | std::vector<int64_t> istargetShape = {2, 3}; | ||
| 82 | void* selfDeviceAddr = nullptr; | ||
| 83 | void* targetDeviceAddr = nullptr; | ||
| 84 | void* outDeviceAddr = nullptr; | ||
| 85 | void* istargetDeviceAddr = nullptr; | ||
| 86 | aclTensor* self = nullptr; | ||
| 87 | aclTensor* target = nullptr; | ||
| 88 | aclTensor* out = nullptr; | ||
| 89 | aclTensor* istarget = nullptr; | ||
| 90 | std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5}; | ||
| 91 | std::vector<int32_t> targetHostData = {0, 1, 2, 3, 4, 5}; | ||
| 92 | std::vector<float> outHostData(2, 0); | ||
| 93 | std::vector<float> istargetHostData(6, 0); | ||
| 94 | int64_t reduction = 0; | ||
| 95 | // 创建self aclTensor | ||
| 96 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 97 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 98 | // 创建target aclTensor | ||
| 99 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_INT32, &target); | ||
| 100 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 101 | // 创建out aclTensor | ||
| 102 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 103 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 104 | // 创建istarget aclTensor | ||
| 105 | ret = CreateAclTensor(istargetHostData, istargetShape, &istargetDeviceAddr, aclDataType::ACL_FLOAT, | ||
| 106 | &istarget); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 108 | |||
| 109 | // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 110 | uint64_t workspaceSize = 0; | ||
| 111 | aclOpExecutor* executor; | ||
| 112 | // 调用aclnnMultilabelMarginLoss第一段接口 | ||
| 113 | ret = aclnnMultilabelMarginLossGetWorkspaceSize(self, target, reduction, out, istarget, &workspaceSize, &executor); | ||
| 114 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMultilabelMarginLossGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 115 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 116 | void* workspaceAddr = nullptr; | ||
| 117 | if (workspaceSize > 0) { | ||
| 118 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 119 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 120 | } | ||
| 121 | // 调用aclnnMultilabelMarginLoss第二段接口 | ||
| 122 | ret = aclnnMultilabelMarginLoss(workspaceAddr, workspaceSize, executor, stream); | ||
| 123 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMultilabelMarginLoss failed. ERROR: %d\n", ret); return ret); | ||
| 124 | |||
| 125 | // 4. (固定写法)同步等待任务执行结束 | ||
| 126 | ret = aclrtSynchronizeStream(stream); | ||
| 127 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 128 | |||
| 129 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 130 | auto outSize = GetShapeSize(outShape); | ||
| 131 | std::vector<float> outData(outSize, 0); | ||
| 132 | ret = aclrtMemcpy(outData.data(), outData.size() * sizeof(outData[0]), outDeviceAddr, | ||
| 133 | outSize * sizeof(outData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 134 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 135 | for (int64_t i = 0; i < outSize; i++) { | ||
| 136 | LOG_PRINT("out[%ld] is: %f\n", i, outData[i]); | ||
| 137 | } | ||
| 138 | |||
| 139 | auto istargetSize = GetShapeSize(istargetShape); | ||
| 140 | std::vector<float> istargetData(istargetSize, 0); | ||
| 141 | ret = aclrtMemcpy(istargetData.data(), istargetData.size() * sizeof(istargetData[0]), istargetDeviceAddr, | ||
| 142 | istargetSize * sizeof(istargetData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 143 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 144 | for (int64_t i = 0; i < istargetSize; i++) { | ||
| 145 | LOG_PRINT("istarget[%ld] is: %f\n", i, istargetData[i]); | ||
| 146 | } | ||
| 147 | |||
| 148 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 149 | aclDestroyTensor(self); | ||
| 150 | aclDestroyTensor(target); | ||
| 151 | aclDestroyTensor(out); | ||
| 152 | aclDestroyTensor(istarget); | ||
| 153 | |||
| 154 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 155 | aclrtFree(selfDeviceAddr); | ||
| 156 | aclrtFree(targetDeviceAddr); | ||
| 157 | aclrtFree(outDeviceAddr); | ||
| 158 | aclrtFree(istargetDeviceAddr); | ||
| 159 | if (workspaceSize > 0) { | ||
| 160 | aclrtFree(workspaceAddr); | ||
| 161 | } | ||
| 162 | aclrtDestroyStream(stream); | ||
| 163 | aclrtResetDevice(deviceId); | ||
| 164 | aclFinalize(); | ||
| 165 | return 0; | ||
| 166 | } | ||
| @@ -14,3 +14,11 @@ if(UT_TEST_ALL OR OP_HOST_UT) | |||
| 14 | add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 14 | add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 15 | add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 15 | add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 16 | endif() | 16 | endif() |
| 17 | if(NOT OP_API_UT) | ||
| 18 | list(REMOVE_ITEM CURRENT_DIRS op_api) | ||
| 19 | endif() | ||
| 20 | foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 21 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 22 | add_subdirectory(${SUB_DIR}) | ||
| 23 | endif() | ||
| 24 | endforeach() | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_multilabel_margin_loss") | 11 | message(STATUS "=== Debug: target_sources add test_multilabel_margin_loss") |
| 12 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
Rloss/multilabel_margin_loss/tests/ut/op_host/op_api/test_multilabel_margin_loss.cpp→loss/multilabel_margin_loss/tests/ut/op_host/op_api/test_aclnn_multilabel_margin_loss.cpp+1-1
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #include "level2/aclnn_multilabel_margin_loss.h" | 14 | #include "../../../../op_host/op_api/aclnn_multilabel_margin_loss.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| @@ -0,0 +1,168 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> selfShape = {2, 3}; | ||
| 79 | std::vector<int64_t> targetShape = {2}; | ||
| 80 | std::vector<int64_t> weightShape = {3}; | ||
| 81 | std::vector<int64_t> outShape = {2}; | ||
| 82 | std::vector<int64_t> totalWeightOutShape = {1}; | ||
| 83 | void* selfDeviceAddr = nullptr; | ||
| 84 | void* targetDeviceAddr = nullptr; | ||
| 85 | void* weightDeviceAddr = nullptr; | ||
| 86 | void* outDeviceAddr = nullptr; | ||
| 87 | void* totalWeightOutDeviceAddr = nullptr; | ||
| 88 | aclTensor* self = nullptr; | ||
| 89 | aclTensor* target = nullptr; | ||
| 90 | aclTensor* weight = nullptr; | ||
| 91 | aclTensor* out = nullptr; | ||
| 92 | aclTensor* totalWeightOut = nullptr; | ||
| 93 | std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5}; | ||
| 94 | std::vector<int32_t> targetHostData = {0, 2}; | ||
| 95 | std::vector<float> weightHostData = {1.1, 1.2, 1.3}; | ||
| 96 | std::vector<float> outHostData(2, 0); | ||
| 97 | std::vector<float> totalWeightOutHostData(1, 0); | ||
| 98 | int64_t reduction = 0; | ||
| 99 | int64_t ignoreIndex = -100; | ||
| 100 | // 创建self aclTensor | ||
| 101 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 102 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 103 | // 创建target aclTensor | ||
| 104 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_INT32, &target); | ||
| 105 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 106 | // 创建weight aclTensor | ||
| 107 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 108 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 109 | // 创建out aclTensor | ||
| 110 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 111 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 112 | // 创建totalWeightOut aclTensor | ||
| 113 | ret = CreateAclTensor(totalWeightOutHostData, totalWeightOutShape, &totalWeightOutDeviceAddr, aclDataType::ACL_FLOAT, | ||
| 114 | &totalWeightOut); | ||
| 115 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 116 | |||
| 117 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 118 | uint64_t workspaceSize = 0; | ||
| 119 | aclOpExecutor* executor; | ||
| 120 | // 调用aclnnNLLLoss第一段接口 | ||
| 121 | ret = aclnnNLLLossGetWorkspaceSize(self, target, weight, reduction, ignoreIndex, out, totalWeightOut, &workspaceSize, | ||
| 122 | &executor); | ||
| 123 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLossGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 124 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 125 | void* workspaceAddr = nullptr; | ||
| 126 | if (workspaceSize > 0) { | ||
| 127 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 128 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 129 | } | ||
| 130 | // 调用aclnnNLLLoss第二段接口 | ||
| 131 | ret = aclnnNLLLoss(workspaceAddr, workspaceSize, executor, stream); | ||
| 132 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLoss failed. ERROR: %d\n", ret); return ret); | ||
| 133 | |||
| 134 | // 4. (固定写法)同步等待任务执行结束 | ||
| 135 | ret = aclrtSynchronizeStream(stream); | ||
| 136 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 137 | |||
| 138 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 139 | auto size = GetShapeSize(outShape); | ||
| 140 | std::vector<float> resultData(size, 0); | ||
| 141 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 142 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 143 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 144 | for (int64_t i = 0; i < size; i++) { | ||
| 145 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 146 | } | ||
| 147 | |||
| 148 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 149 | aclDestroyTensor(self); | ||
| 150 | aclDestroyTensor(target); | ||
| 151 | aclDestroyTensor(weight); | ||
| 152 | aclDestroyTensor(out); | ||
| 153 | aclDestroyTensor(totalWeightOut); | ||
| 154 | |||
| 155 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 156 | aclrtFree(selfDeviceAddr); | ||
| 157 | aclrtFree(targetDeviceAddr); | ||
| 158 | aclrtFree(weightDeviceAddr); | ||
| 159 | aclrtFree(outDeviceAddr); | ||
| 160 | aclrtFree(totalWeightOutDeviceAddr); | ||
| 161 | if (workspaceSize > 0) { | ||
| 162 | aclrtFree(workspaceAddr); | ||
| 163 | } | ||
| 164 | aclrtDestroyStream(stream); | ||
| 165 | aclrtResetDevice(deviceId); | ||
| 166 | aclFinalize(); | ||
| 167 | return 0; | ||
| 168 | } | ||
| @@ -0,0 +1,166 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | int main() { | ||
| 69 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 70 | // 根据自己的实际device填写deviceId | ||
| 71 | int32_t deviceId = 0; | ||
| 72 | aclrtStream stream; | ||
| 73 | auto ret = Init(deviceId, &stream); | ||
| 74 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 75 | |||
| 76 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 77 | std::vector<int64_t> selfShape = {1, 2, 3, 2}; | ||
| 78 | std::vector<int64_t> targetShape = {1, 3, 2}; | ||
| 79 | std::vector<int64_t> weightShape = {2}; | ||
| 80 | std::vector<int64_t> outShape = {1, 3, 2}; | ||
| 81 | std::vector<int64_t> totalWeightOutShape = {1}; | ||
| 82 | void* selfDeviceAddr = nullptr; | ||
| 83 | void* targetDeviceAddr = nullptr; | ||
| 84 | void* weightDeviceAddr = nullptr; | ||
| 85 | void* outDeviceAddr = nullptr; | ||
| 86 | void* totalWeightOutDeviceAddr = nullptr; | ||
| 87 | aclTensor* self = nullptr; | ||
| 88 | aclTensor* target = nullptr; | ||
| 89 | aclTensor* weight = nullptr; | ||
| 90 | aclTensor* out = nullptr; | ||
| 91 | aclTensor* totalWeightOut = nullptr; | ||
| 92 | std::vector<float> selfHostData = {0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1, 8.1, 9.1, 10.1, 11.1}; | ||
| 93 | std::vector<int32_t> targetHostData = {1, 0, 1, 1, 2, 1}; | ||
| 94 | std::vector<float> weightHostData = {1.1, 1.2}; | ||
| 95 | std::vector<float> outHostData = {0, 0, 0, 0, 0, 0}; | ||
| 96 | std::vector<float> totalWeightOutHostData = {0}; | ||
| 97 | int64_t reduction = 0; | ||
| 98 | int64_t ignoreIndex = -100; | ||
| 99 | // 创建self aclTensor | ||
| 100 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 101 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 102 | // 创建other aclTensor | ||
| 103 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_INT32, &target); | ||
| 104 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 105 | // 创建weight aclTensor | ||
| 106 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 108 | // 创建out aclTensor | ||
| 109 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 110 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 111 | // 创建totalWeightOut aclTensor | ||
| 112 | ret = CreateAclTensor(totalWeightOutHostData, totalWeightOutShape, &totalWeightOutDeviceAddr, aclDataType::ACL_FLOAT, | ||
| 113 | &totalWeightOut); | ||
| 114 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 115 | |||
| 116 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 117 | uint64_t workspaceSize = 0; | ||
| 118 | aclOpExecutor* executor; | ||
| 119 | // 调用aclnnNLLLoss2d第一段接口 | ||
| 120 | ret = aclnnNLLLoss2dGetWorkspaceSize(self, target, weight, reduction, ignoreIndex, out, totalWeightOut, &workspaceSize, &executor); | ||
| 121 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLoss2dGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 122 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 123 | void* workspaceAddr = nullptr; | ||
| 124 | if (workspaceSize > 0) { | ||
| 125 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 126 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 127 | } | ||
| 128 | // 调用aclnnNLLLoss2d第二段接口 | ||
| 129 | ret = aclnnNLLLoss2d(workspaceAddr, workspaceSize, executor, stream); | ||
| 130 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLoss2d failed. ERROR: %d\n", ret); return ret); | ||
| 131 | |||
| 132 | // 4. (固定写法)同步等待任务执行结束 | ||
| 133 | ret = aclrtSynchronizeStream(stream); | ||
| 134 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 135 | |||
| 136 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 137 | auto size = GetShapeSize(outShape); | ||
| 138 | std::vector<float> resultData(size, 0); | ||
| 139 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 140 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 141 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 142 | for (int64_t i = 0; i < size; i++) { | ||
| 143 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 144 | } | ||
| 145 | |||
| 146 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 147 | aclDestroyTensor(self); | ||
| 148 | aclDestroyTensor(target); | ||
| 149 | aclDestroyTensor(weight); | ||
| 150 | aclDestroyTensor(out); | ||
| 151 | aclDestroyTensor(totalWeightOut); | ||
| 152 | |||
| 153 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 154 | aclrtFree(selfDeviceAddr); | ||
| 155 | aclrtFree(targetDeviceAddr); | ||
| 156 | aclrtFree(weightDeviceAddr); | ||
| 157 | aclrtFree(outDeviceAddr); | ||
| 158 | aclrtFree(totalWeightOutDeviceAddr); | ||
| 159 | if (workspaceSize > 0) { | ||
| 160 | aclrtFree(workspaceAddr); | ||
| 161 | } | ||
| 162 | aclrtDestroyStream(stream); | ||
| 163 | aclrtResetDevice(deviceId); | ||
| 164 | aclFinalize(); | ||
| 165 | return 0; | ||
| 166 | } | ||
| @@ -596,54 +596,6 @@ TEST_F(l2_nll_loss2d_forward_test, case_027) | |||
| 596 | ut.TestPrecision(); | 596 | ut.TestPrecision(); |
| 597 | } | 597 | } |
| 598 | 598 | ||
| 599 | TEST_F(l2_nll_loss2d_forward_test, case_028) | ||
| 600 | { | ||
| 601 | auto selfDesc = TensorDesc({5, 3, 1, 10}, ACL_FLOAT16, ACL_FORMAT_NCDHW).ValueRange(-1, 1); | ||
| 602 | auto targetDesc = TensorDesc({5, 1, 10}, ACL_INT32, ACL_FORMAT_NCDHW).ValueRange(0, 3); | ||
| 603 | auto weightDesc = TensorDesc({3}, ACL_FLOAT16, ACL_FORMAT_NCDHW).ValueRange(-1, 1); | ||
| 604 | int64_t reduction = 1; | ||
| 605 | int64_t ignoreIndex = -100; | ||
| 606 | |||
| 607 | auto outDesc = TensorDesc({}, ACL_FLOAT, ACL_FORMAT_NCDHW).Precision(0.001, 0.001); | ||
| 608 | auto totalWeightDesc = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_NCDHW).Precision(0.001, 0.001); | ||
| 609 | |||
| 610 | auto ut = OP_API_UT( | ||
| 611 | aclnnNLLLoss2d, INPUT(selfDesc, targetDesc, weightDesc, reduction, ignoreIndex), | ||
| 612 | OUTPUT(outDesc, totalWeightDesc)); | ||
| 613 | |||
| 614 | // SAMPLE: only test GetWorkspaceSize | ||
| 615 | uint64_t workspace_size = 0; | ||
| 616 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 617 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 618 | |||
| 619 | // SAMPLE: precision simulate | ||
| 620 | ut.TestPrecision(); | ||
| 621 | } | ||
| 622 | |||
| 623 | TEST_F(l2_nll_loss2d_forward_test, ascend910_95_case_028) | ||
| 624 | { | ||
| 625 | auto selfDesc = TensorDesc({5, 3, 1, 10}, ACL_FLOAT16, ACL_FORMAT_NCDHW).ValueRange(-1, 1); | ||
| 626 | auto targetDesc = TensorDesc({5, 1, 10}, ACL_INT32, ACL_FORMAT_NCDHW).ValueRange(0, 3); | ||
| 627 | auto weightDesc = TensorDesc({3}, ACL_FLOAT16, ACL_FORMAT_NCDHW).ValueRange(-1, 1); | ||
| 628 | int64_t reduction = 1; | ||
| 629 | int64_t ignoreIndex = -100; | ||
| 630 | |||
| 631 | auto outDesc = TensorDesc({}, ACL_FLOAT, ACL_FORMAT_NCDHW).Precision(0.001, 0.001); | ||
| 632 | auto totalWeightDesc = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_NCDHW).Precision(0.001, 0.001); | ||
| 633 | |||
| 634 | auto ut = OP_API_UT( | ||
| 635 | aclnnNLLLoss2d, INPUT(selfDesc, targetDesc, weightDesc, reduction, ignoreIndex), | ||
| 636 | OUTPUT(outDesc, totalWeightDesc)); | ||
| 637 | |||
| 638 | // SAMPLE: only test GetWorkspaceSize | ||
| 639 | uint64_t workspace_size = 0; | ||
| 640 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 641 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 642 | |||
| 643 | // SAMPLE: precision simulate | ||
| 644 | ut.TestPrecision(); | ||
| 645 | } | ||
| 646 | |||
| 647 | TEST_F(l2_nll_loss2d_forward_test, case_029) | 599 | TEST_F(l2_nll_loss2d_forward_test, case_029) |
| 648 | { | 600 | { |
| 649 | auto selfDesc = TensorDesc({5, 3, 1, 10}, ACL_FLOAT16, ACL_FORMAT_NCDHW).ValueRange(-1, 1); | 601 | auto selfDesc = TensorDesc({5, 3, 1, 10}, ACL_FLOAT16, ACL_FORMAT_NCDHW).ValueRange(-1, 1); |
| @@ -501,54 +501,6 @@ TEST_F(l2_nll_loss_test, case_021) | |||
| 501 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 501 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | TEST_F(l2_nll_loss_test, case_022) | ||
| 505 | { | ||
| 506 | auto selfDesc = TensorDesc({1, 7}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 507 | auto targetDesc = TensorDesc({1}, ACL_INT64, ACL_FORMAT_ND).ValueRange(0, 2); | ||
| 508 | auto weightDesc = TensorDesc({7}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 509 | int64_t reduction = 0; | ||
| 510 | int64_t ignoreIndex = -100; | ||
| 511 | |||
| 512 | auto outDesc = TensorDesc({1}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 513 | auto totalWeightDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001).ValidCount(0); | ||
| 514 | |||
| 515 | auto ut = OP_API_UT( | ||
| 516 | aclnnNLLLoss, INPUT(selfDesc, targetDesc, weightDesc, reduction, ignoreIndex), | ||
| 517 | OUTPUT(outDesc, totalWeightDesc)); | ||
| 518 | |||
| 519 | // SAMPLE: only test GetWorkspaceSize | ||
| 520 | uint64_t workspace_size = 0; | ||
| 521 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 522 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 523 | |||
| 524 | // SAMPLE: precision simulate | ||
| 525 | ut.TestPrecision(); | ||
| 526 | } | ||
| 527 | |||
| 528 | TEST_F(l2_nll_loss_test, case_023) | ||
| 529 | { | ||
| 530 | auto selfDesc = TensorDesc({3, 7}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 531 | auto targetDesc = TensorDesc({3}, ACL_INT32, ACL_FORMAT_ND).ValueRange(0, 2); | ||
| 532 | auto weightDesc = TensorDesc({7}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 533 | int64_t reduction = 1; | ||
| 534 | int64_t ignoreIndex = -100; | ||
| 535 | |||
| 536 | auto outDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 537 | auto totalWeightDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.001, 0.001); | ||
| 538 | |||
| 539 | auto ut = OP_API_UT( | ||
| 540 | aclnnNLLLoss, INPUT(selfDesc, targetDesc, weightDesc, reduction, ignoreIndex), | ||
| 541 | OUTPUT(outDesc, totalWeightDesc)); | ||
| 542 | |||
| 543 | // SAMPLE: only test GetWorkspaceSize | ||
| 544 | uint64_t workspace_size = 0; | ||
| 545 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 546 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 547 | |||
| 548 | // SAMPLE: precision simulate | ||
| 549 | // ut.TestPrecision(); // comment bcz of timeout in model tests (109610 ms) | ||
| 550 | } | ||
| 551 | |||
| 552 | TEST_F(l2_nll_loss_test, Ascend910B2_case_024) | 504 | TEST_F(l2_nll_loss_test, Ascend910B2_case_024) |
| 553 | { | 505 | { |
| 554 | auto selfDesc = TensorDesc({10, 7}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); | 506 | auto selfDesc = TensorDesc({10, 7}, ACL_BF16, ACL_FORMAT_NCHW).ValueRange(-1, 1); |
| @@ -0,0 +1,179 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据复制到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> gradOutputShape = {2}; | ||
| 79 | std::vector<int64_t> selfShape = {2, 3}; | ||
| 80 | std::vector<int64_t> targetShape = {2}; | ||
| 81 | std::vector<int64_t> weightShape = {3}; | ||
| 82 | std::vector<int64_t> totalWeightShape = {1}; | ||
| 83 | std::vector<int64_t> outShape = {2, 3}; | ||
| 84 | void* gradOutputDeviceAddr = nullptr; | ||
| 85 | void* selfDeviceAddr = nullptr; | ||
| 86 | void* targetDeviceAddr = nullptr; | ||
| 87 | void* weightDeviceAddr = nullptr; | ||
| 88 | void* totalWeightDeviceAddr = nullptr; | ||
| 89 | void* outDeviceAddr = nullptr; | ||
| 90 | aclTensor* gradOutput = nullptr; | ||
| 91 | aclTensor* self = nullptr; | ||
| 92 | aclTensor* target = nullptr; | ||
| 93 | aclTensor* weight = nullptr; | ||
| 94 | aclTensor* totalWeight = nullptr; | ||
| 95 | aclTensor* out = nullptr; | ||
| 96 | std::vector<float> gradOutputHostData = {3.1, 6.5}; | ||
| 97 | std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5}; | ||
| 98 | std::vector<int32_t> targetHostData = {0, 2}; | ||
| 99 | std::vector<float> weightHostData = {1.1, 1.2, 1.3}; | ||
| 100 | std::vector<float> totalWeightHostData = {0}; | ||
| 101 | std::vector<float> outHostData(6, 0); | ||
| 102 | int64_t reduction = 0; | ||
| 103 | int64_t ignoreIndex = -100; | ||
| 104 | // 创建gradOutput aclTensor | ||
| 105 | ret = | ||
| 106 | CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 108 | // 创建self aclTensor | ||
| 109 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 110 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 111 | // 创建target aclTensor | ||
| 112 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_INT32, &target); | ||
| 113 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 114 | // 创建weight aclTensor | ||
| 115 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 116 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 117 | // 创建totalWeight aclTensor | ||
| 118 | ret = CreateAclTensor(totalWeightHostData, totalWeightShape, &totalWeightDeviceAddr, aclDataType::ACL_FLOAT, | ||
| 119 | &totalWeight); | ||
| 120 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 121 | // 创建out aclTensor | ||
| 122 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 123 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 124 | |||
| 125 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 126 | uint64_t workspaceSize = 0; | ||
| 127 | aclOpExecutor* executor; | ||
| 128 | // 调用aclnnNLLLossBackward第一段接口 | ||
| 129 | ret = aclnnNLLLossBackwardGetWorkspaceSize(gradOutput, self, target, weight, reduction, ignoreIndex, totalWeight, out, | ||
| 130 | &workspaceSize, &executor); | ||
| 131 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLossBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 132 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 133 | void* workspaceAddr = nullptr; | ||
| 134 | if (workspaceSize > 0) { | ||
| 135 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 136 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 137 | } | ||
| 138 | // 调用aclnnNLLLossBackward第二段接口 | ||
| 139 | ret = aclnnNLLLossBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 140 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLossBackward failed. ERROR: %d\n", ret); return ret); | ||
| 141 | |||
| 142 | // 4. (固定写法)同步等待任务执行结束 | ||
| 143 | ret = aclrtSynchronizeStream(stream); | ||
| 144 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 145 | |||
| 146 | // 5. 获取输出的值,将device侧内存上的结果复制至host侧,需要根据具体API的接口定义修改 | ||
| 147 | auto size = GetShapeSize(outShape); | ||
| 148 | std::vector<float> resultData(size, 0); | ||
| 149 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 150 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 151 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 152 | for (int64_t i = 0; i < size; i++) { | ||
| 153 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 154 | } | ||
| 155 | |||
| 156 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 157 | aclDestroyTensor(gradOutput); | ||
| 158 | aclDestroyTensor(self); | ||
| 159 | aclDestroyTensor(target); | ||
| 160 | aclDestroyTensor(weight); | ||
| 161 | aclDestroyTensor(totalWeight); | ||
| 162 | aclDestroyTensor(out); | ||
| 163 | |||
| 164 | // 7. 释放device 资源 | ||
| 165 | aclrtFree(gradOutputDeviceAddr); | ||
| 166 | aclrtFree(selfDeviceAddr); | ||
| 167 | aclrtFree(targetDeviceAddr); | ||
| 168 | aclrtFree(weightDeviceAddr); | ||
| 169 | aclrtFree(totalWeightDeviceAddr); | ||
| 170 | aclrtFree(outDeviceAddr); | ||
| 171 | if (workspaceSize > 0) { | ||
| 172 | aclrtFree(workspaceAddr); | ||
| 173 | } | ||
| 174 | aclrtDestroyStream(stream); | ||
| 175 | aclrtResetDevice(deviceId); | ||
| 176 | aclFinalize(); | ||
| 177 | |||
| 178 | return 0; | ||
| 179 | } | ||
| @@ -0,0 +1,182 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> gradShape = {3, 1, 1}; | ||
| 79 | std::vector<int64_t> selfShape = {3, 5, 1, 1}; | ||
| 80 | std::vector<int64_t> targetShape = {3, 1, 1}; | ||
| 81 | std::vector<int64_t> weightShape = {5}; | ||
| 82 | std::vector<int64_t> totalWeightShape = {1}; | ||
| 83 | std::vector<int64_t> outShape = {3, 5, 1, 1}; | ||
| 84 | |||
| 85 | void* gradDeviceAddr = nullptr; | ||
| 86 | void* selfDeviceAddr = nullptr; | ||
| 87 | void* targetDeviceAddr = nullptr; | ||
| 88 | void* weightDeviceAddr = nullptr; | ||
| 89 | void* totalWeightDeviceAddr = nullptr; | ||
| 90 | void* outDeviceAddr = nullptr; | ||
| 91 | aclTensor* grad = nullptr; | ||
| 92 | aclTensor* self = nullptr; | ||
| 93 | aclTensor* target = nullptr; | ||
| 94 | aclTensor* weight = nullptr; | ||
| 95 | aclTensor* totalWeight = nullptr; | ||
| 96 | aclTensor* out = nullptr; | ||
| 97 | |||
| 98 | std::vector<float> gradHostData = {2.7, 2.6, 2.5}; | ||
| 99 | std::vector<float> selfHostData = {4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5.0, 5.1, 5.2, 5.3, 5.4, 5.5}; | ||
| 100 | std::vector<int64_t> targetHostData = {2, 3, 1}; | ||
| 101 | std::vector<float> weightHostData = {1.0, 1.0, 1.0, 1.0, 1.0}; | ||
| 102 | std::vector<float> totalWeightHostData = {1.0}; | ||
| 103 | std::vector<float> outHostData = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; | ||
| 104 | int64_t reduction = 0; | ||
| 105 | int64_t ignoreIndex = -100; | ||
| 106 | |||
| 107 | // 创建grad aclTensor | ||
| 108 | ret = CreateAclTensor(gradHostData, gradShape, &gradDeviceAddr, aclDataType::ACL_FLOAT, &grad); | ||
| 109 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 110 | // 创建self aclTensor | ||
| 111 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 112 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 113 | // 创建target aclTensor | ||
| 114 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_INT64, &target); | ||
| 115 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 116 | // 创建weight aclTensor | ||
| 117 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 118 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 119 | // 创建totalWeight aclTensor | ||
| 120 | ret = CreateAclTensor(totalWeightHostData, totalWeightShape, &totalWeightDeviceAddr, | ||
| 121 | aclDataType::ACL_FLOAT, &totalWeight); | ||
| 122 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 123 | // 创建out aclTensor | ||
| 124 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 125 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 126 | |||
| 127 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 128 | uint64_t workspaceSize = 0; | ||
| 129 | aclOpExecutor* executor; | ||
| 130 | // 调用aclnnNLLLoss2dBackward第一段接口 | ||
| 131 | ret = aclnnNLLLoss2dBackwardGetWorkspaceSize(grad, self, target, weight, reduction, ignoreIndex, totalWeight, out, | ||
| 132 | &workspaceSize, &executor); | ||
| 133 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLoss2dBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); | ||
| 134 | return ret); | ||
| 135 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 136 | void* workspaceAddr = nullptr; | ||
| 137 | if (workspaceSize > 0) { | ||
| 138 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 139 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 140 | } | ||
| 141 | // 调用aclnnNLLLoss2dBackward第二段接口 | ||
| 142 | ret = aclnnNLLLoss2dBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 143 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnNLLLoss2dBackward failed. ERROR: %d\n", ret); return ret); | ||
| 144 | |||
| 145 | // 4. (固定写法)同步等待任务执行结束 | ||
| 146 | ret = aclrtSynchronizeStream(stream); | ||
| 147 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 148 | |||
| 149 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 150 | auto size = GetShapeSize(outShape); | ||
| 151 | std::vector<float> resultData(size, 0); | ||
| 152 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 153 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 154 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 155 | for (int64_t i = 0; i < size; i++) { | ||
| 156 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 157 | } | ||
| 158 | |||
| 159 | // 6. 释放aclTensor,需要根据具体API的接口定义修改 | ||
| 160 | aclDestroyTensor(grad); | ||
| 161 | aclDestroyTensor(self); | ||
| 162 | aclDestroyTensor(target); | ||
| 163 | aclDestroyTensor(weight); | ||
| 164 | aclDestroyTensor(totalWeight); | ||
| 165 | aclDestroyTensor(out); | ||
| 166 | |||
| 167 | // 7. 释放device 资源 | ||
| 168 | aclrtFree(gradDeviceAddr); | ||
| 169 | aclrtFree(selfDeviceAddr); | ||
| 170 | aclrtFree(targetDeviceAddr); | ||
| 171 | aclrtFree(weightDeviceAddr); | ||
| 172 | aclrtFree(totalWeightDeviceAddr); | ||
| 173 | aclrtFree(outDeviceAddr); | ||
| 174 | if (workspaceSize > 0) { | ||
| 175 | aclrtFree(workspaceAddr); | ||
| 176 | } | ||
| 177 | aclrtDestroyStream(stream); | ||
| 178 | aclrtResetDevice(deviceId); | ||
| 179 | aclFinalize(); | ||
| 180 | |||
| 181 | return 0; | ||
| 182 | } | ||
| @@ -14,3 +14,11 @@ if(UT_TEST_ALL OR OP_HOST_UT) | |||
| 14 | add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 14 | add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 15 | add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 15 | add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) |
| 16 | endif() | 16 | endif() |
| 17 | if(NOT OP_API_UT) | ||
| 18 | list(REMOVE_ITEM CURRENT_DIRS op_api) | ||
| 19 | endif() | ||
| 20 | foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 21 | if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 22 | add_subdirectory(${SUB_DIR}) | ||
| 23 | endif() | ||
| 24 | endforeach() | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_nll_loss_grad_op_api") | 11 | message(STATUS "=== Debug: target_sources add test_nll_loss_grad_op_api") |
| 12 | add_modules_ut_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -551,31 +551,6 @@ TEST_F(l2_nll_loss2d_backward_test, case_025) | |||
| 551 | ut.TestPrecision(); | 551 | ut.TestPrecision(); |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | TEST_F(l2_nll_loss2d_backward_test, case_026) | ||
| 555 | { | ||
| 556 | auto gradDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND); | ||
| 557 | auto selfDesc = TensorDesc({30, 150, 5, 6}, ACL_FLOAT16, ACL_FORMAT_ND); | ||
| 558 | auto targetDesc = TensorDesc({30, 5, 6}, ACL_INT32, ACL_FORMAT_ND).ValueRange(0, 150); | ||
| 559 | auto weightDesc = TensorDesc({150}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(1, 1); | ||
| 560 | int64_t reduction = 2; | ||
| 561 | int64_t ignoreIndex = -100; | ||
| 562 | auto totalWeightDesc = TensorDesc({1}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 563 | |||
| 564 | auto outDesc = TensorDesc({30, 150, 5, 6}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 565 | |||
| 566 | auto ut = OP_API_UT( | ||
| 567 | aclnnNLLLoss2dBackward, | ||
| 568 | INPUT(gradDesc, selfDesc, targetDesc, weightDesc, reduction, ignoreIndex, totalWeightDesc), OUTPUT(outDesc)); | ||
| 569 | |||
| 570 | // SAMPLE: only test GetWorkspaceSize | ||
| 571 | uint64_t workspace_size = 0; | ||
| 572 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 573 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 574 | |||
| 575 | // SAMPLE: precision simulate | ||
| 576 | ut.TestPrecision(); | ||
| 577 | } | ||
| 578 | |||
| 579 | TEST_F(l2_nll_loss2d_backward_test, case_027) | 554 | TEST_F(l2_nll_loss2d_backward_test, case_027) |
| 580 | { | 555 | { |
| 581 | auto gradDesc = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND); | 556 | auto gradDesc = TensorDesc({1}, ACL_FLOAT, ACL_FORMAT_ND); |
| @@ -509,31 +509,7 @@ TEST_F(l2_nll_loss_backward_test, case_021) | |||
| 509 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 509 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | TEST_F(l2_nll_loss_backward_test, case_022) | 512 | TEST_F(l2_nll_loss_backward_test, Ascend910B2_case_022) |
| 513 | { | ||
| 514 | auto gradDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 515 | auto selfDesc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 516 | auto targetDesc = TensorDesc({5}, ACL_INT32, ACL_FORMAT_ND).Value(vector<int32_t>{0, 1, 2, 3, 4}); | ||
| 517 | auto weightDesc = TensorDesc({5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 518 | int64_t reduction = 1; | ||
| 519 | int64_t ignoreIndex = 0; | ||
| 520 | auto totalWeightDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 521 | |||
| 522 | auto outDesc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 523 | auto ut = OP_API_UT( | ||
| 524 | aclnnNLLLossBackward, | ||
| 525 | INPUT(gradDesc, selfDesc, targetDesc, weightDesc, reduction, ignoreIndex, totalWeightDesc), OUTPUT(outDesc)); | ||
| 526 | |||
| 527 | // SAMPLE: only test GetWorkspaceSize | ||
| 528 | uint64_t workspace_size = 0; | ||
| 529 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 530 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 531 | |||
| 532 | // SAMPLE: precision simulate | ||
| 533 | ut.TestPrecision(); | ||
| 534 | } | ||
| 535 | |||
| 536 | TEST_F(l2_nll_loss_backward_test, Ascend910B2_case_023) | ||
| 537 | { | 513 | { |
| 538 | auto gradDesc = TensorDesc({}, ACL_BF16, ACL_FORMAT_ND); | 514 | auto gradDesc = TensorDesc({}, ACL_BF16, ACL_FORMAT_ND); |
| 539 | auto selfDesc = TensorDesc({10, 7}, ACL_BF16, ACL_FORMAT_ND); | 515 | auto selfDesc = TensorDesc({10, 7}, ACL_BF16, ACL_FORMAT_ND); |
| @@ -545,27 +521,6 @@ TEST_F(l2_nll_loss_backward_test, Ascend910B2_case_023) | |||
| 545 | 521 | ||
| 546 | auto outDesc = TensorDesc({10, 7}, ACL_BF16, ACL_FORMAT_ND).Precision(0.001, 0.001); | 522 | auto outDesc = TensorDesc({10, 7}, ACL_BF16, ACL_FORMAT_ND).Precision(0.001, 0.001); |
| 547 | 523 | ||
| 548 | auto ut = OP_API_UT( | ||
| 549 | aclnnNLLLossBackward, | ||
| 550 | INPUT(gradDesc, selfDesc, targetDesc, weightDesc, reduction, ignoreIndex, totalWeightDesc), OUTPUT(outDesc)); | ||
| 551 | |||
| 552 | // SAMPLE: only test GetWorkspaceSize | ||
| 553 | uint64_t workspace_size = 0; | ||
| 554 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 555 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 556 | } | ||
| 557 | |||
| 558 | TEST_F(l2_nll_loss_backward_test, ascend310P_case_024) | ||
| 559 | { | ||
| 560 | auto gradDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 561 | auto selfDesc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 562 | auto targetDesc = TensorDesc({5}, ACL_INT32, ACL_FORMAT_ND).Value(vector<int32_t>{0, 1, 2, 3, 4}); | ||
| 563 | auto weightDesc = TensorDesc({5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 564 | int64_t reduction = 1; | ||
| 565 | int64_t ignoreIndex = 0; | ||
| 566 | auto totalWeightDesc = TensorDesc({}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 567 | |||
| 568 | auto outDesc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 569 | auto ut = OP_API_UT( | 524 | auto ut = OP_API_UT( |
| 570 | aclnnNLLLossBackward, | 525 | aclnnNLLLossBackward, |
| 571 | INPUT(gradDesc, selfDesc, targetDesc, weightDesc, reduction, ignoreIndex, totalWeightDesc), OUTPUT(outDesc)); | 526 | INPUT(gradDesc, selfDesc, targetDesc, weightDesc, reduction, ignoreIndex, totalWeightDesc), OUTPUT(outDesc)); |
Aloss/sigmoid_cross_entropy_with_logits_grad_v2/examples/test_aclnn_sigmoid_cross_entropy_with_logits_grad_v2.cpp+181-0
| @@ -0,0 +1,181 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请Device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | |||
| 54 | // 调用aclrtMemcpy将Host侧数据拷贝到Device侧内存上 | ||
| 55 | ret = aclrtMemcpy(*deviceAddr, 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); | ||
| 57 | |||
| 58 | // 计算连续tensor的strides | ||
| 59 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 60 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 61 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 62 | } | ||
| 63 | |||
| 64 | // 调用aclCreateTensor接口创建aclTensor | ||
| 65 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 66 | shape.data(), shape.size(), *deviceAddr); | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | int main() { | ||
| 71 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 72 | // 根据自己的实际device填写deviceId | ||
| 73 | int32_t deviceId = 0; | ||
| 74 | aclrtStream stream; | ||
| 75 | auto ret = Init(deviceId, &stream); | ||
| 76 | // check根据自己的需要处理 | ||
| 77 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 78 | |||
| 79 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 80 | std::vector<int64_t> gradOutputShape = {2, 2}; | ||
| 81 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 82 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 83 | std::vector<int64_t> weightShape = {2, 2}; | ||
| 84 | std::vector<int64_t> posWeightShape = {2, 2}; | ||
| 85 | std::vector<int64_t> gradTargetShape = {2, 2}; | ||
| 86 | void* gradOutputDeviceAddr = nullptr; | ||
| 87 | void* selfDeviceAddr = nullptr; | ||
| 88 | void* targetDeviceAddr = nullptr; | ||
| 89 | void* weightDeviceAddr = nullptr; | ||
| 90 | void* posWeightDeviceAddr = nullptr; | ||
| 91 | void* gradTargetDeviceAddr = nullptr; | ||
| 92 | aclTensor* gradOutput = nullptr; | ||
| 93 | aclTensor* self = nullptr; | ||
| 94 | aclTensor* target = nullptr; | ||
| 95 | aclTensor* gradTarget = nullptr; | ||
| 96 | aclTensor* weight = nullptr; | ||
| 97 | aclTensor* posWeight = nullptr; | ||
| 98 | std::vector<float> gradOutputHostData = {0, 1, 2, 3}; | ||
| 99 | std::vector<float> selfHostData = {0, 1, 2, 3}; | ||
| 100 | std::vector<float> targetHostData = {0.1, 0.1, 0.1, 0.1}; | ||
| 101 | std::vector<float> weightHostData = {0, 1, 2, 3}; | ||
| 102 | std::vector<float> posWeightHostData = {0, 1, 2, 3}; | ||
| 103 | std::vector<float> gradTargetHostData = {0, 0, 0, 0}; | ||
| 104 | int64_t reduction = 0; | ||
| 105 | |||
| 106 | // 创建gradOutput aclTensor | ||
| 107 | ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput); | ||
| 108 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 109 | // 创建self aclTensor | ||
| 110 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 111 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 112 | // 创建target aclTensor | ||
| 113 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 114 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 115 | // 创建weight aclTensor | ||
| 116 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 117 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 118 | // 创建posWeight aclTensor | ||
| 119 | ret = CreateAclTensor(posWeightHostData, posWeightShape, &posWeightDeviceAddr, aclDataType::ACL_FLOAT, &posWeight); | ||
| 120 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 121 | // 创建gradTarget aclTensor | ||
| 122 | ret = CreateAclTensor(gradTargetHostData, gradTargetShape, &gradTargetDeviceAddr, aclDataType::ACL_FLOAT, &gradTarget); | ||
| 123 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 124 | |||
| 125 | uint64_t workspaceSize = 0; | ||
| 126 | aclOpExecutor* executor; | ||
| 127 | |||
| 128 | // aclnnBinaryCrossEntropyWithLogitsTargetBackward接口调用示例 | ||
| 129 | // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 130 | // 调用aclnnBinaryCrossEntropyWithLogitsTargetBackward第一段接口 | ||
| 131 | ret = aclnnBinaryCrossEntropyWithLogitsTargetBackwardGetWorkspaceSize(gradOutput, self, target, weight, posWeight, | ||
| 132 | reduction, gradTarget, &workspaceSize, &executor); | ||
| 133 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropyWithLogitsTargetBackwardGetWorkspaceSize failed. ERROR: %d\n", | ||
| 134 | ret); return ret); | ||
| 135 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 136 | void* workspaceAddr = nullptr; | ||
| 137 | if (workspaceSize > 0) { | ||
| 138 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 139 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 140 | } | ||
| 141 | // 调用aclnnBinaryCrossEntropyWithLogitsTargetBackward第二段接口 | ||
| 142 | ret = aclnnBinaryCrossEntropyWithLogitsTargetBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 143 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropyWithLogitsTargetBackward failed. ERROR: %d\n", ret); return ret); | ||
| 144 | |||
| 145 | // 4. (固定写法)同步等待任务执行结束 | ||
| 146 | ret = aclrtSynchronizeStream(stream); | ||
| 147 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 148 | |||
| 149 | // 5. 获取输出的值,将Device侧内存上的结果拷贝至Host侧,需要根据具体API的接口定义修改 | ||
| 150 | auto size = GetShapeSize(gradTargetShape); | ||
| 151 | std::vector<float> resultData(size, 0); | ||
| 152 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradTargetDeviceAddr, | ||
| 153 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 154 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 155 | for (int64_t i = 0; i < size; i++) { | ||
| 156 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 157 | } | ||
| 158 | |||
| 159 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 160 | aclDestroyTensor(gradOutput); | ||
| 161 | aclDestroyTensor(self); | ||
| 162 | aclDestroyTensor(target); | ||
| 163 | aclDestroyTensor(weight); | ||
| 164 | aclDestroyTensor(posWeight); | ||
| 165 | aclDestroyTensor(gradTarget); | ||
| 166 | |||
| 167 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 168 | aclrtFree(gradOutputDeviceAddr); | ||
| 169 | aclrtFree(selfDeviceAddr); | ||
| 170 | aclrtFree(targetDeviceAddr); | ||
| 171 | aclrtFree(weightDeviceAddr); | ||
| 172 | aclrtFree(posWeightDeviceAddr); | ||
| 173 | aclrtFree(gradTargetDeviceAddr); | ||
| 174 | if (workspaceSize > 0) { | ||
| 175 | aclrtFree(workspaceAddr); | ||
| 176 | } | ||
| 177 | aclrtDestroyStream(stream); | ||
| 178 | aclrtResetDevice(deviceId); | ||
| 179 | aclFinalize(); | ||
| 180 | return 0; | ||
| 181 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_sigmoid_cross_entropy_with_logits_grad_v2") | 11 | message(STATUS "=== Debug: target_sources add test_sigmoid_cross_entropy_with_logits_grad_v2") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
Rloss/sigmoid_cross_entropy_with_logits_grad_v2/tests/ut/op_host/op_api/test_binary_cross_entropy_with_logits_backward.cpp→loss/sigmoid_cross_entropy_with_logits_grad_v2/tests/ut/op_host/op_api/test_aclnn_binary_cross_entropy_with_logits_backward.cpp+1-1
| @@ -11,7 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #include "level2/aclnn_binary_cross_entropy_with_logits_backward.h" | 14 | #include "../../../../op_host/op_api/aclnn_binary_cross_entropy_with_logits_backward.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
Aloss/sigmoid_cross_entropy_with_logits_v2/examples/test_aclnn_sigmoid_cross_entropy_with_logits_v2.cpp+173-0
| @@ -0,0 +1,173 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请Device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | |||
| 54 | // 调用aclrtMemcpy将Host侧数据拷贝到Device侧内存上 | ||
| 55 | ret = aclrtMemcpy(*deviceAddr, 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); | ||
| 57 | |||
| 58 | // 计算连续tensor的strides | ||
| 59 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 60 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 61 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 62 | } | ||
| 63 | |||
| 64 | // 调用aclCreateTensor接口创建aclTensor | ||
| 65 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 66 | shape.data(), shape.size(), *deviceAddr); | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | int main() { | ||
| 71 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 72 | // 根据自己的实际device填写deviceId | ||
| 73 | int32_t deviceId = 0; | ||
| 74 | aclrtStream stream; | ||
| 75 | auto ret = Init(deviceId, &stream); | ||
| 76 | // check根据自己的需要处理 | ||
| 77 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 78 | |||
| 79 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 80 | std::vector<int64_t> inputShape = {4, 2}; | ||
| 81 | std::vector<int64_t> targetShape = {4, 2}; | ||
| 82 | std::vector<int64_t> weightShape = {4, 2}; | ||
| 83 | std::vector<int64_t> posWeightShape = {4, 2}; | ||
| 84 | std::vector<int64_t> outShape = {4, 2}; | ||
| 85 | |||
| 86 | void* inputDeviceAddr = nullptr; | ||
| 87 | void* targetDeviceAddr = nullptr; | ||
| 88 | void* weightDeviceAddr = nullptr; | ||
| 89 | void* posWeightDeviceAddr = nullptr; | ||
| 90 | void* outDeviceAddr = nullptr; | ||
| 91 | aclTensor* input = nullptr; | ||
| 92 | aclTensor* target = nullptr; | ||
| 93 | aclTensor* weight = nullptr; | ||
| 94 | aclTensor* posWeight = nullptr; | ||
| 95 | aclTensor* out = nullptr; | ||
| 96 | |||
| 97 | std::vector<float> inputHostData = {0.1, 0.1, 0.2, 0.2, 0.3, 0.3, 0.4, 0.4}; | ||
| 98 | std::vector<float> targetHostData = {0.2, 0.2, 0.1, 0.1, 0.2, 0.2, 0.1, 0.1}; | ||
| 99 | std::vector<float> weightHostData = {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; | ||
| 100 | std::vector<float> posWeightHostData = {0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5}; | ||
| 101 | std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 102 | |||
| 103 | // 创建input aclTensor | ||
| 104 | ret = CreateAclTensor(inputHostData, inputShape, &inputDeviceAddr, aclDataType::ACL_FLOAT, &input); | ||
| 105 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 106 | // 创建target aclTensor | ||
| 107 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 108 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 109 | // 创建weight aclTensor | ||
| 110 | ret = CreateAclTensor(weightHostData, weightShape, &weightDeviceAddr, aclDataType::ACL_FLOAT, &weight); | ||
| 111 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 112 | // 创建posWeight aclTensor | ||
| 113 | ret = CreateAclTensor(posWeightHostData, posWeightShape, &posWeightDeviceAddr, aclDataType::ACL_FLOAT, &posWeight); | ||
| 114 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 115 | // 创建out aclTensor | ||
| 116 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 117 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 118 | |||
| 119 | int64_t reduction = 0; | ||
| 120 | |||
| 121 | uint64_t workspaceSize = 0; | ||
| 122 | aclOpExecutor* executor; | ||
| 123 | |||
| 124 | // aclnnBinaryCrossEntropyWithLogits接口调用示例 | ||
| 125 | // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 126 | // 调用aclnnBinaryCrossEntropyWithLogits第一段接口 | ||
| 127 | ret = aclnnBinaryCrossEntropyWithLogitsGetWorkspaceSize(input, target, weight, posWeight, reduction, out, &workspaceSize, &executor); | ||
| 128 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropyWithLogitsGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 129 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 130 | void* workspaceAddr = nullptr; | ||
| 131 | if (workspaceSize > 0) { | ||
| 132 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 133 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 134 | } | ||
| 135 | // 调用aclnnBinaryCrossEntropyWithLogits第二段接口 | ||
| 136 | ret = aclnnBinaryCrossEntropyWithLogits(workspaceAddr, workspaceSize, executor, stream); | ||
| 137 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnBinaryCrossEntropyWithLogits failed. ERROR: %d\n", ret); return ret); | ||
| 138 | |||
| 139 | // 4. (固定写法)同步等待任务执行结束 | ||
| 140 | ret = aclrtSynchronizeStream(stream); | ||
| 141 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 142 | |||
| 143 | // 5. 获取输出的值,将Device侧内存上的结果拷贝至Host侧,需要根据具体API的接口定义修改 | ||
| 144 | auto size = GetShapeSize(outShape); | ||
| 145 | std::vector<float> resultData(size, 0); | ||
| 146 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 147 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 148 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 149 | for (int64_t i = 0; i < size; i++) { | ||
| 150 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 151 | } | ||
| 152 | |||
| 153 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 154 | aclDestroyTensor(input); | ||
| 155 | aclDestroyTensor(target); | ||
| 156 | aclDestroyTensor(weight); | ||
| 157 | aclDestroyTensor(posWeight); | ||
| 158 | aclDestroyTensor(out); | ||
| 159 | |||
| 160 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 161 | aclrtFree(inputDeviceAddr); | ||
| 162 | aclrtFree(targetDeviceAddr); | ||
| 163 | aclrtFree(weightDeviceAddr); | ||
| 164 | aclrtFree(posWeightDeviceAddr); | ||
| 165 | aclrtFree(outDeviceAddr); | ||
| 166 | if (workspaceSize > 0) { | ||
| 167 | aclrtFree(workspaceAddr); | ||
| 168 | } | ||
| 169 | aclrtDestroyStream(stream); | ||
| 170 | aclrtResetDevice(deviceId); | ||
| 171 | aclFinalize(); | ||
| 172 | return 0; | ||
| 173 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_sigmoid_cross_entropy_with_logits_v2") | 11 | message(STATUS "=== Debug: target_sources add test_sigmoid_cross_entropy_with_logits_v2") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
Rloss/sigmoid_cross_entropy_with_logits_v2/tests/ut/op_host/op_api/test_binary_cross_entropy_with_logits.cpp→loss/sigmoid_cross_entropy_with_logits_v2/tests/ut/op_host/op_api/test_aclnn_binary_cross_entropy_with_logits.cpp+1-85
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | #include "level2/aclnn_binary_cross_entropy_with_logits.h" | 18 | #include "../../../../op_host/op_api/aclnn_binary_cross_entropy_with_logits.h" |
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | 21 | ||
| @@ -40,48 +40,6 @@ class l2BinaryCrossEntropyWithLogitsTest : public testing::Test { | |||
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | // *** tensor dtype test *** | 42 | // *** tensor dtype test *** |
| 43 | // test type: FLOAT/FLOAT32 | ||
| 44 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_float_type) { | ||
| 45 | auto self_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 46 | auto target_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 47 | auto weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 48 | auto pos_weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 49 | int64_t reduction = Reduction::None; | ||
| 50 | auto out_tensor_desc = TensorDesc(self_tensor_desc).Precision(0.0001, 0.0001); | ||
| 51 | |||
| 52 | auto ut = | ||
| 53 | OP_API_UT(aclnnBinaryCrossEntropyWithLogits, | ||
| 54 | INPUT(self_tensor_desc, target_tensor_desc, weight_tensor_desc, pos_weight_tensor_desc, reduction), | ||
| 55 | OUTPUT(out_tensor_desc)); | ||
| 56 | |||
| 57 | uint64_t workspace_size = 0; | ||
| 58 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 59 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 60 | |||
| 61 | ut.TestPrecision(); | ||
| 62 | } | ||
| 63 | |||
| 64 | // test type: FLOAT16 | ||
| 65 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_float16_type) { | ||
| 66 | auto self_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 67 | auto target_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 68 | auto weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 69 | auto pos_weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 70 | int64_t reduction = Reduction::None; | ||
| 71 | auto out_tensor_desc = TensorDesc(self_tensor_desc).Precision(0.0001, 0.0001); | ||
| 72 | |||
| 73 | auto ut = | ||
| 74 | OP_API_UT(aclnnBinaryCrossEntropyWithLogits, | ||
| 75 | INPUT(self_tensor_desc, target_tensor_desc, weight_tensor_desc, pos_weight_tensor_desc, reduction), | ||
| 76 | OUTPUT(out_tensor_desc)); | ||
| 77 | |||
| 78 | uint64_t workspace_size = 0; | ||
| 79 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 80 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 81 | |||
| 82 | ut.TestPrecision(); | ||
| 83 | } | ||
| 84 | |||
| 85 | // test invalid input type | 43 | // test invalid input type |
| 86 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_invalid_double_type) { | 44 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_invalid_double_type) { |
| 87 | auto self_tensor_desc = TensorDesc({5, 5}, ACL_DOUBLE, ACL_FORMAT_ND).ValueRange(0, 1); | 45 | auto self_tensor_desc = TensorDesc({5, 5}, ACL_DOUBLE, ACL_FORMAT_ND).ValueRange(0, 1); |
| @@ -202,48 +160,6 @@ TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_unable_bro | |||
| 202 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 160 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); |
| 203 | } | 161 | } |
| 204 | 162 | ||
| 205 | // test diff input dtype | ||
| 206 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_diff_input_dtype) { | ||
| 207 | auto self_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 208 | auto target_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 209 | auto weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 210 | auto pos_weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 211 | int64_t reduction = Reduction::None; | ||
| 212 | auto out_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 213 | |||
| 214 | auto ut = | ||
| 215 | OP_API_UT(aclnnBinaryCrossEntropyWithLogits, | ||
| 216 | INPUT(self_tensor_desc, target_tensor_desc, weight_tensor_desc, pos_weight_tensor_desc, reduction), | ||
| 217 | OUTPUT(out_tensor_desc)); | ||
| 218 | |||
| 219 | uint64_t workspace_size = 0; | ||
| 220 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 221 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 222 | |||
| 223 | ut.TestPrecision(); | ||
| 224 | } | ||
| 225 | |||
| 226 | // test optional param has diff dtype with input | ||
| 227 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_diff_optional_param_dtype) { | ||
| 228 | auto self_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 229 | auto target_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 230 | auto weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 231 | auto pos_weight_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(0, 1); | ||
| 232 | int64_t reduction = Reduction::None; | ||
| 233 | auto out_tensor_desc = TensorDesc({5, 5}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 234 | |||
| 235 | auto ut = | ||
| 236 | OP_API_UT(aclnnBinaryCrossEntropyWithLogits, | ||
| 237 | INPUT(self_tensor_desc, target_tensor_desc, weight_tensor_desc, pos_weight_tensor_desc, reduction), | ||
| 238 | OUTPUT(out_tensor_desc)); | ||
| 239 | |||
| 240 | uint64_t workspace_size = 0; | ||
| 241 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspace_size); | ||
| 242 | EXPECT_EQ(aclRet, ACL_SUCCESS); | ||
| 243 | |||
| 244 | ut.TestPrecision(); | ||
| 245 | } | ||
| 246 | |||
| 247 | // *** tensor rank range *** | 163 | // *** tensor rank range *** |
| 248 | // empty tensor, with reduction is none | 164 | // empty tensor, with reduction is none |
| 249 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_empty_tensor_under_none_reduction) { | 165 | TEST_F(l2BinaryCrossEntropyWithLogitsTest, case_bcelosswithlogits_for_empty_tensor_under_none_reduction) { |
| @@ -0,0 +1,156 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> gradOutShape = {4, 2}; | ||
| 79 | std::vector<int64_t> selfShape = {4, 2}; | ||
| 80 | std::vector<int64_t> targetShape = {4, 2}; | ||
| 81 | std::vector<int64_t> gradInputShape = {4, 2}; | ||
| 82 | int64_t reduction = 0; | ||
| 83 | float beta = 1.0; | ||
| 84 | void* gradOutDeviceAddr = nullptr; | ||
| 85 | void* selfDeviceAddr = nullptr; | ||
| 86 | void* targetDeviceAddr = nullptr; | ||
| 87 | void* gradInputDeviceAddr = nullptr; | ||
| 88 | aclTensor* gradOut = nullptr; | ||
| 89 | aclTensor* self = nullptr; | ||
| 90 | aclTensor* target = nullptr; | ||
| 91 | aclTensor* gradInput = nullptr; | ||
| 92 | std::vector<float> gradOutHostData = {1, 1, 1, 1, 1, 1, 1, 1}; | ||
| 93 | std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
| 94 | std::vector<float> targetHostData = {1, 1, 1, 1, 1, 1, 1, 1}; | ||
| 95 | std::vector<float> gradInputHostData(8, 0); | ||
| 96 | // 创建gradOut aclTensor | ||
| 97 | ret = CreateAclTensor(gradOutHostData, gradOutShape, &gradOutDeviceAddr, aclDataType::ACL_FLOAT, &gradOut); | ||
| 98 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 99 | // 创建self aclTensor | ||
| 100 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 101 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 102 | // 创建target aclTensor | ||
| 103 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 104 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 105 | // 创建gradInput aclTensor | ||
| 106 | ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 108 | |||
| 109 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 110 | uint64_t workspaceSize = 0; | ||
| 111 | aclOpExecutor* executor; | ||
| 112 | // 调用aclnnSmoothL1LossBackward第一段接口 | ||
| 113 | ret = aclnnSmoothL1LossBackwardGetWorkspaceSize(gradOut, self, target, reduction, beta, gradInput, &workspaceSize, &executor); | ||
| 114 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSmoothL1LossBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 115 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 116 | void* workspaceAddr = nullptr; | ||
| 117 | if (workspaceSize > 0) { | ||
| 118 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 119 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 120 | } | ||
| 121 | // 调用aclnnSmoothL1LossBackward第二段接口 | ||
| 122 | ret = aclnnSmoothL1LossBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 123 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSmoothL1LossBackward failed. ERROR: %d\n", ret); return ret); | ||
| 124 | |||
| 125 | // 4. (固定写法)同步等待任务执行结束 | ||
| 126 | ret = aclrtSynchronizeStream(stream); | ||
| 127 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 128 | |||
| 129 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 130 | auto size = GetShapeSize(gradInputShape); | ||
| 131 | std::vector<float> resultData(size, 0); | ||
| 132 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr, | ||
| 133 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 134 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 135 | for (int64_t i = 0; i < size; i++) { | ||
| 136 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 137 | } | ||
| 138 | |||
| 139 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 140 | aclDestroyTensor(gradOut); | ||
| 141 | aclDestroyTensor(self); | ||
| 142 | aclDestroyTensor(target); | ||
| 143 | aclDestroyTensor(gradInput); | ||
| 144 | // 7. 释放device资源,需要根据具体API的接口定义参数 | ||
| 145 | aclrtFree(gradOutDeviceAddr); | ||
| 146 | aclrtFree(selfDeviceAddr); | ||
| 147 | aclrtFree(targetDeviceAddr); | ||
| 148 | aclrtFree(gradInputDeviceAddr); | ||
| 149 | if (workspaceSize > 0) { | ||
| 150 | aclrtFree(workspaceAddr); | ||
| 151 | } | ||
| 152 | aclrtDestroyStream(stream); | ||
| 153 | aclrtResetDevice(deviceId); | ||
| 154 | aclFinalize(); | ||
| 155 | return 0; | ||
| 156 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") | 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -0,0 +1,148 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> selfShape = {2, 2, 7, 7}; | ||
| 79 | std::vector<int64_t> targetShape = {2, 2, 7, 7}; | ||
| 80 | std::vector<int64_t> resultShape = {2, 2, 7, 7}; | ||
| 81 | |||
| 82 | // 创建self aclTensor | ||
| 83 | std::vector<float> selfData(GetShapeSize(selfShape)* 2, 1); | ||
| 84 | aclTensor* self = nullptr; | ||
| 85 | void *selfDeviceAddr = nullptr; | ||
| 86 | ret = CreateAclTensor(selfData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT16, &self); | ||
| 87 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 88 | // 创建target aclTensor | ||
| 89 | std::vector<float> targetData(GetShapeSize(targetShape)* 2, 1); | ||
| 90 | aclTensor* target = nullptr; | ||
| 91 | void *targetDeviceAddr = nullptr; | ||
| 92 | ret = CreateAclTensor(targetData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT16, &target); | ||
| 93 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 94 | // 创建result aclTensor | ||
| 95 | std::vector<float> resultData(GetShapeSize(resultShape)* 2, 1); | ||
| 96 | aclTensor* result = nullptr; | ||
| 97 | void *resultDeviceAddr = nullptr; | ||
| 98 | ret = CreateAclTensor(resultData, resultShape, &resultDeviceAddr, aclDataType::ACL_FLOAT16, &result); | ||
| 99 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 100 | |||
| 101 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 102 | uint64_t workspaceSize = 0; | ||
| 103 | aclOpExecutor* executor; | ||
| 104 | // 调用aclnnSmoothL1Loss第一段接口 | ||
| 105 | int64_t reduction = 0; | ||
| 106 | float beta = 1.0; | ||
| 107 | ret = aclnnSmoothL1LossGetWorkspaceSize(self, target, reduction, beta, result, &workspaceSize, &executor); | ||
| 108 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSmoothL1LossGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 109 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 110 | void* workspaceAddr = nullptr; | ||
| 111 | if (workspaceSize > 0) { | ||
| 112 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 113 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 114 | } | ||
| 115 | // 调用aclnnSmoothL1Loss第二段接口 | ||
| 116 | ret = aclnnSmoothL1Loss(workspaceAddr, workspaceSize, executor, stream); | ||
| 117 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSmoothL1Loss failed. ERROR: %d\n", ret); return ret); | ||
| 118 | |||
| 119 | // 4. (固定写法)同步等待任务执行结束 | ||
| 120 | ret = aclrtSynchronizeStream(stream); | ||
| 121 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 122 | |||
| 123 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 124 | auto size = GetShapeSize(resultShape); | ||
| 125 | std::vector<float> resultOutData(size, 0); | ||
| 126 | ret = aclrtMemcpy(resultOutData.data(), resultOutData.size() * sizeof(resultOutData[0]), resultDeviceAddr, | ||
| 127 | size * sizeof(resultOutData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 128 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 129 | for (int64_t i = 0; i < size; i++) { | ||
| 130 | LOG_PRINT("result[%ld] is: %f\n", i, resultOutData[i]); | ||
| 131 | } | ||
| 132 | |||
| 133 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 134 | aclDestroyTensor(self); | ||
| 135 | aclDestroyTensor(target); | ||
| 136 | aclDestroyTensor(result); | ||
| 137 | // 7. 释放device资源,需要根据具体API的接口定义参数 | ||
| 138 | aclrtFree(selfDeviceAddr); | ||
| 139 | aclrtFree(targetDeviceAddr); | ||
| 140 | aclrtFree(resultDeviceAddr); | ||
| 141 | if (workspaceSize > 0) { | ||
| 142 | aclrtFree(workspaceAddr); | ||
| 143 | } | ||
| 144 | aclrtDestroyStream(stream); | ||
| 145 | aclrtResetDevice(deviceId); | ||
| 146 | aclFinalize(); | ||
| 147 | return 0; | ||
| 148 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") | 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -0,0 +1,147 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 78 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 79 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 80 | std::vector<int64_t> outShape = {2, 2}; | ||
| 81 | void* selfDeviceAddr = nullptr; | ||
| 82 | void* targetDeviceAddr = nullptr; | ||
| 83 | void* outDeviceAddr = nullptr; | ||
| 84 | aclTensor* self = nullptr; | ||
| 85 | aclTensor* target = nullptr; | ||
| 86 | aclTensor* out = nullptr; | ||
| 87 | std::vector<float> selfHostData = {0.3, 0.7, 0.5, 0.5}; | ||
| 88 | std::vector<float> targetHostData = {-1, 1, 1, -1}; | ||
| 89 | std::vector<float> outHostData = {0, 0, 0, 0}; | ||
| 90 | int64_t reduction = 0; | ||
| 91 | // 创建self aclTensor | ||
| 92 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 93 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 94 | // 创建target aclTensor | ||
| 95 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 96 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 97 | // 创建out aclTensor | ||
| 98 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 99 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 100 | |||
| 101 | // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 102 | uint64_t workspaceSize = 0; | ||
| 103 | aclOpExecutor* executor; | ||
| 104 | // 调用aclnnSoftMarginLoss第一段接口 | ||
| 105 | ret = aclnnSoftMarginLossGetWorkspaceSize(self, target, reduction, out, &workspaceSize, &executor); | ||
| 106 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSoftMarginLossGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 107 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 108 | void* workspaceAddr = nullptr; | ||
| 109 | if (workspaceSize > 0) { | ||
| 110 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 111 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 112 | } | ||
| 113 | // 调用aclnnSoftMarginLoss第二段接口 | ||
| 114 | ret = aclnnSoftMarginLoss(workspaceAddr, workspaceSize, executor, stream); | ||
| 115 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSoftMarginLoss failed. ERROR: %d\n", ret); return ret); | ||
| 116 | |||
| 117 | // 4. (固定写法)同步等待任务执行结束 | ||
| 118 | ret = aclrtSynchronizeStream(stream); | ||
| 119 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 120 | |||
| 121 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 122 | auto size = GetShapeSize(outShape); | ||
| 123 | std::vector<float> resultData(size, 0); | ||
| 124 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 125 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 126 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 127 | for (int64_t i = 0; i < size; i++) { | ||
| 128 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 129 | } | ||
| 130 | |||
| 131 | // 6. 释放aclTensor,需要根据具体API的接口定义修改 | ||
| 132 | aclDestroyTensor(self); | ||
| 133 | aclDestroyTensor(target); | ||
| 134 | aclDestroyTensor(out); | ||
| 135 | |||
| 136 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 137 | aclrtFree(selfDeviceAddr); | ||
| 138 | aclrtFree(targetDeviceAddr); | ||
| 139 | aclrtFree(outDeviceAddr); | ||
| 140 | if (workspaceSize > 0) { | ||
| 141 | aclrtFree(workspaceAddr); | ||
| 142 | } | ||
| 143 | aclrtDestroyStream(stream); | ||
| 144 | aclrtResetDevice(deviceId); | ||
| 145 | aclFinalize(); | ||
| 146 | return 0; | ||
| 147 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") | 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -107,7 +107,7 @@ TEST_F(l2_soft_margin_loss_test, soft_margin_loss_bfloat16) { | |||
| 107 | auto ut = OP_API_UT(aclnnSoftMarginLoss, INPUT(selfDesc, targetDesc, reduction), OUTPUT(outDesc)); | 107 | auto ut = OP_API_UT(aclnnSoftMarginLoss, INPUT(selfDesc, targetDesc, reduction), OUTPUT(outDesc)); |
| 108 | uint64_t workspaceSize = 0; | 108 | uint64_t workspaceSize = 0; |
| 109 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | 109 | aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); |
| 110 | EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | 110 | EXPECT_EQ(aclRet, ACL_SUCCESS); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | // empty tensor, reduction none | 113 | // empty tensor, reduction none |
| @@ -0,0 +1,159 @@ | |||
| 1 | /** | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | |||
| 16 | do { \ | ||
| 17 | if (!(cond)) { \ | ||
| 18 | return_expr; \ | ||
| 19 | } \ | ||
| 20 | } while (0) | ||
| 21 | |||
| 22 | |||
| 23 | do { \ | ||
| 24 | printf(message, ##__VA_ARGS__); \ | ||
| 25 | } while (0) | ||
| 26 | |||
| 27 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | int64_t shapeSize = 1; | ||
| 29 | for (auto i : shape) { | ||
| 30 | shapeSize *= i; | ||
| 31 | } | ||
| 32 | return shapeSize; | ||
| 33 | } | ||
| 34 | |||
| 35 | int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | // 固定写法,资源初始化 | ||
| 37 | auto ret = aclInit(nullptr); | ||
| 38 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | ret = aclrtSetDevice(deviceId); | ||
| 40 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | ret = aclrtCreateStream(stream); | ||
| 42 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | template <typename T> | ||
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | aclDataType dataType, aclTensor** tensor) { | ||
| 49 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | // 调用aclrtMalloc申请device侧内存 | ||
| 51 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 54 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 55 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 56 | |||
| 57 | // 计算连续tensor的strides | ||
| 58 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 59 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 60 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 61 | } | ||
| 62 | |||
| 63 | // 调用aclCreateTensor接口创建aclTensor | ||
| 64 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 65 | shape.data(), shape.size(), *deviceAddr); | ||
| 66 | return 0; | ||
| 67 | } | ||
| 68 | |||
| 69 | int main() { | ||
| 70 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 71 | // 根据自己的实际device填写deviceId | ||
| 72 | int32_t deviceId = 0; | ||
| 73 | aclrtStream stream; | ||
| 74 | auto ret = Init(deviceId, &stream); | ||
| 75 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init failed. ERROR: %d\n", ret); return ret); | ||
| 76 | |||
| 77 | // 2. 构造输入与输出,需要根据API的接口自定义构造gradOutput | ||
| 78 | std::vector<int64_t> gradOutputShape = {2, 2}; | ||
| 79 | std::vector<int64_t> selfShape = {2, 2}; | ||
| 80 | std::vector<int64_t> targetShape = {2, 2}; | ||
| 81 | std::vector<int64_t> outShape = {2, 2}; | ||
| 82 | void* gradOutputDeviceAddr = nullptr; | ||
| 83 | void* selfDeviceAddr = nullptr; | ||
| 84 | void* targetDeviceAddr = nullptr; | ||
| 85 | void* outDeviceAddr = nullptr; | ||
| 86 | aclTensor* gradOutput = nullptr; | ||
| 87 | aclTensor* self = nullptr; | ||
| 88 | aclTensor* target = nullptr; | ||
| 89 | aclTensor* out = nullptr; | ||
| 90 | std::vector<float> gradOutputHostData = {0, 1, 2, 3}; | ||
| 91 | std::vector<float> selfHostData = {0, 1, 2, 3}; | ||
| 92 | std::vector<float> targetHostData = {1, 1, 1, 1}; | ||
| 93 | std::vector<float> outHostData(4, 0); | ||
| 94 | // 创建gradOutput aclTensor | ||
| 95 | ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, | ||
| 96 | aclDataType::ACL_FLOAT, &gradOutput); | ||
| 97 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 98 | // 创建self aclTensor | ||
| 99 | ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 100 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 101 | // 创建target aclTensor | ||
| 102 | ret = CreateAclTensor(targetHostData, targetShape, &targetDeviceAddr, aclDataType::ACL_FLOAT, &target); | ||
| 103 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 104 | // 创建out aclTensor | ||
| 105 | ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 106 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 107 | // 创建reduction | ||
| 108 | int64_t reduction = 1; | ||
| 109 | |||
| 110 | // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 111 | uint64_t workspaceSize = 0; | ||
| 112 | aclOpExecutor* executor; | ||
| 113 | // 调用aclnnSoftMarginLossBackward第一段接口 | ||
| 114 | ret = aclnnSoftMarginLossBackwardGetWorkspaceSize(gradOutput, self, target, reduction, out, &workspaceSize, &executor); | ||
| 115 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSoftMarginLossBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); | ||
| 116 | return ret); | ||
| 117 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 118 | void* workspaceAddr = nullptr; | ||
| 119 | if (workspaceSize > 0) { | ||
| 120 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 121 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 122 | } | ||
| 123 | // 调用aclnnSoftMarginLossBackward第二段接口 | ||
| 124 | ret = aclnnSoftMarginLossBackward(workspaceAddr, workspaceSize, executor, stream); | ||
| 125 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSoftMarginLossBackward failed. ERROR: %d\n", ret); return ret); | ||
| 126 | |||
| 127 | // 4. (固定写法)同步等待任务执行结束 | ||
| 128 | ret = aclrtSynchronizeStream(stream); | ||
| 129 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 130 | |||
| 131 | // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 132 | auto size = GetShapeSize(outShape); | ||
| 133 | std::vector<float> resultData(size, 0); | ||
| 134 | ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 135 | size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 136 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 137 | for (int64_t i = 0; i < size; i++) { | ||
| 138 | LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 139 | } | ||
| 140 | |||
| 141 | // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 142 | aclDestroyTensor(gradOutput); | ||
| 143 | aclDestroyTensor(self); | ||
| 144 | aclDestroyTensor(target); | ||
| 145 | aclDestroyTensor(out); | ||
| 146 | |||
| 147 | // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 148 | aclrtFree(gradOutputDeviceAddr); | ||
| 149 | aclrtFree(selfDeviceAddr); | ||
| 150 | aclrtFree(targetDeviceAddr); | ||
| 151 | aclrtFree(outDeviceAddr); | ||
| 152 | if (workspaceSize > 0) { | ||
| 153 | aclrtFree(workspaceAddr); | ||
| 154 | } | ||
| 155 | aclrtDestroyStream(stream); | ||
| 156 | aclrtResetDevice(deviceId); | ||
| 157 | aclFinalize(); | ||
| 158 | return 0; | ||
| 159 | } | ||
| @@ -9,4 +9,6 @@ | |||
| 9 | # ---------------------------------------------------------------------------- | 9 | # ---------------------------------------------------------------------------- |
| 10 | 10 | ||
| 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") | 11 | message(STATUS "=== Debug: target_sources add test_non_max_suppression_op_api") |
| 12 | add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | 12 | if(UT_TEST_ALL OR OP_API_UT) |
| 13 | add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | endif() | ||
| @@ -0,0 +1,184 @@ | |||
| 1 | /* * | ||
| 2 | * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | * This file is a part of the CANN Open Software. | ||
| 5 | * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | */ | ||
| 10 | |||
| 11 | |||
| 12 | |||
| 13 | |||
| 14 | |||
| 15 | do { \ | ||
| 16 | if (!(cond)) { \ | ||
| 17 | return_expr; \ | ||
| 18 | } \ | ||
| 19 | } while (0) | ||
| 20 | |||
| 21 | |||
| 22 | do { \ | ||
| 23 | printf(message, ##__VA_ARGS__); \ | ||
| 24 | } while (0) | ||
| 25 | |||
| 26 | int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 27 | int64_t shapeSize = 1; | ||
| 28 | for (auto i : shape) { | ||
| 29 | shapeSize *= i; | ||
| 30 | } | ||
| 31 | return shapeSize; | ||
| 32 | } | ||
| 33 | |||
| 34 | void PrintOutResult(std::vector<int64_t> &shape, void** deviceAddr) { | ||
| 35 | auto size = GetShapeSize(shape); | ||
| 36 | std::vector<int64_t> resultData(size, 0); | ||
| 37 | auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), | ||
| 38 | *deviceAddr, size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 39 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return); | ||
| 40 | for (int64_t i = 0; i < size; i++) { | ||
| 41 | LOG_PRINT("mean result[%ld] is: %ld\n", i, resultData[i]); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | int Init(int64_t deviceId, aclrtStream* stream) { | ||
| 46 | // 固定写法,资源初始化 | ||
| 47 | auto ret = aclInit(nullptr); | ||
| 48 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 49 | ret = aclrtSetDevice(deviceId); | ||
| 50 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 51 | ret = aclrtCreateStream(stream); | ||
| 52 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 53 | return 0; | ||
| 54 | } | ||
| 55 | |||
| 56 | template <typename T> | ||
| 57 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 58 | aclDataType dataType, aclTensor** tensor) { | ||
| 59 | auto size = GetShapeSize(shape) * sizeof(T); | ||
| 60 | // 调用aclrtMalloc申请device侧内存 | ||
| 61 | auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 62 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 63 | // 调用aclrtMemcpy将host侧数据复制到device侧内存上 | ||
| 64 | ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 65 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 66 | |||
| 67 | // 计算连续tensor的strides | ||
| 68 | std::vector<int64_t> strides(shape.size(), 1); | ||
| 69 | for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 70 | strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 71 | } | ||
| 72 | |||
| 73 | // 调用aclCreateTensor接口创建aclTensor | ||
| 74 | *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 75 | shape.data(), shape.size(), *deviceAddr); | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | int main() { | ||
| 80 | // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 81 | // 根据自己的实际device填写deviceId | ||
| 82 | int32_t deviceId = 0; | ||
| 83 | aclrtStream stream; | ||
| 84 | auto ret = Init(deviceId, &stream); | ||
| 85 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 86 | |||
| 87 | // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 88 | std::vector<int64_t> inputShape = {8,1}; | ||
| 89 | std::vector<int64_t> input2Shape = {4,1}; | ||
| 90 | std::vector<int64_t> inputHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
| 91 | std::vector<int64_t> input2HostData = {0, 1, 2, 3}; | ||
| 92 | |||
| 93 | void* input1DeviceAddr = nullptr; | ||
| 94 | aclTensor* input1 = nullptr; | ||
| 95 | void* input2DeviceAddr = nullptr; | ||
| 96 | aclTensor* input2 = nullptr; | ||
| 97 | void* input3DeviceAddr = nullptr; | ||
| 98 | aclTensor* input3 = nullptr; | ||
| 99 | void* input4DeviceAddr = nullptr; | ||
| 100 | aclTensor* input4 = nullptr; | ||
| 101 | void* input5DeviceAddr = nullptr; | ||
| 102 | aclTensor* input5 = nullptr; | ||
| 103 | void* input6DeviceAddr = nullptr; | ||
| 104 | aclTensor* input6 = nullptr; | ||
| 105 | // 创建input aclTensor | ||
| 106 | ret = CreateAclTensor(inputHostData, inputShape, &input1DeviceAddr, aclDataType::ACL_INT64, &input1); | ||
| 107 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 108 | |||
| 109 | ret = CreateAclTensor(input2HostData, input2Shape, &input2DeviceAddr, aclDataType::ACL_INT64, &input2); | ||
| 110 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 111 | ret = CreateAclTensor(inputHostData, inputShape, &input3DeviceAddr, aclDataType::ACL_INT64, &input3); | ||
| 112 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 113 | ret = CreateAclTensor(inputHostData, inputShape, &input4DeviceAddr, aclDataType::ACL_INT64, &input4); | ||
| 114 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 115 | ret = CreateAclTensor(inputHostData, inputShape, &input5DeviceAddr, aclDataType::ACL_INT64, &input5); | ||
| 116 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 117 | ret = CreateAclTensor(inputHostData, inputShape, &input6DeviceAddr, aclDataType::ACL_INT64, &input6); | ||
| 118 | CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 119 | |||
| 120 | int64_t numseq = 8; | ||
| 121 | int64_t numqueries = 4; | ||
| 122 | int64_t blocksize = 2; | ||
| 123 | |||
| 124 | // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 125 | uint64_t workspaceSize = 16 * 1024 * 1024; | ||
| 126 | aclOpExecutor* executor; | ||
| 127 | |||
| 128 | // 调用aclnnAdvanceStep第一段接口 | ||
| 129 | ret = aclnnAdvanceStepGetWorkspaceSize( | ||
| 130 | input1,input2,input3,input4,input5,input6, | ||
| 131 | numseq,numqueries,blocksize, | ||
| 132 | &workspaceSize, | ||
| 133 | &executor); | ||
| 134 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdvanceStepGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 135 | |||
| 136 | // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 137 | void* workspaceAddr = nullptr; | ||
| 138 | if (workspaceSize > 0) { | ||
| 139 | ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 140 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 141 | } | ||
| 142 | |||
| 143 | // 调用aclnnAdvanceStep第二段接口 | ||
| 144 | ret = aclnnAdvanceStep( | ||
| 145 | workspaceAddr, | ||
| 146 | workspaceSize, | ||
| 147 | executor, | ||
| 148 | stream); | ||
| 149 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAdvanceStep failed. ERROR: %d\n", ret); return ret); | ||
| 150 | |||
| 151 | // 4. (固定写法)同步等待任务执行结束 | ||
| 152 | ret = aclrtSynchronizeStream(stream); | ||
| 153 | CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 154 | |||
| 155 | // 5. 获取输出的值,将device侧内存上的结果复制至host侧,需要根据具体API的接口定义修改 | ||
| 156 | PrintOutResult(inputShape, &input1DeviceAddr); | ||
| 157 | PrintOutResult(inputShape, &input3DeviceAddr); | ||
| 158 | PrintOutResult(inputShape, &input4DeviceAddr); | ||
| 159 | PrintOutResult(inputShape, &input5DeviceAddr); | ||
| 160 | |||
| 161 | // 6. 释放aclTensor和aclTensor,需要根据具体API的接口定义修改 | ||
| 162 | aclDestroyTensor(input1); | ||
| 163 | aclDestroyTensor(input2); | ||
| 164 | aclDestroyTensor(input3); | ||
| 165 | aclDestroyTensor(input4); | ||
| 166 | aclDestroyTensor(input5); | ||
| 167 | aclDestroyTensor(input6); | ||
| 168 | |||
| 169 | // 7.释放device资源,需要根据具体API的接口定义修改 | ||
| 170 | aclrtFree(input1DeviceAddr); | ||
| 171 | aclrtFree(input2DeviceAddr); | ||
| 172 | aclrtFree(input3DeviceAddr); | ||
| 173 | aclrtFree(input4DeviceAddr); | ||
| 174 | aclrtFree(input5DeviceAddr); | ||
| 175 | aclrtFree(input6DeviceAddr); | ||
| 176 | if (workspaceSize > 0) { | ||
| 177 | aclrtFree(workspaceAddr); | ||
| 178 | } | ||
| 179 | aclrtDestroyStream(stream); | ||
| 180 | aclrtResetDevice(deviceId); | ||
| 181 | aclFinalize(); | ||
| 182 | |||
| 183 | return 0; | ||
| 184 | } | ||