已合并
aclnnSplitTensor增加输出数据类型一致的校验,及样例指针重复释放修复 #3773
sunhao_hw创建于 7月3日
aclnnSplitTensor增加输出数据类型一致的校验,及样例指针重复释放修复 #3773
已合并
共 5 个文件变更+734-710
| @@ -235,149 +235,152 @@ aclnnStatus aclnnSplitTensor( | |||
| 235 | #include "aclnnop/aclnn_split_tensor.h" | 235 | #include "aclnnop/aclnn_split_tensor.h" |
| 236 | 236 | ||
| 237 | #define CHECK_RET(cond, return_expr) \ | 237 | #define CHECK_RET(cond, return_expr) \ |
| 238 | - do { \ | 238 | + do { \ |
| 239 | - if (!(cond)) { \ | 239 | + if (!(cond)) { \ |
| 240 | - return_expr; \ | 240 | + return_expr; \ |
| 241 | - } \ | 241 | + } \ |
| 242 | - } while (0) | 242 | + } while (0) |
| 243 | 243 | ||
| 244 | -#define LOG_PRINT(message, ...) \ | 244 | +#define LOG_PRINT(message, ...) \ |
| 245 | - do { \ | 245 | + do { \ |
| 246 | - printf(message, ##__VA_ARGS__); \ | 246 | + printf(message, ##__VA_ARGS__); \ |
| 247 | - } while (0) | 247 | + } while (0) |
| 248 | 248 | ||
| 249 | -int64_t GetShapeSize(const std::vector<int64_t>& shape) { | 249 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) |
| 250 | - int64_t shapeSize = 1; | 250 | +{ |
| 251 | - for (auto i : shape) { | 251 | + int64_t shapeSize = 1; |
| 252 | - shapeSize *= i; | 252 | + for (auto i : shape) { |
| 253 | - } | 253 | + shapeSize *= i; |
| 254 | - return shapeSize; | 254 | + } |
| 255 | + return shapeSize; | ||
| 255 | } | 256 | } |
| 256 | 257 | ||
| 257 | -int Init(int32_t deviceId, aclrtStream* stream) { | 258 | +int Init(int32_t deviceId, aclrtStream* stream) |
| 258 | - // 固定写法,资源初始化 | 259 | +{ |
| 259 | - auto ret = aclInit(nullptr); | 260 | + // 固定写法,资源初始化 |
| 260 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 261 | + auto ret = aclInit(nullptr); |
| 261 | - ret = aclrtSetDevice(deviceId); | 262 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 262 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 263 | + ret = aclrtSetDevice(deviceId); |
| 263 | - ret = aclrtCreateStream(stream); | 264 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 264 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 265 | + ret = aclrtCreateStream(stream); |
| 265 | - return 0; | 266 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 267 | + return 0; | ||
| 266 | } | 268 | } |
| 267 | 269 | ||
| 268 | template <typename T> | 270 | template <typename T> |
| 269 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 271 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 270 | - aclDataType dataType, aclTensor** tensor) { | 272 | + aclDataType dataType, aclTensor** tensor) |
| 271 | - auto size = GetShapeSize(shape) * sizeof(T); | 273 | +{ |
| 272 | - // 调用aclrtMalloc申请device侧内存 | 274 | + auto size = GetShapeSize(shape) * sizeof(T); |
| 273 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 275 | + // 调用aclrtMalloc申请device侧内存 |
| 274 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 276 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 275 | - // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 277 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); |
| 276 | - ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 278 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 277 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 279 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 280 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 278 | 281 | ||
| 279 | - // 计算连续tensor的strides | 282 | + // 计算连续tensor的strides |
| 280 | - std::vector<int64_t> strides(shape.size(), 1); | 283 | + std::vector<int64_t> strides(shape.size(), 1); |
| 281 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 284 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 282 | - strides[i] = shape[i + 1] * strides[i + 1]; | 285 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 283 | - } | ||
| 284 | - | ||
| 285 | - // 调用aclCreateTensor接口创建aclTensor | ||
| 286 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 287 | - shape.data(), shape.size(), *deviceAddr); | ||
| 288 | - return 0; | ||
| 289 | -} | ||
| 290 | - | ||
| 291 | -void CheckResult(const std::vector<std::vector<int64_t>> &shapeList, const std::vector<void *> addrList) { | ||
| 292 | - for (size_t i = 0; i < shapeList.size(); i++) { | ||
| 293 | - auto size = GetShapeSize(shapeList[i]); | ||
| 294 | - std::vector<float> resultData(size, 0); | ||
| 295 | - auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], | ||
| 296 | - size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 297 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 298 | - for (int64_t j = 0; j < size; j++) { | ||
| 299 | - LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 300 | } | 286 | } |
| 301 | - } | 287 | + |
| 288 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 289 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 290 | + shape.data(), shape.size(), *deviceAddr); | ||
| 291 | + return 0; | ||
| 302 | } | 292 | } |
| 303 | 293 | ||
| 304 | -int main() { | 294 | +void CheckResult(const std::vector<std::vector<int64_t>>& shapeList, const std::vector<void*> addrList) |
| 305 | - // 1.(固定写法)device/stream初始化,参考acl API手册 | 295 | +{ |
| 306 | - // 根据自己的实际device填写deviceId | 296 | + for (size_t i = 0; i < shapeList.size(); i++) { |
| 307 | - int32_t deviceId = 0; | 297 | + auto size = GetShapeSize(shapeList[i]); |
| 308 | - aclrtStream stream; | 298 | + std::vector<float> resultData(size, 0); |
| 309 | - auto ret = Init(deviceId, &stream); | 299 | + auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], |
| 310 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 300 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); |
| 301 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 302 | + for (int64_t j = 0; j < size; j++) { | ||
| 303 | + LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 304 | + } | ||
| 305 | + } | ||
| 306 | +} | ||
| 311 | 307 | ||
| 312 | - // 2.构造输入与输出,需要根据API的接口自定义构造 | 308 | +int main() |
| 313 | - std::vector<int64_t> selfShape = {4, 2}; | 309 | +{ |
| 314 | - std::vector<int64_t> shape1 = {2, 2}; | 310 | + // 1.(固定写法)device/stream初始化,参考acl API手册 |
| 315 | - std::vector<int64_t> shape2 = {2, 2}; | 311 | + // 根据自己的实际device填写deviceId |
| 316 | - uint64_t splitSections = 2; | 312 | + int32_t deviceId = 0; |
| 317 | - int64_t dim = 0; | 313 | + aclrtStream stream; |
| 314 | + auto ret = Init(deviceId, &stream); | ||
| 315 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 318 | 316 | ||
| 319 | - void* selfDeviceAddr = nullptr; | 317 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 320 | - void* shape1DeviceAddr = nullptr; | 318 | + std::vector<int64_t> selfShape = {4, 2}; |
| 321 | - void* shape2DeviceAddr = nullptr; | 319 | + std::vector<int64_t> shape1 = {2, 2}; |
| 320 | + std::vector<int64_t> shape2 = {2, 2}; | ||
| 321 | + uint64_t splitSections = 2; | ||
| 322 | + int64_t dim = 0; | ||
| 322 | 323 | ||
| 323 | - aclTensor* self = nullptr; | 324 | + void* selfDeviceAddr = nullptr; |
| 324 | - aclTensor* shape1Addr = nullptr; | 325 | + void* shape1DeviceAddr = nullptr; |
| 325 | - aclTensor* shape2Addr = nullptr; | 326 | + void* shape2DeviceAddr = nullptr; |
| 326 | 327 | ||
| 327 | - std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | 328 | + aclTensor* self = nullptr; |
| 328 | - std::vector<float> shape1HostData = {0, 1, 4, 5}; | 329 | + aclTensor* shape1Addr = nullptr; |
| 329 | - std::vector<float> shape2HostData = {2, 3, 6, 7}; | 330 | + aclTensor* shape2Addr = nullptr; |
| 330 | 331 | ||
| 331 | - // 创建self aclTensor | 332 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; |
| 332 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 333 | + std::vector<float> shape1HostData = {0, 1, 4, 5}; |
| 333 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 334 | + std::vector<float> shape2HostData = {2, 3, 6, 7}; |
| 334 | 335 | ||
| 335 | - ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); | 336 | + // 创建self aclTensor |
| 336 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 337 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); |
| 337 | - ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); | 338 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 338 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 339 | 339 | ||
| 340 | - // 创建out aclTensorList | 340 | + ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); |
| 341 | - std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; | 341 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 342 | - aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); | 342 | + ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); |
| 343 | - CHECK_RET(out != nullptr, return ret); | 343 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 344 | 344 | ||
| 345 | - // 调用CANN算子库API,需要修改为具体的Api名称 | 345 | + // 创建out aclTensorList |
| 346 | - uint64_t workspaceSize = 0; | 346 | + std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; |
| 347 | - aclOpExecutor *executor; | 347 | + aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); |
| 348 | - // 调用aclnnSplitTensor第一段接口 | 348 | + CHECK_RET(out != nullptr, return ret); |
| 349 | - ret = aclnnSplitTensorGetWorkspaceSize(self, splitSections, dim, out, &workspaceSize, &executor); | ||
| 350 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensorGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 351 | - // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 352 | - void *workspaceAddr = nullptr; | ||
| 353 | - if (workspaceSize > 0) { | ||
| 354 | - auto ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 355 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 356 | - } | ||
| 357 | - // 调用aclnnSplitTensor第二段接口 | ||
| 358 | - ret = aclnnSplitTensor(workspaceAddr, workspaceSize, executor, stream); | ||
| 359 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensor failed. ERROR: %d\n", ret); return ret); | ||
| 360 | 349 | ||
| 361 | - ret = aclrtSynchronizeStream(stream); | 350 | + // 调用CANN算子库API,需要修改为具体的Api名称 |
| 362 | - CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); | 351 | + uint64_t workspaceSize = 0; |
| 352 | + aclOpExecutor* executor; | ||
| 353 | + // 调用aclnnSplitTensor第一段接口 | ||
| 354 | + ret = aclnnSplitTensorGetWorkspaceSize(self, splitSections, dim, out, &workspaceSize, &executor); | ||
| 355 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensorGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 356 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 357 | + void* workspaceAddr = nullptr; | ||
| 358 | + if (workspaceSize > 0) { | ||
| 359 | + auto ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 360 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 361 | + } | ||
| 362 | + // 调用aclnnSplitTensor第二段接口 | ||
| 363 | + ret = aclnnSplitTensor(workspaceAddr, workspaceSize, executor, stream); | ||
| 364 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensor failed. ERROR: %d\n", ret); return ret); | ||
| 363 | 365 | ||
| 364 | - // 6.释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | 366 | + ret = aclrtSynchronizeStream(stream); |
| 365 | - aclDestroyTensor(self); | 367 | + CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); |
| 366 | - aclDestroyTensorList(out); | ||
| 367 | - aclDestroyTensor(shape1Addr); | ||
| 368 | - aclDestroyTensor(shape2Addr); | ||
| 369 | 368 | ||
| 370 | - // 7.释放device资源 | 369 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 |
| 371 | - aclrtFree(selfDeviceAddr); | 370 | + aclDestroyTensor(self); |
| 372 | - aclrtFree(shape1DeviceAddr); | 371 | + aclDestroyTensorList(out); |
| 373 | - aclrtFree(shape2DeviceAddr); | ||
| 374 | - if (workspaceSize > 0) { | ||
| 375 | - aclrtFree(workspaceAddr); | ||
| 376 | - } | ||
| 377 | - aclrtDestroyStream(stream); | ||
| 378 | - aclrtResetDevice(deviceId); | ||
| 379 | - aclFinalize(); | ||
| 380 | 372 | ||
| 381 | - return 0; | 373 | + // 7. 释放device 资源 |
| 374 | + aclrtFree(selfDeviceAddr); | ||
| 375 | + aclrtFree(shape1DeviceAddr); | ||
| 376 | + aclrtFree(shape2DeviceAddr); | ||
| 377 | + if (workspaceSize > 0) { | ||
| 378 | + aclrtFree(workspaceAddr); | ||
| 379 | + } | ||
| 380 | + aclrtDestroyStream(stream); | ||
| 381 | + aclrtResetDevice(deviceId); | ||
| 382 | + aclFinalize(); | ||
| 383 | + | ||
| 384 | + return 0; | ||
| 382 | } | 385 | } |
| 383 | ``` | 386 | ``` |
| @@ -233,154 +233,157 @@ aclnnStatus aclnnSplitWithSize( | |||
| 233 | #include "aclnnop/aclnn_split_with_size.h" | 233 | #include "aclnnop/aclnn_split_with_size.h" |
| 234 | 234 | ||
| 235 | #define CHECK_RET(cond, return_expr) \ | 235 | #define CHECK_RET(cond, return_expr) \ |
| 236 | - do { \ | 236 | + do { \ |
| 237 | - if (!(cond)) { \ | 237 | + if (!(cond)) { \ |
| 238 | - return_expr; \ | 238 | + return_expr; \ |
| 239 | - } \ | 239 | + } \ |
| 240 | - } while (0) | 240 | + } while (0) |
| 241 | 241 | ||
| 242 | -#define LOG_PRINT(message, ...) \ | 242 | +#define LOG_PRINT(message, ...) \ |
| 243 | - do { \ | 243 | + do { \ |
| 244 | - printf(message, ##__VA_ARGS__); \ | 244 | + printf(message, ##__VA_ARGS__); \ |
| 245 | - } while (0) | 245 | + } while (0) |
| 246 | 246 | ||
| 247 | -int64_t GetShapeSize(const std::vector<int64_t>& shape) { | 247 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) |
| 248 | - int64_t shapeSize = 1; | 248 | +{ |
| 249 | - for (auto i : shape) { | 249 | + int64_t shapeSize = 1; |
| 250 | - shapeSize *= i; | 250 | + for (auto i : shape) { |
| 251 | - } | 251 | + shapeSize *= i; |
| 252 | - return shapeSize; | 252 | + } |
| 253 | + return shapeSize; | ||
| 253 | } | 254 | } |
| 254 | 255 | ||
| 255 | -int Init(int32_t deviceId, aclrtStream* stream) { | 256 | +int Init(int32_t deviceId, aclrtStream* stream) |
| 256 | - // 固定写法,资源初始化 | 257 | +{ |
| 257 | - auto ret = aclInit(nullptr); | 258 | + // 固定写法,资源初始化 |
| 258 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 259 | + auto ret = aclInit(nullptr); |
| 259 | - ret = aclrtSetDevice(deviceId); | 260 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 260 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 261 | + ret = aclrtSetDevice(deviceId); |
| 261 | - ret = aclrtCreateStream(stream); | 262 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 262 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 263 | + ret = aclrtCreateStream(stream); |
| 263 | - return 0; | 264 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 265 | + return 0; | ||
| 264 | } | 266 | } |
| 265 | 267 | ||
| 266 | template <typename T> | 268 | template <typename T> |
| 267 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 269 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 268 | - aclDataType dataType, aclTensor** tensor) { | 270 | + aclDataType dataType, aclTensor** tensor) |
| 269 | - auto size = GetShapeSize(shape) * sizeof(T); | 271 | +{ |
| 270 | - // 调用aclrtMalloc申请device侧内存 | 272 | + auto size = GetShapeSize(shape) * sizeof(T); |
| 271 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 273 | + // 调用aclrtMalloc申请device侧内存 |
| 272 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 274 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 273 | - // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 275 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); |
| 274 | - ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 276 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 275 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 277 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 278 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 276 | 279 | ||
| 277 | - // 计算连续tensor的strides | 280 | + // 计算连续tensor的strides |
| 278 | - std::vector<int64_t> strides(shape.size(), 1); | 281 | + std::vector<int64_t> strides(shape.size(), 1); |
| 279 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 282 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 280 | - strides[i] = shape[i + 1] * strides[i + 1]; | 283 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 281 | - } | ||
| 282 | - | ||
| 283 | - // 调用aclCreateTensor接口创建aclTensor | ||
| 284 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 285 | - shape.data(), shape.size(), *deviceAddr); | ||
| 286 | - return 0; | ||
| 287 | -} | ||
| 288 | - | ||
| 289 | -void CheckResult(const std::vector<std::vector<int64_t>> &shapeList, const std::vector<void *> addrList) { | ||
| 290 | - for (size_t i = 0; i < shapeList.size(); i++) { | ||
| 291 | - auto size = GetShapeSize(shapeList[i]); | ||
| 292 | - std::vector<float> resultData(size, 0); | ||
| 293 | - auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], | ||
| 294 | - size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 295 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 296 | - for (int64_t j = 0; j < size; j++) { | ||
| 297 | - LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 298 | } | 284 | } |
| 299 | - } | 285 | + |
| 286 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 287 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 288 | + shape.data(), shape.size(), *deviceAddr); | ||
| 289 | + return 0; | ||
| 300 | } | 290 | } |
| 301 | 291 | ||
| 302 | -int main() { | 292 | +void CheckResult(const std::vector<std::vector<int64_t>>& shapeList, const std::vector<void*> addrList) |
| 303 | - // 1.(固定写法)device/stream初始化,参考acl API手册 | 293 | +{ |
| 304 | - // 根据自己的实际device填写deviceId | 294 | + for (size_t i = 0; i < shapeList.size(); i++) { |
| 305 | - int32_t deviceId = 0; | 295 | + auto size = GetShapeSize(shapeList[i]); |
| 306 | - aclrtStream stream; | 296 | + std::vector<float> resultData(size, 0); |
| 307 | - auto ret = Init(deviceId, &stream); | 297 | + auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], |
| 308 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 298 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); |
| 299 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 300 | + for (int64_t j = 0; j < size; j++) { | ||
| 301 | + LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 302 | + } | ||
| 303 | + } | ||
| 304 | +} | ||
| 309 | 305 | ||
| 310 | - // 2.构造输入与输出,需要根据API的接口自定义构造 | 306 | +int main() |
| 311 | - std::vector<int64_t> selfShape = {5, 2}; | 307 | +{ |
| 312 | - std::vector<int64_t> shape1 = {1, 2}; | 308 | + // 1.(固定写法)device/stream初始化,参考acl API手册 |
| 313 | - std::vector<int64_t> shape2 = {4, 2}; | 309 | + // 根据自己的实际device填写deviceId |
| 314 | - int64_t splitValue[] = {1, 4}; | 310 | + int32_t deviceId = 0; |
| 315 | - int64_t dim = 0; | 311 | + aclrtStream stream; |
| 312 | + auto ret = Init(deviceId, &stream); | ||
| 313 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 316 | 314 | ||
| 317 | - void* selfDeviceAddr = nullptr; | 315 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 318 | - void* shape1DeviceAddr = nullptr; | 316 | + std::vector<int64_t> selfShape = {5, 2}; |
| 319 | - void* shape2DeviceAddr = nullptr; | 317 | + std::vector<int64_t> shape1 = {1, 2}; |
| 318 | + std::vector<int64_t> shape2 = {4, 2}; | ||
| 319 | + int64_t splitValue[] = {1, 4}; | ||
| 320 | + int64_t dim = 0; | ||
| 320 | 321 | ||
| 321 | - aclTensor* self = nullptr; | 322 | + void* selfDeviceAddr = nullptr; |
| 322 | - aclTensor* shape1Addr = nullptr; | 323 | + void* shape1DeviceAddr = nullptr; |
| 323 | - aclTensor* shape2Addr = nullptr; | 324 | + void* shape2DeviceAddr = nullptr; |
| 324 | - aclIntArray *splitSize = nullptr; | ||
| 325 | 325 | ||
| 326 | - std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; | 326 | + aclTensor* self = nullptr; |
| 327 | - std::vector<float> shape1HostData = {0, 5}; | 327 | + aclTensor* shape1Addr = nullptr; |
| 328 | - std::vector<float> shape2HostData = {1, 2, 3, 4, 6, 7, 8, 9}; | 328 | + aclTensor* shape2Addr = nullptr; |
| 329 | + aclIntArray* splitSize = nullptr; | ||
| 329 | 330 | ||
| 330 | - // 创建self aclTensor | 331 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
| 331 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 332 | + std::vector<float> shape1HostData = {0, 5}; |
| 332 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 333 | + std::vector<float> shape2HostData = {1, 2, 3, 4, 6, 7, 8, 9}; |
| 333 | 334 | ||
| 334 | - splitSize = aclCreateIntArray(splitValue, 2); | 335 | + // 创建self aclTensor |
| 335 | - CHECK_RET(splitSize != nullptr, return ret); | 336 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); |
| 337 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 336 | 338 | ||
| 337 | - ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); | 339 | + splitSize = aclCreateIntArray(splitValue, 2); |
| 338 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 340 | + CHECK_RET(splitSize != nullptr, return ret); |
| 339 | - ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); | ||
| 340 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 341 | 341 | ||
| 342 | - // 创建out aclTensorList | 342 | + ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); |
| 343 | - std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; | 343 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 344 | - aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); | 344 | + ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); |
| 345 | - CHECK_RET(out != nullptr, return ret); | 345 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 346 | 346 | ||
| 347 | - // 调用CANN算子库API,需要修改为具体的Api名称 | 347 | + // 创建out aclTensorList |
| 348 | - uint64_t workspaceSize = 0; | 348 | + std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; |
| 349 | - aclOpExecutor *executor; | 349 | + aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); |
| 350 | - // 调用aclnnSplitWithSize第一段接口 | 350 | + CHECK_RET(out != nullptr, return ret); |
| 351 | - ret = aclnnSplitWithSizeGetWorkspaceSize(self, splitSize, dim, out, &workspaceSize, &executor); | ||
| 352 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSizeGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 353 | - // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 354 | - void *workspaceAddr = nullptr; | ||
| 355 | - if (workspaceSize > 0) { | ||
| 356 | - auto ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 357 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 358 | - } | ||
| 359 | - // 调用aclnnSplitWithSize第二段接口 | ||
| 360 | - ret = aclnnSplitWithSize(workspaceAddr, workspaceSize, executor, stream); | ||
| 361 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSize failed. ERROR: %d\n", ret); return ret); | ||
| 362 | 351 | ||
| 363 | - ret = aclrtSynchronizeStream(stream); | 352 | + // 调用CANN算子库API,需要修改为具体的Api名称 |
| 364 | - CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); | 353 | + uint64_t workspaceSize = 0; |
| 354 | + aclOpExecutor* executor; | ||
| 355 | + // 调用aclnnSplitWithSize第一段接口 | ||
| 356 | + ret = aclnnSplitWithSizeGetWorkspaceSize(self, splitSize, dim, out, &workspaceSize, &executor); | ||
| 357 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSizeGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 358 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 359 | + void* workspaceAddr = nullptr; | ||
| 360 | + if (workspaceSize > 0) { | ||
| 361 | + auto ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 362 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 363 | + } | ||
| 364 | + // 调用aclnnSplitWithSize第二段接口 | ||
| 365 | + ret = aclnnSplitWithSize(workspaceAddr, workspaceSize, executor, stream); | ||
| 366 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSize failed. ERROR: %d\n", ret); return ret); | ||
| 365 | 367 | ||
| 366 | - // 6.释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | 368 | + ret = aclrtSynchronizeStream(stream); |
| 367 | - aclDestroyTensor(self); | 369 | + CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); |
| 368 | - aclDestroyIntArray(splitSize); | ||
| 369 | - aclDestroyTensorList(out); | ||
| 370 | - aclDestroyTensor(shape1Addr); | ||
| 371 | - aclDestroyTensor(shape2Addr); | ||
| 372 | 370 | ||
| 373 | - // 7.释放device资源 | 371 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 |
| 374 | - aclrtFree(selfDeviceAddr); | 372 | + aclDestroyTensor(self); |
| 375 | - aclrtFree(shape1DeviceAddr); | 373 | + aclDestroyIntArray(splitSize); |
| 376 | - aclrtFree(shape2DeviceAddr); | 374 | + aclDestroyTensorList(out); |
| 377 | - if (workspaceSize > 0) { | ||
| 378 | - aclrtFree(workspaceAddr); | ||
| 379 | - } | ||
| 380 | - aclrtDestroyStream(stream); | ||
| 381 | - aclrtResetDevice(deviceId); | ||
| 382 | - aclFinalize(); | ||
| 383 | 375 | ||
| 384 | - return 0; | 376 | + // 7. 释放device 资源 |
| 377 | + aclrtFree(selfDeviceAddr); | ||
| 378 | + aclrtFree(shape1DeviceAddr); | ||
| 379 | + aclrtFree(shape2DeviceAddr); | ||
| 380 | + if (workspaceSize > 0) { | ||
| 381 | + aclrtFree(workspaceAddr); | ||
| 382 | + } | ||
| 383 | + aclrtDestroyStream(stream); | ||
| 384 | + aclrtResetDevice(deviceId); | ||
| 385 | + aclFinalize(); | ||
| 386 | + | ||
| 387 | + return 0; | ||
| 385 | } | 388 | } |
| 386 | ``` | 389 | ``` |
| @@ -16,148 +16,151 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | - do { \ | 19 | + do { \ |
| 20 | - if (!(cond)) { \ | 20 | + if (!(cond)) { \ |
| 21 | - return_expr; \ | 21 | + return_expr; \ |
| 22 | - } \ | 22 | + } \ |
| 23 | - } while (0) | 23 | + } while (0) |
| 24 | 24 | ||
| 25 | -#define LOG_PRINT(message, ...) \ | 25 | +#define LOG_PRINT(message, ...) \ |
| 26 | - do { \ | 26 | + do { \ |
| 27 | - printf(message, ##__VA_ARGS__); \ | 27 | + printf(message, ##__VA_ARGS__); \ |
| 28 | - } while (0) | 28 | + } while (0) |
| 29 | 29 | ||
| 30 | -int64_t GetShapeSize(const std::vector<int64_t>& shape) { | 30 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) |
| 31 | - int64_t shapeSize = 1; | 31 | +{ |
| 32 | - for (auto i : shape) { | 32 | + int64_t shapeSize = 1; |
| 33 | - shapeSize *= i; | 33 | + for (auto i : shape) { |
| 34 | - } | 34 | + shapeSize *= i; |
| 35 | - return shapeSize; | 35 | + } |
| 36 | + return shapeSize; | ||
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | -int Init(int32_t deviceId, aclrtStream* stream) { | 39 | +int Init(int32_t deviceId, aclrtStream* stream) |
| 39 | - // 固定写法,资源初始化 | 40 | +{ |
| 40 | - auto ret = aclInit(nullptr); | 41 | + // 固定写法,资源初始化 |
| 41 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 42 | + auto ret = aclInit(nullptr); |
| 42 | - ret = aclrtSetDevice(deviceId); | 43 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 43 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 44 | + ret = aclrtSetDevice(deviceId); |
| 44 | - ret = aclrtCreateStream(stream); | 45 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 45 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 46 | + ret = aclrtCreateStream(stream); |
| 46 | - return 0; | 47 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 48 | + return 0; | ||
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | template <typename T> | 51 | template <typename T> |
| 50 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 52 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 51 | - aclDataType dataType, aclTensor** tensor) { | 53 | + aclDataType dataType, aclTensor** tensor) |
| 52 | - auto size = GetShapeSize(shape) * sizeof(T); | 54 | +{ |
| 53 | - // 调用aclrtMalloc申请device侧内存 | 55 | + auto size = GetShapeSize(shape) * sizeof(T); |
| 54 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 56 | + // 调用aclrtMalloc申请device侧内存 |
| 55 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 57 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 56 | - // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 58 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); |
| 57 | - ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 59 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 58 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 60 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 61 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 59 | 62 | ||
| 60 | - // 计算连续tensor的strides | 63 | + // 计算连续tensor的strides |
| 61 | - std::vector<int64_t> strides(shape.size(), 1); | 64 | + std::vector<int64_t> strides(shape.size(), 1); |
| 62 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 65 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 63 | - strides[i] = shape[i + 1] * strides[i + 1]; | 66 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 64 | - } | ||
| 65 | - | ||
| 66 | - // 调用aclCreateTensor接口创建aclTensor | ||
| 67 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 68 | - shape.data(), shape.size(), *deviceAddr); | ||
| 69 | - return 0; | ||
| 70 | -} | ||
| 71 | - | ||
| 72 | -void CheckResult(const std::vector<std::vector<int64_t>> &shapeList, const std::vector<void *> addrList) { | ||
| 73 | - for (size_t i = 0; i < shapeList.size(); i++) { | ||
| 74 | - auto size = GetShapeSize(shapeList[i]); | ||
| 75 | - std::vector<float> resultData(size, 0); | ||
| 76 | - auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], | ||
| 77 | - size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 78 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 79 | - for (int64_t j = 0; j < size; j++) { | ||
| 80 | - LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 81 | } | 67 | } |
| 82 | - } | 68 | + |
| 69 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 70 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 71 | + shape.data(), shape.size(), *deviceAddr); | ||
| 72 | + return 0; | ||
| 83 | } | 73 | } |
| 84 | 74 | ||
| 85 | -int main() { | 75 | +void CheckResult(const std::vector<std::vector<int64_t>>& shapeList, const std::vector<void*> addrList) |
| 86 | - // 1.(固定写法)device/stream初始化,参考acl API手册 | 76 | +{ |
| 87 | - // 根据自己的实际device填写deviceId | 77 | + for (size_t i = 0; i < shapeList.size(); i++) { |
| 88 | - int32_t deviceId = 0; | 78 | + auto size = GetShapeSize(shapeList[i]); |
| 89 | - aclrtStream stream; | 79 | + std::vector<float> resultData(size, 0); |
| 90 | - auto ret = Init(deviceId, &stream); | 80 | + auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], |
| 91 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 81 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); |
| 82 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 83 | + for (int64_t j = 0; j < size; j++) { | ||
| 84 | + LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | +} | ||
| 92 | 88 | ||
| 93 | - // 2. 构造输入与输出,需要根据API的接口自定义构造 | 89 | +int main() |
| 94 | - std::vector<int64_t> selfShape = {4, 2}; | 90 | +{ |
| 95 | - std::vector<int64_t> shape1 = {2, 2}; | 91 | + // 1.(固定写法)device/stream初始化,参考acl API手册 |
| 96 | - std::vector<int64_t> shape2 = {2, 2}; | 92 | + // 根据自己的实际device填写deviceId |
| 97 | - uint64_t splitSections = 2; | 93 | + int32_t deviceId = 0; |
| 98 | - int64_t dim = 0; | 94 | + aclrtStream stream; |
| 95 | + auto ret = Init(deviceId, &stream); | ||
| 96 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 99 | 97 | ||
| 100 | - void* selfDeviceAddr = nullptr; | 98 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 101 | - void* shape1DeviceAddr = nullptr; | 99 | + std::vector<int64_t> selfShape = {4, 2}; |
| 102 | - void* shape2DeviceAddr = nullptr; | 100 | + std::vector<int64_t> shape1 = {2, 2}; |
| 101 | + std::vector<int64_t> shape2 = {2, 2}; | ||
| 102 | + uint64_t splitSections = 2; | ||
| 103 | + int64_t dim = 0; | ||
| 103 | 104 | ||
| 104 | - aclTensor* self = nullptr; | 105 | + void* selfDeviceAddr = nullptr; |
| 105 | - aclTensor* shape1Addr = nullptr; | 106 | + void* shape1DeviceAddr = nullptr; |
| 106 | - aclTensor* shape2Addr = nullptr; | 107 | + void* shape2DeviceAddr = nullptr; |
| 107 | 108 | ||
| 108 | - std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | 109 | + aclTensor* self = nullptr; |
| 109 | - std::vector<float> shape1HostData = {0, 1, 4, 5}; | 110 | + aclTensor* shape1Addr = nullptr; |
| 110 | - std::vector<float> shape2HostData = {2, 3, 6, 7}; | 111 | + aclTensor* shape2Addr = nullptr; |
| 111 | 112 | ||
| 112 | - // 创建self aclTensor | 113 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; |
| 113 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 114 | + std::vector<float> shape1HostData = {0, 1, 4, 5}; |
| 114 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 115 | + std::vector<float> shape2HostData = {2, 3, 6, 7}; |
| 115 | 116 | ||
| 116 | - ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); | 117 | + // 创建self aclTensor |
| 117 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 118 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); |
| 118 | - ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); | 119 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 119 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 120 | 120 | ||
| 121 | - // 创建out aclTensorList | 121 | + ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); |
| 122 | - std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; | 122 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 123 | - aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); | 123 | + ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); |
| 124 | - CHECK_RET(out != nullptr, return ret); | 124 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 125 | 125 | ||
| 126 | - // 调用CANN算子库API,需要修改为具体的Api名称 | 126 | + // 创建out aclTensorList |
| 127 | - uint64_t workspaceSize = 0; | 127 | + std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; |
| 128 | - aclOpExecutor *executor; | 128 | + aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); |
| 129 | - // 调用aclnnSplitTensor第一段接口 | 129 | + CHECK_RET(out != nullptr, return ret); |
| 130 | - ret = aclnnSplitTensorGetWorkspaceSize(self, splitSections, dim, out, &workspaceSize, &executor); | ||
| 131 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensorGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 132 | - // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 133 | - void *workspaceAddr = nullptr; | ||
| 134 | - if (workspaceSize > 0) { | ||
| 135 | - auto 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 | - // 调用aclnnSplitTensor第二段接口 | ||
| 139 | - ret = aclnnSplitTensor(workspaceAddr, workspaceSize, executor, stream); | ||
| 140 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensor failed. ERROR: %d\n", ret); return ret); | ||
| 141 | 130 | ||
| 142 | - ret = aclrtSynchronizeStream(stream); | 131 | + // 调用CANN算子库API,需要修改为具体的Api名称 |
| 143 | - CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); | 132 | + uint64_t workspaceSize = 0; |
| 133 | + aclOpExecutor* executor; | ||
| 134 | + // 调用aclnnSplitTensor第一段接口 | ||
| 135 | + ret = aclnnSplitTensorGetWorkspaceSize(self, splitSections, dim, out, &workspaceSize, &executor); | ||
| 136 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensorGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 137 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 138 | + void* workspaceAddr = nullptr; | ||
| 139 | + if (workspaceSize > 0) { | ||
| 140 | + auto ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 141 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 142 | + } | ||
| 143 | + // 调用aclnnSplitTensor第二段接口 | ||
| 144 | + ret = aclnnSplitTensor(workspaceAddr, workspaceSize, executor, stream); | ||
| 145 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitTensor failed. ERROR: %d\n", ret); return ret); | ||
| 144 | 146 | ||
| 145 | - // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | 147 | + ret = aclrtSynchronizeStream(stream); |
| 146 | - aclDestroyTensor(self); | 148 | + CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); |
| 147 | - aclDestroyTensorList(out); | ||
| 148 | - aclDestroyTensor(shape1Addr); | ||
| 149 | - aclDestroyTensor(shape2Addr); | ||
| 150 | 149 | ||
| 151 | - // 7. 释放device 资源 | 150 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 |
| 152 | - aclrtFree(selfDeviceAddr); | 151 | + aclDestroyTensor(self); |
| 153 | - aclrtFree(shape1DeviceAddr); | 152 | + aclDestroyTensorList(out); |
| 154 | - aclrtFree(shape2DeviceAddr); | ||
| 155 | - if (workspaceSize > 0) { | ||
| 156 | - aclrtFree(workspaceAddr); | ||
| 157 | - } | ||
| 158 | - aclrtDestroyStream(stream); | ||
| 159 | - aclrtResetDevice(deviceId); | ||
| 160 | - aclFinalize(); | ||
| 161 | 153 | ||
| 162 | - return 0; | 154 | + // 7. 释放device 资源 |
| 155 | + aclrtFree(selfDeviceAddr); | ||
| 156 | + aclrtFree(shape1DeviceAddr); | ||
| 157 | + aclrtFree(shape2DeviceAddr); | ||
| 158 | + if (workspaceSize > 0) { | ||
| 159 | + aclrtFree(workspaceAddr); | ||
| 160 | + } | ||
| 161 | + aclrtDestroyStream(stream); | ||
| 162 | + aclrtResetDevice(deviceId); | ||
| 163 | + aclFinalize(); | ||
| 164 | + | ||
| 165 | + return 0; | ||
| 163 | } | 166 | } |
| @@ -16,153 +16,156 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | - do { \ | 19 | + do { \ |
| 20 | - if (!(cond)) { \ | 20 | + if (!(cond)) { \ |
| 21 | - return_expr; \ | 21 | + return_expr; \ |
| 22 | - } \ | 22 | + } \ |
| 23 | - } while (0) | 23 | + } while (0) |
| 24 | 24 | ||
| 25 | -#define LOG_PRINT(message, ...) \ | 25 | +#define LOG_PRINT(message, ...) \ |
| 26 | - do { \ | 26 | + do { \ |
| 27 | - printf(message, ##__VA_ARGS__); \ | 27 | + printf(message, ##__VA_ARGS__); \ |
| 28 | - } while (0) | 28 | + } while (0) |
| 29 | 29 | ||
| 30 | -int64_t GetShapeSize(const std::vector<int64_t>& shape) { | 30 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) |
| 31 | - int64_t shapeSize = 1; | 31 | +{ |
| 32 | - for (auto i : shape) { | 32 | + int64_t shapeSize = 1; |
| 33 | - shapeSize *= i; | 33 | + for (auto i : shape) { |
| 34 | - } | 34 | + shapeSize *= i; |
| 35 | - return shapeSize; | 35 | + } |
| 36 | + return shapeSize; | ||
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | -int Init(int32_t deviceId, aclrtStream* stream) { | 39 | +int Init(int32_t deviceId, aclrtStream* stream) |
| 39 | - // 固定写法,资源初始化 | 40 | +{ |
| 40 | - auto ret = aclInit(nullptr); | 41 | + // 固定写法,资源初始化 |
| 41 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 42 | + auto ret = aclInit(nullptr); |
| 42 | - ret = aclrtSetDevice(deviceId); | 43 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 43 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 44 | + ret = aclrtSetDevice(deviceId); |
| 44 | - ret = aclrtCreateStream(stream); | 45 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 45 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 46 | + ret = aclrtCreateStream(stream); |
| 46 | - return 0; | 47 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 48 | + return 0; | ||
| 47 | } | 49 | } |
| 48 | 50 | ||
| 49 | template <typename T> | 51 | template <typename T> |
| 50 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 52 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 51 | - aclDataType dataType, aclTensor** tensor) { | 53 | + aclDataType dataType, aclTensor** tensor) |
| 52 | - auto size = GetShapeSize(shape) * sizeof(T); | 54 | +{ |
| 53 | - // 调用aclrtMalloc申请device侧内存 | 55 | + auto size = GetShapeSize(shape) * sizeof(T); |
| 54 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 56 | + // 调用aclrtMalloc申请device侧内存 |
| 55 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 57 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 56 | - // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 58 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); |
| 57 | - ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 59 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 58 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 60 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 61 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 59 | 62 | ||
| 60 | - // 计算连续tensor的strides | 63 | + // 计算连续tensor的strides |
| 61 | - std::vector<int64_t> strides(shape.size(), 1); | 64 | + std::vector<int64_t> strides(shape.size(), 1); |
| 62 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 65 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 63 | - strides[i] = shape[i + 1] * strides[i + 1]; | 66 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 64 | - } | ||
| 65 | - | ||
| 66 | - // 调用aclCreateTensor接口创建aclTensor | ||
| 67 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 68 | - shape.data(), shape.size(), *deviceAddr); | ||
| 69 | - return 0; | ||
| 70 | -} | ||
| 71 | - | ||
| 72 | -void CheckResult(const std::vector<std::vector<int64_t>> &shapeList, const std::vector<void *> addrList) { | ||
| 73 | - for (size_t i = 0; i < shapeList.size(); i++) { | ||
| 74 | - auto size = GetShapeSize(shapeList[i]); | ||
| 75 | - std::vector<float> resultData(size, 0); | ||
| 76 | - auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], | ||
| 77 | - size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 78 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 79 | - for (int64_t j = 0; j < size; j++) { | ||
| 80 | - LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 81 | } | 67 | } |
| 82 | - } | 68 | + |
| 69 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 70 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 71 | + shape.data(), shape.size(), *deviceAddr); | ||
| 72 | + return 0; | ||
| 83 | } | 73 | } |
| 84 | 74 | ||
| 85 | -int main() { | 75 | +void CheckResult(const std::vector<std::vector<int64_t>>& shapeList, const std::vector<void*> addrList) |
| 86 | - // 1.(固定写法)device/stream初始化,参考acl API手册 | 76 | +{ |
| 87 | - // 根据自己的实际device填写deviceId | 77 | + for (size_t i = 0; i < shapeList.size(); i++) { |
| 88 | - int32_t deviceId = 0; | 78 | + auto size = GetShapeSize(shapeList[i]); |
| 89 | - aclrtStream stream; | 79 | + std::vector<float> resultData(size, 0); |
| 90 | - auto ret = Init(deviceId, &stream); | 80 | + auto ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), addrList[i], |
| 91 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 81 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); |
| 82 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return); | ||
| 83 | + for (int64_t j = 0; j < size; j++) { | ||
| 84 | + LOG_PRINT("result[%ld] is: %f\n", j, resultData[j]); | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | +} | ||
| 92 | 88 | ||
| 93 | - // 2. 构造输入与输出,需要根据API的接口自定义构造 | 89 | +int main() |
| 94 | - std::vector<int64_t> selfShape = {5, 2}; | 90 | +{ |
| 95 | - std::vector<int64_t> shape1 = {1, 2}; | 91 | + // 1.(固定写法)device/stream初始化,参考acl API手册 |
| 96 | - std::vector<int64_t> shape2 = {4, 2}; | 92 | + // 根据自己的实际device填写deviceId |
| 97 | - int64_t splitValue[] = {1, 4}; | 93 | + int32_t deviceId = 0; |
| 98 | - int64_t dim = 0; | 94 | + aclrtStream stream; |
| 95 | + auto ret = Init(deviceId, &stream); | ||
| 96 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 99 | 97 | ||
| 100 | - void* selfDeviceAddr = nullptr; | 98 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 101 | - void* shape1DeviceAddr = nullptr; | 99 | + std::vector<int64_t> selfShape = {5, 2}; |
| 102 | - void* shape2DeviceAddr = nullptr; | 100 | + std::vector<int64_t> shape1 = {1, 2}; |
| 101 | + std::vector<int64_t> shape2 = {4, 2}; | ||
| 102 | + int64_t splitValue[] = {1, 4}; | ||
| 103 | + int64_t dim = 0; | ||
| 103 | 104 | ||
| 104 | - aclTensor* self = nullptr; | 105 | + void* selfDeviceAddr = nullptr; |
| 105 | - aclTensor* shape1Addr = nullptr; | 106 | + void* shape1DeviceAddr = nullptr; |
| 106 | - aclTensor* shape2Addr = nullptr; | 107 | + void* shape2DeviceAddr = nullptr; |
| 107 | - aclIntArray *splitSize = nullptr; | ||
| 108 | 108 | ||
| 109 | - std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; | 109 | + aclTensor* self = nullptr; |
| 110 | - std::vector<float> shape1HostData = {0, 5}; | 110 | + aclTensor* shape1Addr = nullptr; |
| 111 | - std::vector<float> shape2HostData = {1, 2, 3, 4, 6, 7, 8, 9}; | 111 | + aclTensor* shape2Addr = nullptr; |
| 112 | + aclIntArray* splitSize = nullptr; | ||
| 112 | 113 | ||
| 113 | - // 创建self aclTensor | 114 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; |
| 114 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 115 | + std::vector<float> shape1HostData = {0, 5}; |
| 115 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 116 | + std::vector<float> shape2HostData = {1, 2, 3, 4, 6, 7, 8, 9}; |
| 116 | 117 | ||
| 117 | - splitSize = aclCreateIntArray(splitValue, 2); | 118 | + // 创建self aclTensor |
| 118 | - CHECK_RET(splitSize != nullptr, return ret); | 119 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); |
| 120 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 119 | 121 | ||
| 120 | - ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); | 122 | + splitSize = aclCreateIntArray(splitValue, 2); |
| 121 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 123 | + CHECK_RET(splitSize != nullptr, return ret); |
| 122 | - ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); | ||
| 123 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 124 | 124 | ||
| 125 | - // 创建out aclTensorList | 125 | + ret = CreateAclTensor(shape1HostData, shape1, &shape1DeviceAddr, aclDataType::ACL_FLOAT, &shape1Addr); |
| 126 | - std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; | 126 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 127 | - aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); | 127 | + ret = CreateAclTensor(shape2HostData, shape2, &shape2DeviceAddr, aclDataType::ACL_FLOAT, &shape2Addr); |
| 128 | - CHECK_RET(out != nullptr, return ret); | 128 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 129 | 129 | ||
| 130 | - // 调用CANN算子库API,需要修改为具体的Api名称 | 130 | + // 创建out aclTensorList |
| 131 | - uint64_t workspaceSize = 0; | 131 | + std::vector<aclTensor*> tmp = {shape1Addr, shape2Addr}; |
| 132 | - aclOpExecutor *executor; | 132 | + aclTensorList* out = aclCreateTensorList(tmp.data(), tmp.size()); |
| 133 | - // 调用aclnnSplitWithSize第一段接口 | 133 | + CHECK_RET(out != nullptr, return ret); |
| 134 | - ret = aclnnSplitWithSizeGetWorkspaceSize(self, splitSize, dim, out, &workspaceSize, &executor); | ||
| 135 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSizeGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 136 | - // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 137 | - void *workspaceAddr = nullptr; | ||
| 138 | - if (workspaceSize > 0) { | ||
| 139 | - auto 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 | - // 调用aclnnSplitWithSize第二段接口 | ||
| 143 | - ret = aclnnSplitWithSize(workspaceAddr, workspaceSize, executor, stream); | ||
| 144 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSize failed. ERROR: %d\n", ret); return ret); | ||
| 145 | 134 | ||
| 146 | - ret = aclrtSynchronizeStream(stream); | 135 | + // 调用CANN算子库API,需要修改为具体的Api名称 |
| 147 | - CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); | 136 | + uint64_t workspaceSize = 0; |
| 137 | + aclOpExecutor* executor; | ||
| 138 | + // 调用aclnnSplitWithSize第一段接口 | ||
| 139 | + ret = aclnnSplitWithSizeGetWorkspaceSize(self, splitSize, dim, out, &workspaceSize, &executor); | ||
| 140 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSizeGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 141 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 142 | + void* workspaceAddr = nullptr; | ||
| 143 | + if (workspaceSize > 0) { | ||
| 144 | + auto ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 145 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 146 | + } | ||
| 147 | + // 调用aclnnSplitWithSize第二段接口 | ||
| 148 | + ret = aclnnSplitWithSize(workspaceAddr, workspaceSize, executor, stream); | ||
| 149 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSplitWithSize failed. ERROR: %d\n", ret); return ret); | ||
| 148 | 150 | ||
| 149 | - // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | 151 | + ret = aclrtSynchronizeStream(stream); |
| 150 | - aclDestroyTensor(self); | 152 | + CheckResult({shape1, shape2}, {shape1DeviceAddr, shape2DeviceAddr}); |
| 151 | - aclDestroyIntArray(splitSize); | ||
| 152 | - aclDestroyTensorList(out); | ||
| 153 | - aclDestroyTensor(shape1Addr); | ||
| 154 | - aclDestroyTensor(shape2Addr); | ||
| 155 | 153 | ||
| 156 | - // 7. 释放device 资源 | 154 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 |
| 157 | - aclrtFree(selfDeviceAddr); | 155 | + aclDestroyTensor(self); |
| 158 | - aclrtFree(shape1DeviceAddr); | 156 | + aclDestroyIntArray(splitSize); |
| 159 | - aclrtFree(shape2DeviceAddr); | 157 | + aclDestroyTensorList(out); |
| 160 | - if (workspaceSize > 0) { | ||
| 161 | - aclrtFree(workspaceAddr); | ||
| 162 | - } | ||
| 163 | - aclrtDestroyStream(stream); | ||
| 164 | - aclrtResetDevice(deviceId); | ||
| 165 | - aclFinalize(); | ||
| 166 | 158 | ||
| 167 | - return 0; | 159 | + // 7. 释放device 资源 |
| 160 | + aclrtFree(selfDeviceAddr); | ||
| 161 | + aclrtFree(shape1DeviceAddr); | ||
| 162 | + aclrtFree(shape2DeviceAddr); | ||
| 163 | + if (workspaceSize > 0) { | ||
| 164 | + aclrtFree(workspaceAddr); | ||
| 165 | + } | ||
| 166 | + aclrtDestroyStream(stream); | ||
| 167 | + aclrtResetDevice(deviceId); | ||
| 168 | + aclFinalize(); | ||
| 169 | + | ||
| 170 | + return 0; | ||
| 168 | } | 171 | } |
| @@ -25,7 +25,6 @@ | |||
| 25 | 25 | ||
| 26 | 26 | ||
| 27 | 27 | ||
| 28 | - | ||
| 29 | using namespace op; | 28 | using namespace op; |
| 30 | 29 | ||
| 31 | extern "C" { | 30 | extern "C" { |
| @@ -37,255 +36,268 @@ constexpr int64_t SPLIT_LOOP_SIZE_512 = 512; | |||
| 37 | 36 | ||
| 38 | // 根据API定义,需要列出所能支持的所有dtype | 37 | // 根据API定义,需要列出所能支持的所有dtype |
| 39 | static const std::initializer_list<DataType> DTYPE_SUPPORT_LIST = { | 38 | static const std::initializer_list<DataType> DTYPE_SUPPORT_LIST = { |
| 40 | - DataType::DT_DOUBLE, DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16, | 39 | + DataType::DT_DOUBLE, DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16, |
| 41 | - DataType::DT_INT64, DataType::DT_INT32, DataType::DT_INT16, DataType::DT_INT8, | 40 | + DataType::DT_INT64, DataType::DT_INT32, DataType::DT_INT16, DataType::DT_INT8, |
| 42 | - DataType::DT_UINT8, DataType::DT_BOOL, DataType::DT_COMPLEX128, DataType::DT_COMPLEX64}; | 41 | + DataType::DT_UINT8, DataType::DT_BOOL, DataType::DT_COMPLEX128, DataType::DT_COMPLEX64}; |
| 43 | 42 | ||
| 44 | static const std::initializer_list<DataType> DTYPE_SUPPORT_LIST_950 = { | 43 | static const std::initializer_list<DataType> DTYPE_SUPPORT_LIST_950 = { |
| 45 | - DataType::DT_DOUBLE, DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16, | 44 | + DataType::DT_DOUBLE, DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16, DataType::DT_INT64, |
| 46 | - DataType::DT_INT64, DataType::DT_UINT64, DataType::DT_INT32, DataType::DT_UINT32, | 45 | + DataType::DT_UINT64, DataType::DT_INT32, DataType::DT_UINT32, DataType::DT_INT16, DataType::DT_UINT16, |
| 47 | - DataType::DT_INT16, DataType::DT_UINT16, DataType::DT_INT8, DataType::DT_UINT8, | 46 | + DataType::DT_INT8, DataType::DT_UINT8, DataType::DT_BOOL, DataType::DT_COMPLEX128, DataType::DT_COMPLEX64}; |
| 48 | - DataType::DT_BOOL, DataType::DT_COMPLEX128, DataType::DT_COMPLEX64}; | ||
| 49 | 47 | ||
| 50 | -inline static bool CheckNotNull(const aclTensor *self, const aclTensorList *out) { | 48 | +inline static bool CheckNotNull(const aclTensor* self, const aclTensorList* out) |
| 51 | - OP_CHECK_NULL(self, return false); | 49 | +{ |
| 52 | - OP_CHECK_NULL(out, return false); | 50 | + OP_CHECK_NULL(self, return false); |
| 53 | - return true; | 51 | + OP_CHECK_NULL(out, return false); |
| 52 | + return true; | ||
| 54 | } | 53 | } |
| 55 | 54 | ||
| 56 | -inline static bool CheckDtypeValid(const aclTensor *self, const aclTensorList *out) { | 55 | +inline static bool CheckDtypeValid(const aclTensor* self, const aclTensorList* out) |
| 57 | - if (IsRegBase()) { | 56 | +{ |
| 58 | - OP_CHECK_DTYPE_NOT_SUPPORT(self, DTYPE_SUPPORT_LIST_950, return false); | 57 | + if (IsRegBase()) { |
| 59 | - // 检查每一个输出tensor的数据类型是否在API支持列表内 | 58 | + OP_CHECK_DTYPE_NOT_SUPPORT(self, DTYPE_SUPPORT_LIST_950, return false); |
| 60 | - for (size_t index = 0; index < out->Size(); index++) { | 59 | + // 检查每一个输出tensor的数据类型是否在API支持列表内 |
| 61 | - OP_CHECK_DTYPE_NOT_SUPPORT((*out)[index], DTYPE_SUPPORT_LIST_950, return false); | 60 | + for (size_t index = 0; index < out->Size(); index++) { |
| 61 | + OP_CHECK_DTYPE_NOT_SUPPORT((*out)[index], DTYPE_SUPPORT_LIST_950, return false); | ||
| 62 | + } | ||
| 63 | + } else { | ||
| 64 | + OP_CHECK_DTYPE_NOT_SUPPORT(self, DTYPE_SUPPORT_LIST, return false); | ||
| 65 | + // 检查每一个输出tensor的数据类型是否在API支持列表内 | ||
| 66 | + for (size_t index = 0; index < out->Size(); index++) { | ||
| 67 | + OP_CHECK_DTYPE_NOT_SUPPORT((*out)[index], DTYPE_SUPPORT_LIST, return false); | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + // 检查所有输出tensor的数据类型是否一致 | ||
| 71 | + if (out->Size() >= 2) { | ||
| 72 | + for (size_t index = 1; index < out->Size(); index++) { | ||
| 73 | + OP_CHECK_DTYPE_NOT_SAME((*out)[0], (*out)[index], return false); | ||
| 74 | + } | ||
| 62 | } | 75 | } |
| 63 | return true; | 76 | return true; |
| 64 | - } | ||
| 65 | - OP_CHECK_DTYPE_NOT_SUPPORT(self, DTYPE_SUPPORT_LIST, return false); | ||
| 66 | - // 检查每一个输出tensor的数据类型是否在API支持列表内 | ||
| 67 | - for (size_t index = 0; index < out->Size(); index++) { | ||
| 68 | - OP_CHECK_DTYPE_NOT_SUPPORT((*out)[index], DTYPE_SUPPORT_LIST, return false); | ||
| 69 | - } | ||
| 70 | - return true; | ||
| 71 | } | 77 | } |
| 72 | 78 | ||
| 73 | -static bool CheckShape(const aclTensor *self, uint64_t splitSections, int64_t dim, const aclTensorList *out) { | 79 | +static bool CheckShape(const aclTensor* self, uint64_t splitSections, int64_t dim, const aclTensorList* out) |
| 74 | - // 校验输入的长度 | 80 | +{ |
| 75 | - OP_CHECK_MAX_DIM(self, MAX_DIM_LEN, return false); | 81 | + // 校验输入的长度 |
| 76 | - OP_CHECK_MIN_DIM(self, 1, return false); | 82 | + OP_CHECK_MAX_DIM(self, MAX_DIM_LEN, return false); |
| 77 | - // 校验每一个输出的长度 | 83 | + OP_CHECK_MIN_DIM(self, 1, return false); |
| 78 | - for (size_t index = 0; index < out->Size(); index++) { | 84 | + // 校验每一个输出的长度 |
| 79 | - OP_CHECK_MAX_DIM((*out)[index], MAX_DIM_LEN, return false); | 85 | + for (size_t index = 0; index < out->Size(); index++) { |
| 80 | - } | 86 | + OP_CHECK_MAX_DIM((*out)[index], MAX_DIM_LEN, return false); |
| 81 | - // 校验输入self与dim间关系 | 87 | + } |
| 82 | - int64_t selfDim = static_cast<int64_t>(self->GetViewShape().GetDimNum()); | 88 | + // 校验输入self与dim间关系 |
| 83 | - if ((dim >= 0 && dim >= selfDim) || (dim < 0 && dim < -selfDim)) { | 89 | + int64_t selfDim = static_cast<int64_t>(self->GetViewShape().GetDimNum()); |
| 84 | - OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, | 90 | + if ((dim >= 0 && dim >= selfDim) || (dim < 0 && dim < -selfDim)) { |
| 85 | - "Expected aclnnSplitTensor dim value [%ld] to be in range [%ld, %ld) but check failed.", | 91 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, |
| 86 | - dim, -selfDim, selfDim); | 92 | + "Expected aclnnSplitTensor dim value [%ld] to be in range [%ld, %ld) but check failed.", dim, -selfDim, |
| 87 | - return false; | 93 | + selfDim); |
| 88 | - } | 94 | + return false; |
| 89 | - size_t dimIndex = dim >= 0 ? static_cast<size_t>(dim) : static_cast<size_t>(dim + selfDim); | 95 | + } |
| 90 | - int64_t splitShape = self->GetViewShape().GetDim(dimIndex); | 96 | + size_t dimIndex = dim >= 0 ? static_cast<size_t>(dim) : static_cast<size_t>(dim + selfDim); |
| 91 | - if (splitShape != 0 && splitSections == 0) { | 97 | + int64_t splitShape = self->GetViewShape().GetDim(dimIndex); |
| 92 | - OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, | 98 | + if (splitShape != 0 && splitSections == 0) { |
| 99 | + OP_LOGE( | ||
| 100 | + ACLNN_ERR_PARAM_NULLPTR, | ||
| 93 | "Expected aclnnSplitTensor splitSections to not be zero while split dim size is not zero but got [%lu].", | 101 | "Expected aclnnSplitTensor splitSections to not be zero while split dim size is not zero but got [%lu].", |
| 94 | splitSections); | 102 | splitSections); |
| 95 | - return false; | 103 | + return false; |
| 96 | - } | ||
| 97 | - if (splitShape == 0 && splitSections != 0) { | ||
| 98 | - OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, | ||
| 99 | - "Expected aclnnSplitTensor splitSections to be zero while split dim size is zero but got [%lu].", | ||
| 100 | - splitSections); | ||
| 101 | - return false; | ||
| 102 | - } | ||
| 103 | - return true; | ||
| 104 | -} | ||
| 105 | - | ||
| 106 | -inline static aclnnStatus CheckParams(const aclTensor *self, uint64_t splitSections, int64_t dim, | ||
| 107 | - const aclTensorList *out) { | ||
| 108 | - // 1. 检查参数是否为空指针 | ||
| 109 | - CHECK_RET(CheckNotNull(self, out), ACLNN_ERR_PARAM_NULLPTR); | ||
| 110 | - | ||
| 111 | - // 2. 检查输入与输出的数据类型是否在API支持的数据类型范围之内 | ||
| 112 | - CHECK_RET(CheckDtypeValid(self, out), ACLNN_ERR_PARAM_INVALID); | ||
| 113 | - | ||
| 114 | - // 3. 检查输入输出的shape支持能力 | ||
| 115 | - CHECK_RET(CheckShape(self, splitSections, dim, out), ACLNN_ERR_PARAM_INVALID); | ||
| 116 | - | ||
| 117 | - return ACLNN_SUCCESS; | ||
| 118 | -} | ||
| 119 | - | ||
| 120 | -inline static aclnnStatus SplitZeroCalculation(const aclTensor *self, aclTensorList *out, aclOpExecutor *executor) { | ||
| 121 | - auto selfCast = l0op::Cast(self, (*out)[0]->GetDataType(), executor); | ||
| 122 | - CHECK_RET(selfCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 123 | - auto selfViewCopy = l0op::ViewCopy(selfCast, (*out)[0], executor); | ||
| 124 | - CHECK_RET(selfViewCopy != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 125 | - return ACLNN_SUCCESS; | ||
| 126 | -} | ||
| 127 | - | ||
| 128 | -static aclnnStatus SplitOnceCalculation(const aclTensor *self, const aclIntArray *splitSize, int64_t dim, | ||
| 129 | - aclTensorList *out, aclOpExecutor *executor) { | ||
| 130 | - // 调用SplitV算子 | ||
| 131 | - auto splitRes = l0op::SplitV(self, splitSize, dim, executor); | ||
| 132 | - // 循环调用Cast和ViewCopy | ||
| 133 | - if ((splitRes == nullptr) || (splitSize->Size() > out->Size()) || (splitSize->Size() > splitRes->Size())) { | ||
| 134 | - OP_LOGE(ACLNN_ERR_PARAM_INVALID, | ||
| 135 | - "Index value exceeds the out size range, splitSize->Size=%lu, splitRes->Size=%lu, out->Size=%lu", | ||
| 136 | - splitSize->Size(), splitRes->Size(), out->Size()); | ||
| 137 | - return ACLNN_ERR_PARAM_INVALID; | ||
| 138 | - } | ||
| 139 | - for (size_t index = 0; index < splitSize->Size(); index++) { | ||
| 140 | - CHECK_RET(CheckShapeAndScalarSame((*splitRes)[index], (*out)[index]), ACLNN_ERR_PARAM_INVALID); | ||
| 141 | - auto splitCast = l0op::Cast((*splitRes)[index], (*out)[index]->GetDataType(), executor); | ||
| 142 | - CHECK_RET(splitCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 143 | - auto splitViewCopy = l0op::ViewCopy(splitCast, (*out)[index], executor); | ||
| 144 | - CHECK_RET(splitViewCopy != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 145 | - } | ||
| 146 | - return ACLNN_SUCCESS; | ||
| 147 | -} | ||
| 148 | - | ||
| 149 | -static aclnnStatus SplitLoopCalculation(const aclTensor *self, const aclIntArray *splitSize, int64_t dim, | ||
| 150 | - aclTensorList *out, aclOpExecutor *executor) { | ||
| 151 | - const int64_t numSplit = splitSize->Size(); | ||
| 152 | - const int64_t splitLoopSize = (!IsRegBase()) ? | ||
| 153 | - SPLIT_LOOP_SIZE : SPLIT_LOOP_SIZE_512; | ||
| 154 | - const int64_t loopSize = (numSplit + splitLoopSize - 1) / splitLoopSize; | ||
| 155 | - const int64_t lastSize = (numSplit % splitLoopSize == 0) ? splitLoopSize : numSplit % splitLoopSize; | ||
| 156 | - // 1. 根据loopSize和lastSize, 将splitSize构造为新的SplitSize | ||
| 157 | - op::Shape selfShape = self->GetViewShape(); | ||
| 158 | - const size_t selfDim = selfShape.GetDimNum(); | ||
| 159 | - FVector<int64_t> newSplitSize; | ||
| 160 | - FVector<aclIntArray *> splitList; | ||
| 161 | - | ||
| 162 | - for (int64_t loopIndex = 0; loopIndex < loopSize; loopIndex++) { | ||
| 163 | - int64_t newSplit = 0; | ||
| 164 | - FVector<int64_t> chunkVector; | ||
| 165 | - int64_t currentSplitValue = 0; | ||
| 166 | - if (loopIndex != loopSize - 1) { | ||
| 167 | - for (int64_t noLastIndex = 0; noLastIndex < splitLoopSize; noLastIndex++) { | ||
| 168 | - currentSplitValue = *(splitSize->GetData() + loopIndex * splitLoopSize + noLastIndex); | ||
| 169 | - chunkVector.emplace_back(currentSplitValue); | ||
| 170 | - newSplit += currentSplitValue; | ||
| 171 | - } | ||
| 172 | - } else { | ||
| 173 | - for (int64_t lastIndex = 0; lastIndex < lastSize; lastIndex++) { | ||
| 174 | - currentSplitValue = *(splitSize->GetData() + loopIndex * splitLoopSize + lastIndex); | ||
| 175 | - chunkVector.emplace_back(currentSplitValue); | ||
| 176 | - newSplit += currentSplitValue; | ||
| 177 | - } | ||
| 178 | } | 104 | } |
| 179 | - splitList.emplace_back(executor->AllocIntArray(chunkVector.data(), chunkVector.size())); | 105 | + if (splitShape == 0 && splitSections != 0) { |
| 180 | - newSplitSize.emplace_back(newSplit); | 106 | + OP_LOGE(ACLNN_ERR_PARAM_NULLPTR, |
| 181 | - } | 107 | + "Expected aclnnSplitTensor splitSections to be zero while split dim size is zero but got [%lu].", |
| 182 | - | 108 | + splitSections); |
| 183 | - // 2. 循环调用Slice将self切成N个大块, 并对每个大块使用SplitV再次切分 | 109 | + return false; |
| 184 | - FVector<const aclTensor *> splitTensorList; | ||
| 185 | - int64_t offsetValue = 0; | ||
| 186 | - for (size_t sliceIndex = 0; sliceIndex < newSplitSize.size(); sliceIndex++) { | ||
| 187 | - // 计算offset, offset逐块递增 | ||
| 188 | - FVector<int64_t> offsetVector(selfDim, 0); | ||
| 189 | - offsetValue += sliceIndex == 0 ? 0 : newSplitSize[sliceIndex - 1]; | ||
| 190 | - offsetVector[static_cast<size_t>(dim)] = offsetValue; | ||
| 191 | - aclIntArray *offsetArray = executor->AllocIntArray(offsetVector.data(), offsetVector.size()); | ||
| 192 | - | ||
| 193 | - // 计算size, size与输出块大小保持一致 | ||
| 194 | - FVector<int64_t> sizeVector; | ||
| 195 | - for (size_t selfIndex = 0; selfIndex < selfDim; selfIndex++) { | ||
| 196 | - int64_t sizeValue = | ||
| 197 | - selfIndex == static_cast<size_t>(dim) ? newSplitSize[sliceIndex] : selfShape.GetDim(selfIndex); | ||
| 198 | - sizeVector.emplace_back(sizeValue); | ||
| 199 | } | 110 | } |
| 200 | - aclIntArray *sizeArray = executor->AllocIntArray(sizeVector.data(), sizeVector.size()); | 111 | + return true; |
| 112 | +} | ||
| 201 | 113 | ||
| 202 | - // 调用l0op::Slice对每一块进行处理 | 114 | +inline static aclnnStatus CheckParams(const aclTensor* self, uint64_t splitSections, int64_t dim, |
| 203 | - auto sliceRes = l0op::Slice(self, offsetArray, sizeArray, executor); | 115 | + const aclTensorList* out) |
| 204 | - CHECK_RET(sliceRes != nullptr, ACLNN_ERR_INNER_NULLPTR); | 116 | +{ |
| 117 | + // 1. 检查参数是否为空指针 | ||
| 118 | + CHECK_RET(CheckNotNull(self, out), ACLNN_ERR_PARAM_NULLPTR); | ||
| 205 | 119 | ||
| 206 | - // 调用l0op::SPlitV将sliceRes进行切分 | 120 | + // 2. 检查输入与输出的数据类型是否在API支持的数据类型范围之内 |
| 207 | - auto splitRes = l0op::SplitV(sliceRes, splitList[sliceIndex], dim, executor); | 121 | + CHECK_RET(CheckDtypeValid(self, out), ACLNN_ERR_PARAM_INVALID); |
| 208 | - CHECK_RET(splitRes != nullptr, ACLNN_ERR_INNER_NULLPTR); | 122 | + |
| 209 | - for (int64_t resIndex = 0; resIndex < static_cast<int64_t>(splitRes->Size()); resIndex++) { | 123 | + // 3. 检查输入输出的shape支持能力 |
| 210 | - if ((resIndex + sliceIndex * splitLoopSize) >= out->Size()) { | 124 | + CHECK_RET(CheckShape(self, splitSections, dim, out), ACLNN_ERR_PARAM_INVALID); |
| 125 | + | ||
| 126 | + return ACLNN_SUCCESS; | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +inline static aclnnStatus SplitZeroCalculation(const aclTensor* self, aclTensorList* out, aclOpExecutor* executor) | ||
| 130 | +{ | ||
| 131 | + auto selfCast = l0op::Cast(self, (*out)[0]->GetDataType(), executor); | ||
| 132 | + CHECK_RET(selfCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 133 | + auto selfViewCopy = l0op::ViewCopy(selfCast, (*out)[0], executor); | ||
| 134 | + CHECK_RET(selfViewCopy != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 135 | + return ACLNN_SUCCESS; | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +static aclnnStatus SplitOnceCalculation(const aclTensor* self, const aclIntArray* splitSize, int64_t dim, | ||
| 139 | + aclTensorList* out, aclOpExecutor* executor) | ||
| 140 | +{ | ||
| 141 | + // 调用SplitV算子 | ||
| 142 | + auto splitRes = l0op::SplitV(self, splitSize, dim, executor); | ||
| 143 | + // 循环调用Cast和ViewCopy | ||
| 144 | + if ((splitRes == nullptr) || (splitSize->Size() > out->Size()) || (splitSize->Size() > splitRes->Size())) { | ||
| 211 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, | 145 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, |
| 212 | - "Index value exceeds the out size range, resIndex=%ld, sliceIndex=%zu, out->Size=%lu", | 146 | + "Index value exceeds the out size range, splitSize->Size=%lu, splitRes->Size=%lu, out->Size=%lu", |
| 213 | - resIndex, sliceIndex, out->Size()); | 147 | + splitSize->Size(), splitRes->Size(), out->Size()); |
| 214 | return ACLNN_ERR_PARAM_INVALID; | 148 | return ACLNN_ERR_PARAM_INVALID; |
| 215 | - } | ||
| 216 | - auto splitCast = l0op::Cast((*splitRes)[resIndex], (*out)[resIndex + sliceIndex * splitLoopSize]->GetDataType(), | ||
| 217 | - executor); | ||
| 218 | - CHECK_RET(splitCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 219 | - auto splitViewCopy = l0op::ViewCopy(splitCast, (*out)[resIndex + sliceIndex * splitLoopSize], executor); | ||
| 220 | - CHECK_RET(splitViewCopy != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 221 | } | 149 | } |
| 222 | - } | 150 | + for (size_t index = 0; index < splitSize->Size(); index++) { |
| 223 | - return ACLNN_SUCCESS; | 151 | + CHECK_RET(CheckShapeAndScalarSame((*splitRes)[index], (*out)[index]), ACLNN_ERR_PARAM_INVALID); |
| 152 | + auto splitCast = l0op::Cast((*splitRes)[index], (*out)[index]->GetDataType(), executor); | ||
| 153 | + CHECK_RET(splitCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 154 | + auto splitViewCopy = l0op::ViewCopy(splitCast, (*out)[index], executor); | ||
| 155 | + CHECK_RET(splitViewCopy != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 156 | + } | ||
| 157 | + return ACLNN_SUCCESS; | ||
| 224 | } | 158 | } |
| 225 | 159 | ||
| 226 | -aclnnStatus aclnnSplitTensorGetWorkspaceSize(const aclTensor *self, uint64_t splitSections, int64_t dim, | 160 | +static aclnnStatus SplitLoopCalculation(const aclTensor* self, const aclIntArray* splitSize, int64_t dim, |
| 227 | - aclTensorList *out, uint64_t *workspaceSize, aclOpExecutor **executor) { | 161 | + aclTensorList* out, aclOpExecutor* executor) |
| 228 | - L2_DFX_PHASE_1(aclnnSplitTensor, DFX_IN(self, splitSections, dim), DFX_OUT(out)); | 162 | +{ |
| 163 | + const int64_t numSplit = splitSize->Size(); | ||
| 164 | + const int64_t splitLoopSize = (!IsRegBase()) ? SPLIT_LOOP_SIZE : SPLIT_LOOP_SIZE_512; | ||
| 165 | + const int64_t loopSize = (numSplit + splitLoopSize - 1) / splitLoopSize; | ||
| 166 | + const int64_t lastSize = (numSplit % splitLoopSize == 0) ? splitLoopSize : numSplit % splitLoopSize; | ||
| 167 | + // 1. 根据loopSize和lastSize, 将splitSize构造为新的SplitSize | ||
| 168 | + op::Shape selfShape = self->GetViewShape(); | ||
| 169 | + const size_t selfDim = selfShape.GetDimNum(); | ||
| 170 | + FVector<int64_t> newSplitSize; | ||
| 171 | + FVector<aclIntArray*> splitList; | ||
| 229 | 172 | ||
| 230 | - // 固定写法,创建OpExecutor | 173 | + for (int64_t loopIndex = 0; loopIndex < loopSize; loopIndex++) { |
| 231 | - auto uniqueExecutor = CREATE_EXECUTOR(); | 174 | + int64_t newSplit = 0; |
| 232 | - CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | 175 | + FVector<int64_t> chunkVector; |
| 176 | + int64_t currentSplitValue = 0; | ||
| 177 | + if (loopIndex != loopSize - 1) { | ||
| 178 | + for (int64_t noLastIndex = 0; noLastIndex < splitLoopSize; noLastIndex++) { | ||
| 179 | + currentSplitValue = *(splitSize->GetData() + loopIndex * splitLoopSize + noLastIndex); | ||
| 180 | + chunkVector.emplace_back(currentSplitValue); | ||
| 181 | + newSplit += currentSplitValue; | ||
| 182 | + } | ||
| 183 | + } else { | ||
| 184 | + for (int64_t lastIndex = 0; lastIndex < lastSize; lastIndex++) { | ||
| 185 | + currentSplitValue = *(splitSize->GetData() + loopIndex * splitLoopSize + lastIndex); | ||
| 186 | + chunkVector.emplace_back(currentSplitValue); | ||
| 187 | + newSplit += currentSplitValue; | ||
| 188 | + } | ||
| 189 | + } | ||
| 190 | + splitList.emplace_back(executor->AllocIntArray(chunkVector.data(), chunkVector.size())); | ||
| 191 | + newSplitSize.emplace_back(newSplit); | ||
| 192 | + } | ||
| 233 | 193 | ||
| 234 | - // 固定写法,参数检查 | 194 | + // 2. 循环调用Slice将self切成N个大块, 并对每个大块使用SplitV再次切分 |
| 235 | - auto ret = CheckParams(self, splitSections, dim, out); | 195 | + FVector<const aclTensor*> splitTensorList; |
| 236 | - CHECK_RET(ret == ACLNN_SUCCESS, ret); | 196 | + int64_t offsetValue = 0; |
| 197 | + for (size_t sliceIndex = 0; sliceIndex < newSplitSize.size(); sliceIndex++) { | ||
| 198 | + // 计算offset, offset逐块递增 | ||
| 199 | + FVector<int64_t> offsetVector(selfDim, 0); | ||
| 200 | + offsetValue += sliceIndex == 0 ? 0 : newSplitSize[sliceIndex - 1]; | ||
| 201 | + offsetVector[static_cast<size_t>(dim)] = offsetValue; | ||
| 202 | + aclIntArray* offsetArray = executor->AllocIntArray(offsetVector.data(), offsetVector.size()); | ||
| 237 | 203 | ||
| 238 | - // 修正dim取值 | 204 | + // 计算size, size与输出块大小保持一致 |
| 239 | - if (dim < 0) { | 205 | + FVector<int64_t> sizeVector; |
| 240 | - dim += static_cast<int64_t>(self->GetViewShape().GetDimNum()); | 206 | + for (size_t selfIndex = 0; selfIndex < selfDim; selfIndex++) { |
| 241 | - } | 207 | + int64_t sizeValue = selfIndex == static_cast<size_t>(dim) ? newSplitSize[sliceIndex] : |
| 208 | + selfShape.GetDim(selfIndex); | ||
| 209 | + sizeVector.emplace_back(sizeValue); | ||
| 210 | + } | ||
| 211 | + aclIntArray* sizeArray = executor->AllocIntArray(sizeVector.data(), sizeVector.size()); | ||
| 242 | 212 | ||
| 243 | - int64_t dimSize = self->GetViewShape().GetDim(static_cast<size_t>(dim)); | 213 | + // 调用l0op::Slice对每一块进行处理 |
| 244 | - // 空tensor处理 | 214 | + auto sliceRes = l0op::Slice(self, offsetArray, sizeArray, executor); |
| 245 | - if (self->IsEmpty()) { | 215 | + CHECK_RET(sliceRes != nullptr, ACLNN_ERR_INNER_NULLPTR); |
| 246 | - *workspaceSize = 0; | 216 | + |
| 217 | + // 调用l0op::SPlitV将sliceRes进行切分 | ||
| 218 | + auto splitRes = l0op::SplitV(sliceRes, splitList[sliceIndex], dim, executor); | ||
| 219 | + CHECK_RET(splitRes != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 220 | + for (int64_t resIndex = 0; resIndex < static_cast<int64_t>(splitRes->Size()); resIndex++) { | ||
| 221 | + if ((resIndex + sliceIndex * splitLoopSize) >= out->Size()) { | ||
| 222 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID, | ||
| 223 | + "Index value exceeds the out size range, resIndex=%ld, sliceIndex=%zu, out->Size=%lu", resIndex, | ||
| 224 | + sliceIndex, out->Size()); | ||
| 225 | + return ACLNN_ERR_PARAM_INVALID; | ||
| 226 | + } | ||
| 227 | + auto splitCast = l0op::Cast((*splitRes)[resIndex], | ||
| 228 | + (*out)[resIndex + sliceIndex * splitLoopSize]->GetDataType(), executor); | ||
| 229 | + CHECK_RET(splitCast != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 230 | + auto splitViewCopy = l0op::ViewCopy(splitCast, (*out)[resIndex + sliceIndex * splitLoopSize], executor); | ||
| 231 | + CHECK_RET(splitViewCopy != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 232 | + } | ||
| 233 | + } | ||
| 234 | + return ACLNN_SUCCESS; | ||
| 235 | +} | ||
| 236 | + | ||
| 237 | +aclnnStatus aclnnSplitTensorGetWorkspaceSize(const aclTensor* self, uint64_t splitSections, int64_t dim, | ||
| 238 | + aclTensorList* out, uint64_t* workspaceSize, aclOpExecutor** executor) | ||
| 239 | +{ | ||
| 240 | + L2_DFX_PHASE_1(aclnnSplitTensor, DFX_IN(self, splitSections, dim), DFX_OUT(out)); | ||
| 241 | + | ||
| 242 | + // 固定写法,创建OpExecutor | ||
| 243 | + auto uniqueExecutor = CREATE_EXECUTOR(); | ||
| 244 | + CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | ||
| 245 | + | ||
| 246 | + // 固定写法,参数检查 | ||
| 247 | + auto ret = CheckParams(self, splitSections, dim, out); | ||
| 248 | + CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 249 | + | ||
| 250 | + // 修正dim取值 | ||
| 251 | + if (dim < 0) { | ||
| 252 | + dim += static_cast<int64_t>(self->GetViewShape().GetDimNum()); | ||
| 253 | + } | ||
| 254 | + | ||
| 255 | + int64_t dimSize = self->GetViewShape().GetDim(static_cast<size_t>(dim)); | ||
| 256 | + // 空tensor处理 | ||
| 257 | + if (self->IsEmpty()) { | ||
| 258 | + *workspaceSize = 0; | ||
| 259 | + uniqueExecutor.ReleaseTo(executor); | ||
| 260 | + return ACLNN_SUCCESS; | ||
| 261 | + } | ||
| 262 | + | ||
| 263 | + // 固定写法,将输入self转换成连续的tensor | ||
| 264 | + auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | ||
| 265 | + CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 266 | + | ||
| 267 | + // 根据数据类型和输出个数判断调用对应的实现函数 | ||
| 268 | + if (dimSize == static_cast<int64_t>(splitSections)) { | ||
| 269 | + // 无需调用SplitV,直接进行Cast和ViewCopy即可 | ||
| 270 | + ret = SplitZeroCalculation(selfContiguous, out, uniqueExecutor.get()); | ||
| 271 | + } else { | ||
| 272 | + // 计算输出个数, if splitSections > dimSize, split only one | ||
| 273 | + int64_t numSplit = (dimSize + static_cast<int64_t>(splitSections) - 1) / static_cast<int64_t>(splitSections); | ||
| 274 | + int64_t lastSplitSize = splitSections - (static_cast<int64_t>(splitSections) * numSplit - dimSize); | ||
| 275 | + // 构造算子依赖的splitSize | ||
| 276 | + FVector<int64_t> splitVector(numSplit, static_cast<int64_t>(splitSections)); | ||
| 277 | + splitVector[numSplit - 1] = lastSplitSize; | ||
| 278 | + aclIntArray* splitSize = uniqueExecutor.get()->AllocIntArray(splitVector.data(), splitVector.size()); | ||
| 279 | + // 在SplitV算子的AiCore场景或者输出个数超过32个时,使用循环切分 | ||
| 280 | + if (l0op::SplitVAiCoreSupport(selfContiguous) && splitSize->Size() > SPLIT_LOOP_SIZE && !IsRegBase()) { | ||
| 281 | + ret = SplitLoopCalculation(selfContiguous, splitSize, dim, out, uniqueExecutor.get()); | ||
| 282 | + } else if (splitSize->Size() > SPLIT_LOOP_SIZE_512) { | ||
| 283 | + ret = SplitLoopCalculation(selfContiguous, splitSize, dim, out, uniqueExecutor.get()); | ||
| 284 | + } else { | ||
| 285 | + ret = SplitOnceCalculation(selfContiguous, splitSize, dim, out, uniqueExecutor.get()); | ||
| 286 | + } | ||
| 287 | + } | ||
| 288 | + CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 289 | + | ||
| 290 | + // 固定写法,获取计算过程中需要使用的workspace大小 | ||
| 291 | + *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 247 | uniqueExecutor.ReleaseTo(executor); | 292 | uniqueExecutor.ReleaseTo(executor); |
| 248 | return ACLNN_SUCCESS; | 293 | return ACLNN_SUCCESS; |
| 249 | - } | ||
| 250 | - | ||
| 251 | - // 固定写法,将输入self转换成连续的tensor | ||
| 252 | - auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | ||
| 253 | - CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 254 | - | ||
| 255 | - // 根据数据类型和输出个数判断调用对应的实现函数 | ||
| 256 | - if (dimSize == static_cast<int64_t>(splitSections)) { | ||
| 257 | - // 无需调用SplitV,直接进行Cast和ViewCopy即可 | ||
| 258 | - ret = SplitZeroCalculation(selfContiguous, out, uniqueExecutor.get()); | ||
| 259 | - } else { | ||
| 260 | - // 计算输出个数, if splitSections > dimSize, split only one | ||
| 261 | - int64_t numSplit = (dimSize + static_cast<int64_t>(splitSections) - 1) / static_cast<int64_t>(splitSections); | ||
| 262 | - int64_t lastSplitSize = splitSections - (static_cast<int64_t>(splitSections) * numSplit - dimSize); | ||
| 263 | - // 构造算子依赖的splitSize | ||
| 264 | - FVector<int64_t> splitVector(numSplit, static_cast<int64_t>(splitSections)); | ||
| 265 | - splitVector[numSplit - 1] = lastSplitSize; | ||
| 266 | - aclIntArray *splitSize = uniqueExecutor.get()->AllocIntArray(splitVector.data(), splitVector.size()); | ||
| 267 | - // 在SplitV算子的AiCore场景或者输出个数超过32个时,使用循环切分 | ||
| 268 | - if (l0op::SplitVAiCoreSupport(selfContiguous) && splitSize->Size() > SPLIT_LOOP_SIZE && | ||
| 269 | - !IsRegBase()) { | ||
| 270 | - ret = SplitLoopCalculation(selfContiguous, splitSize, dim, out, uniqueExecutor.get()); | ||
| 271 | - } else if (splitSize->Size() > SPLIT_LOOP_SIZE_512) { | ||
| 272 | - ret = SplitLoopCalculation(selfContiguous, splitSize, dim, out, uniqueExecutor.get()); | ||
| 273 | - } else { | ||
| 274 | - ret = SplitOnceCalculation(selfContiguous, splitSize, dim, out, uniqueExecutor.get()); | ||
| 275 | - } | ||
| 276 | - } | ||
| 277 | - CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 278 | - | ||
| 279 | - // 固定写法,获取计算过程中需要使用的workspace大小 | ||
| 280 | - *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 281 | - uniqueExecutor.ReleaseTo(executor); | ||
| 282 | - return ACLNN_SUCCESS; | ||
| 283 | } | 294 | } |
| 284 | 295 | ||
| 285 | -aclnnStatus aclnnSplitTensor(void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream) { | 296 | +aclnnStatus aclnnSplitTensor(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) |
| 286 | - L2_DFX_PHASE_2(aclnnSplitTensor); | 297 | +{ |
| 287 | - // 固定写法,调用框架能力,完成计算 | 298 | + L2_DFX_PHASE_2(aclnnSplitTensor); |
| 288 | - return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | 299 | + // 固定写法,调用框架能力,完成计算 |
| 300 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 289 | } | 301 | } |
| 290 | 302 | ||
| 291 | 303 | ||