已合并
[CANNBOT]atanh 算子修改tiling #3184
wangweidong创建于 6月8日
[CANNBOT]atanh 算子修改tiling #3184
已合并
共 4 个文件变更+256-193
| @@ -16,114 +16,140 @@ | |||
| 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 | 25 | ||
| 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 | -{ | 31 | + int64_t shapeSize = 1; |
| 32 | - int64_t shapeSize = 1; | 32 | + for (auto i : shape) { |
| 33 | - for (auto i : shape) { | 33 | + shapeSize *= i; |
| 34 | - shapeSize *= i; | 34 | + } |
| 35 | - } | 35 | + return shapeSize; |
| 36 | - return shapeSize; | ||
| 37 | } | 36 | } |
| 38 | 37 | ||
| 39 | -int Init(int32_t deviceId, aclrtStream* stream) | 38 | +int Init(int32_t deviceId, aclrtStream* stream) { |
| 40 | -{ | 39 | + // 固定写法,资源初始化 |
| 41 | - auto ret = aclInit(nullptr); | 40 | + auto ret = aclInit(nullptr); |
| 42 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 41 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 43 | - ret = aclrtSetDevice(deviceId); | 42 | + ret = aclrtSetDevice(deviceId); |
| 44 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 43 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 45 | - ret = aclrtCreateStream(stream); | 44 | + ret = aclrtCreateStream(stream); |
| 46 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 45 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 47 | - return 0; | 46 | + return 0; |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | template <typename T> | 49 | template <typename T> |
| 51 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 50 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 52 | - aclDataType dataType, aclTensor** tensor) | 51 | + aclDataType dataType, aclTensor** tensor) { |
| 53 | -{ | 52 | + auto size = GetShapeSize(shape) * sizeof(T); |
M | |||
| 54 | - auto size = GetShapeSize(shape) * sizeof(T); | 53 | + // 调用aclrtMalloc申请device侧内存 |
| 55 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 54 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 56 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 55 | + 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); | 56 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 58 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 57 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 58 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 59 | 59 | ||
| 60 | - std::vector<int64_t> strides(shape.size(), 1); | 60 | + // 计算连续tensor的strides |
| 61 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 61 | + std::vector<int64_t> strides(shape.size(), 1); |
| 62 | - strides[i] = shape[i + 1] * strides[i + 1]; | 62 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 63 | - } | 63 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 64 | + } | ||
| 64 | 65 | ||
| 65 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, | 66 | + // 调用aclCreateTensor接口创建aclTensor |
| 66 | - aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); | 67 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); |
| 67 | - return 0; | 68 | + return 0; |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | -int main() | 71 | +int main() { |
| 71 | -{ | 72 | + // 1. (固定写法)device/stream初始化,参考acl API手册 |
| 72 | - int32_t deviceId = 0; | 73 | + // 根据自己的实际device填写deviceId |
| 73 | - aclrtStream stream; | 74 | + int32_t deviceId = 0; |
| 74 | - auto ret = Init(deviceId, &stream); | 75 | + aclrtStream stream; |
| 75 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 76 | + auto ret = Init(deviceId, &stream); |
| 77 | + // check根据自己的需要处理 | ||
| 78 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 79 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 80 | + std::vector<int64_t> selfShape = {4, 2}; | ||
| 81 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 82 | + void* selfDeviceAddr = nullptr; | ||
| 83 | + void* outDeviceAddr = nullptr; | ||
| 84 | + aclTensor* self = nullptr; | ||
| 85 | + aclTensor* out = nullptr; | ||
| 86 | + std::vector<float> selfHostData = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; | ||
| 87 | + std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 88 | + // 创建self aclTensor | ||
| 89 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 90 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 91 | + // 创建out aclTensor | ||
| 92 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 93 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 76 | 94 | ||
| 77 | - std::vector<int64_t> selfShape = {4, 2}; | 95 | + // aclnnAtanh接口调用示例 |
| 78 | - std::vector<int64_t> outShape = {4, 2}; | 96 | + // 3. 调用CANN算子库API |
| 79 | - void* selfDeviceAddr = nullptr; | 97 | + // 调用aclnnAtanh第一段接口 |
| 80 | - void* outDeviceAddr = nullptr; | 98 | + uint64_t workspaceSize = 0; |
| 81 | - aclTensor* self = nullptr; | 99 | + aclOpExecutor* executor; |
| 82 | - aclTensor* out = nullptr; | 100 | + ret = aclnnAtanhGetWorkspaceSize(self, out, &workspaceSize, &executor); |
| 83 | - std::vector<float> selfHostData = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; | 101 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanhGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); |
| 84 | - std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | 102 | + // 根据第一段接口计算出的workspaceSize申请device内存 |
| 103 | + void* workspaceAddr = nullptr; | ||
| 104 | + if (workspaceSize > 0) { | ||
| 105 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 106 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 107 | + } | ||
| 108 | + // 调用aclnnAtanh第二段接口 | ||
| 109 | + ret = aclnnAtanh(workspaceAddr, workspaceSize, executor, stream); | ||
| 110 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanh failed. ERROR: %d\n", ret); return ret); | ||
| 111 | + | ||
| 112 | + // aclnnInplaceAtanh接口调用示例 | ||
| 113 | + uint64_t inplaceWorkspaceSize = 0; | ||
| 114 | + aclOpExecutor* inplaceExecutor; | ||
| 115 | + ret = aclnnInplaceAtanhGetWorkspaceSize(self, &inplaceWorkspaceSize, &inplaceExecutor); | ||
| 116 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnInplaceAtanhGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 117 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 118 | + void* inplaceWorkspaceAddr = nullptr; | ||
| 119 | + if (inplaceWorkspaceSize > 0) { | ||
| 120 | + ret = aclrtMalloc(&inplaceWorkspaceAddr, inplaceWorkspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 121 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 122 | + } | ||
| 123 | + // 调用aclnnInplaceAtanh第二段接口 | ||
| 124 | + ret = aclnnInplaceAtanh(inplaceWorkspaceAddr, inplaceWorkspaceSize, inplaceExecutor, stream); | ||
| 125 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnInplaceAtanh 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); | ||
| 85 | 130 | ||
| 86 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 131 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 |
| 87 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 132 | + auto size = GetShapeSize(outShape); |
| 88 | - ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | 133 | + std::vector<float> resultData(size, 0); |
| 89 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 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 | + } | ||
| 90 | 140 | ||
| 91 | - uint64_t workspaceSize = 0; | 141 | + // 6. 释放aclTensor,需要根据具体API的接口定义修改 |
| 92 | - aclOpExecutor* executor; | 142 | + aclDestroyTensor(self); |
| 93 | - ret = aclnnAtanhGetWorkspaceSize(self, out, &workspaceSize, &executor); | 143 | + aclDestroyTensor(out); |
| 94 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanhGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | 144 | + |
| 95 | - | 145 | + // 7. 释放device资源,需要根据具体API的接口定义修改 |
| 96 | - void* workspaceAddr = nullptr; | 146 | + aclrtFree(selfDeviceAddr); |
| 97 | - if (workspaceSize > 0) { | 147 | + aclrtFree(outDeviceAddr); |
| 98 | - ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | 148 | + if (workspaceSize > 0) { |
| 99 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | 149 | + aclrtFree(workspaceAddr); |
| 100 | - } | 150 | + } |
| 101 | - | 151 | + aclrtDestroyStream(stream); |
| 102 | - ret = aclnnAtanh(workspaceAddr, workspaceSize, executor, stream); | 152 | + aclrtResetDevice(deviceId); |
| 103 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanh failed. ERROR: %d\n", ret); return ret); | 153 | + aclFinalize(); |
| 104 | - | 154 | + return 0; |
| 105 | - ret = aclrtSynchronizeStream(stream); | 155 | +} |
| 106 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 107 | - | ||
| 108 | - auto size = GetShapeSize(outShape); | ||
| 109 | - std::vector<float> resultData(size, 0); | ||
| 110 | - ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 111 | - size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 112 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 113 | - for (int64_t i = 0; i < size; i++) { | ||
| 114 | - LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - aclDestroyTensor(self); | ||
| 118 | - aclDestroyTensor(out); | ||
| 119 | - | ||
| 120 | - aclrtFree(selfDeviceAddr); | ||
| 121 | - aclrtFree(outDeviceAddr); | ||
| 122 | - if (workspaceSize > 0) { | ||
| 123 | - aclrtFree(workspaceAddr); | ||
| 124 | - } | ||
| 125 | - aclrtDestroyStream(stream); | ||
| 126 | - aclrtResetDevice(deviceId); | ||
| 127 | - aclFinalize(); | ||
| 128 | - return 0; | ||
| 129 | -} | ||
| @@ -16,114 +16,140 @@ | |||
| 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 | 25 | ||
| 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 | -{ | 31 | + int64_t shapeSize = 1; |
| 32 | - int64_t shapeSize = 1; | 32 | + for (auto i : shape) { |
| 33 | - for (auto i : shape) { | 33 | + shapeSize *= i; |
| 34 | - shapeSize *= i; | 34 | + } |
| 35 | - } | 35 | + return shapeSize; |
| 36 | - return shapeSize; | ||
| 37 | } | 36 | } |
| 38 | 37 | ||
| 39 | -int Init(int32_t deviceId, aclrtStream* stream) | 38 | +int Init(int32_t deviceId, aclrtStream* stream) { |
| 40 | -{ | 39 | + // 固定写法,资源初始化 |
| 41 | - auto ret = aclInit(nullptr); | 40 | + auto ret = aclInit(nullptr); |
| 42 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 41 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 43 | - ret = aclrtSetDevice(deviceId); | 42 | + ret = aclrtSetDevice(deviceId); |
| 44 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 43 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 45 | - ret = aclrtCreateStream(stream); | 44 | + ret = aclrtCreateStream(stream); |
| 46 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 45 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 47 | - return 0; | 46 | + return 0; |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | template <typename T> | 49 | template <typename T> |
| 51 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 50 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 52 | - aclDataType dataType, aclTensor** tensor) | 51 | + aclDataType dataType, aclTensor** tensor) { |
| 53 | -{ | 52 | + auto size = GetShapeSize(shape) * sizeof(T); |
| 54 | - auto size = GetShapeSize(shape) * sizeof(T); | 53 | + // 调用aclrtMalloc申请device侧内存 |
| 55 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 54 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 56 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 55 | + 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); | 56 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 58 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | 57 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 58 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 59 | 59 | ||
| 60 | - std::vector<int64_t> strides(shape.size(), 1); | 60 | + // 计算连续tensor的strides |
| 61 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 61 | + std::vector<int64_t> strides(shape.size(), 1); |
| 62 | - strides[i] = shape[i + 1] * strides[i + 1]; | 62 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 63 | - } | 63 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 64 | + } | ||
| 64 | 65 | ||
| 65 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, | 66 | + // 调用aclCreateTensor接口创建aclTensor |
| 66 | - aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); | 67 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(), *deviceAddr); |
| 67 | - return 0; | 68 | + return 0; |
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | -int main() | 71 | +int main() { |
| 71 | -{ | 72 | + // 1. (固定写法)device/stream初始化,参考acl API手册 |
| 72 | - int32_t deviceId = 0; | 73 | + // 根据自己的实际device填写deviceId |
| 73 | - aclrtStream stream; | 74 | + int32_t deviceId = 0; |
| 74 | - auto ret = Init(deviceId, &stream); | 75 | + aclrtStream stream; |
| 75 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 76 | + auto ret = Init(deviceId, &stream); |
| 77 | + // check根据自己的需要处理 | ||
| 78 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 79 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 80 | + std::vector<int64_t> selfShape = {4, 2}; | ||
| 81 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 82 | + void* selfDeviceAddr = nullptr; | ||
| 83 | + void* outDeviceAddr = nullptr; | ||
| 84 | + aclTensor* self = nullptr; | ||
| 85 | + aclTensor* out = nullptr; | ||
| 86 | + std::vector<float> selfHostData = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; | ||
| 87 | + std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 88 | + // 创建self aclTensor | ||
| 89 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 90 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 91 | + // 创建out aclTensor | ||
| 92 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 93 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 76 | 94 | ||
| 77 | - std::vector<int64_t> selfShape = {4, 2}; | 95 | + // aclnnAtanh接口调用示例 |
| 78 | - std::vector<int64_t> outShape = {4, 2}; | 96 | + // 3. 调用CANN算子库API |
| 79 | - void* selfDeviceAddr = nullptr; | 97 | + // 调用aclnnAtanh第一段接口 |
| 80 | - void* outDeviceAddr = nullptr; | 98 | + uint64_t workspaceSize = 0; |
| 81 | - aclTensor* self = nullptr; | 99 | + aclOpExecutor* executor; |
| 82 | - aclTensor* out = nullptr; | 100 | + ret = aclnnAtanhGetWorkspaceSize(self, out, &workspaceSize, &executor); |
| 83 | - std::vector<float> selfHostData = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}; | 101 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanhGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); |
| 84 | - std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | 102 | + // 根据第一段接口计算出的workspaceSize申请device内存 |
| 103 | + void* workspaceAddr = nullptr; | ||
| 104 | + if (workspaceSize > 0) { | ||
| 105 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 106 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 107 | + } | ||
| 108 | + // 调用aclnnAtanh第二段接口 | ||
| 109 | + ret = aclnnAtanh(workspaceAddr, workspaceSize, executor, stream); | ||
| 110 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanh failed. ERROR: %d\n", ret); return ret); | ||
| 111 | + | ||
| 112 | + // aclnnInplaceAtanh接口调用示例 | ||
| 113 | + uint64_t inplaceWorkspaceSize = 0; | ||
| 114 | + aclOpExecutor* inplaceExecutor; | ||
| 115 | + ret = aclnnInplaceAtanhGetWorkspaceSize(self, &inplaceWorkspaceSize, &inplaceExecutor); | ||
| 116 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnInplaceAtanhGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 117 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 118 | + void* inplaceWorkspaceAddr = nullptr; | ||
| 119 | + if (inplaceWorkspaceSize > 0) { | ||
| 120 | + ret = aclrtMalloc(&inplaceWorkspaceAddr, inplaceWorkspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
W SEC-5.2 FAIL — 两个示例文件中,新增的 aclnnInplaceAtanh 路径申请了 inplaceWorkspaceAddr(aclrtMalloc,行 120),但清理阶段(行 146-151)未释放。原有 aclnnAtanh 的 workspaceAddr 有 aclrtFree,新增路径遗漏了对称释放。 修复:在 aclrtFree(workspaceAddr) 之后补充: if (inplaceWorkspaceSize > 0) { aclrtFree(inplaceWorkspaceAddr); } ![]() ![]() | |||
| 121 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 122 | + } | ||
| 123 | + // 调用aclnnInplaceAtanh第二段接口 | ||
| 124 | + ret = aclnnInplaceAtanh(inplaceWorkspaceAddr, inplaceWorkspaceSize, inplaceExecutor, stream); | ||
| 125 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnInplaceAtanh 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); | ||
| 85 | 130 | ||
| 86 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 131 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 |
| 87 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 132 | + auto size = GetShapeSize(outShape); |
| 88 | - ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | 133 | + std::vector<float> resultData(size, 0); |
| 89 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 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 | + } | ||
| 90 | 140 | ||
| 91 | - uint64_t workspaceSize = 0; | 141 | + // 6. 释放aclTensor,需要根据具体API的接口定义修改 |
| 92 | - aclOpExecutor* executor; | 142 | + aclDestroyTensor(self); |
| 93 | - ret = aclnnAtanhGetWorkspaceSize(self, out, &workspaceSize, &executor); | 143 | + aclDestroyTensor(out); |
| 94 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanhGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | 144 | + |
| 95 | - | 145 | + // 7. 释放device资源,需要根据具体API的接口定义修改 |
| 96 | - void* workspaceAddr = nullptr; | 146 | + aclrtFree(selfDeviceAddr); |
| 97 | - if (workspaceSize > 0) { | 147 | + aclrtFree(outDeviceAddr); |
| 98 | - ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | 148 | + if (workspaceSize > 0) { |
| 99 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | 149 | + aclrtFree(workspaceAddr); |
| 100 | - } | 150 | + } |
| 101 | - | 151 | + aclrtDestroyStream(stream); |
| 102 | - ret = aclnnAtanh(workspaceAddr, workspaceSize, executor, stream); | 152 | + aclrtResetDevice(deviceId); |
| 103 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnAtanh failed. ERROR: %d\n", ret); return ret); | 153 | + aclFinalize(); |
| 104 | - | 154 | + return 0; |
| 105 | - ret = aclrtSynchronizeStream(stream); | 155 | +} |
| 106 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 107 | - | ||
| 108 | - auto size = GetShapeSize(outShape); | ||
| 109 | - std::vector<float> resultData(size, 0); | ||
| 110 | - ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 111 | - size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 112 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 113 | - for (int64_t i = 0; i < size; i++) { | ||
| 114 | - LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 115 | - } | ||
| 116 | - | ||
| 117 | - aclDestroyTensor(self); | ||
| 118 | - aclDestroyTensor(out); | ||
| 119 | - | ||
| 120 | - aclrtFree(selfDeviceAddr); | ||
| 121 | - aclrtFree(outDeviceAddr); | ||
| 122 | - if (workspaceSize > 0) { | ||
| 123 | - aclrtFree(workspaceAddr); | ||
| 124 | - } | ||
| 125 | - aclrtDestroyStream(stream); | ||
| 126 | - aclrtResetDevice(deviceId); | ||
| 127 | - aclFinalize(); | ||
| 128 | - return 0; | ||
| 129 | -} | ||
| @@ -75,7 +75,13 @@ static ge::graphStatus AtanhTilingFunc(gert::TilingContext* context) | |||
| 75 | OP_LOGE(context, "set tiling data error"), return ge::GRAPH_FAILED); | 75 | OP_LOGE(context, "set tiling data error"), return ge::GRAPH_FAILED); |
| 76 | 76 | ||
| 77 | tiling->totalNum = totalNum; | 77 | tiling->totalNum = totalNum; |
| 78 | + // blockDim 必须封顶在物理 AIV 核数;SIMT 核内用 grid-stride 覆盖全部元素。 | ||
| 79 | + // 原实现 SetBlockDim(CeilDiv(totalNum, coreNum)) 会让 blockDim 随元素数线性膨胀, | ||
| 80 | + // 大 shape 下远超可用核数,触发 507035 vector core exception。 | ||
| 78 | int64_t usedCoreNum = Ops::Base::CeilDiv(totalNum, coreNum); | 81 | int64_t usedCoreNum = Ops::Base::CeilDiv(totalNum, coreNum); |
| 82 | + if (usedCoreNum > coreNum) { | ||
| 83 | + usedCoreNum = coreNum; | ||
| 84 | + } | ||
| 79 | if (usedCoreNum == 0) { | 85 | if (usedCoreNum == 0) { |
| 80 | usedCoreNum = 1; | 86 | usedCoreNum = 1; |
| 81 | } | 87 | } |
| @@ -37,9 +37,14 @@ template <typename T> | |||
| 37 | __simt_vf__ __aicore__ LAUNCH_BOUND(THREAD_NUM) | 37 | __simt_vf__ __aicore__ LAUNCH_BOUND(THREAD_NUM) |
| 38 | inline void OpAtanhSimtKernel(int64_t totalElements, __gm__ T* x, __gm__ T* y) | 38 | inline void OpAtanhSimtKernel(int64_t totalElements, __gm__ T* x, __gm__ T* y) |
| 39 | { | 39 | { |
| 40 | - for (uint64_t index = static_cast<uint64_t>(Simt::GetBlockIdx() * Simt::GetThreadNum() + Simt::GetThreadIdx()); | 40 | + // 全程使用 uint64 计算 index/stride,避免 blockIdx*threadNum 在 32-bit 下溢出(大元素数下越界)。 |
| 41 | - index < totalElements; | 41 | + uint64_t threadNum = static_cast<uint64_t>(Simt::GetThreadNum()); |
| 42 | - index += static_cast<uint32_t>(Simt::GetThreadNum() * Simt::GetBlockNum())) { | 42 | + uint64_t blockNum = static_cast<uint64_t>(Simt::GetBlockNum()); |
| 43 | + uint64_t total = static_cast<uint64_t>(totalElements); | ||
| 44 | + uint64_t stride = threadNum * blockNum; | ||
| 45 | + for (uint64_t index = static_cast<uint64_t>(Simt::GetBlockIdx()) * threadNum + static_cast<uint64_t>(Simt::GetThreadIdx()); | ||
| 46 | + index < total; | ||
| 47 | + index += stride) { | ||
| 43 | if constexpr (std::is_same_v<T, float>) { | 48 | if constexpr (std::is_same_v<T, float>) { |
| 44 | y[index] = atanhf(x[index]); | 49 | y[index] = atanhf(x[index]); |
| 45 | } else if constexpr (std::is_same_v<T, half>) { | 50 | } else if constexpr (std::is_same_v<T, half>) { |


确认缩进是否合理