已合并
fix foreach_addcmul_scalar int32 经 float24 往返丢失低位 #8650
east_yang创建于 13 天前
fix foreach_addcmul_scalar int32 经 float24 往返丢失低位 #8650
已合并
共 5 个文件变更+165-141
| @@ -13,141 +13,146 @@ | |||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | - do { \ | 16 | + do { \ |
| 17 | - if (!(cond)) { \ | 17 | + if (!(cond)) { \ |
| 18 | - return_expr; \ | 18 | + return_expr; \ |
| 19 | - } \ | 19 | + } \ |
| 20 | - } while(0) | 20 | + } while (0) |
| 21 | 21 | ||
| 22 | -#define LOG_PRINT(message, ...) \ | 22 | +#define LOG_PRINT(message, ...) \ |
| 23 | - do { \ | 23 | + do { \ |
| 24 | - printf(message, ##__VA_ARGS__); \ | 24 | + printf(message, ##__VA_ARGS__); \ |
| 25 | - } while(0) | 25 | + } while (0) |
| 26 | 26 | ||
| 27 | -int64_t GetShapeSize(const std::vector<int64_t>& shape) { | 27 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) |
| 28 | - int64_t shape_size = 1; | 28 | +{ |
| 29 | - for (auto i : shape) { | 29 | + int64_t shape_size = 1; |
| 30 | - shape_size *= i; | 30 | + for (auto i : shape) { |
| 31 | - } | 31 | + shape_size *= i; |
| 32 | - return shape_size; | 32 | + } |
| 33 | + return shape_size; | ||
| 33 | } | 34 | } |
| 34 | 35 | ||
| 35 | -int Init(int32_t deviceId, aclrtStream* stream) { | 36 | +int Init(int32_t deviceId, aclrtStream* stream) |
| 36 | - // 固定写法,资源初始化 | 37 | +{ |
| 37 | - auto ret = aclInit(nullptr); | 38 | + // 固定写法,资源初始化 |
| 38 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | 39 | + auto ret = aclInit(nullptr); |
| 39 | - ret = aclrtSetDevice(deviceId); | 40 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); |
| 40 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | 41 | + ret = aclrtSetDevice(deviceId); |
| 41 | - ret = aclrtCreateStream(stream); | 42 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); |
| 42 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | 43 | + ret = aclrtCreateStream(stream); |
| 43 | - return 0; | 44 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); |
| 45 | + return 0; | ||
| 44 | } | 46 | } |
| 45 | 47 | ||
| 46 | -template<typename T> | 48 | +template <typename T> |
| 47 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | 49 | int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, |
| 48 | - aclDataType dataType, aclTensor** tensor) { | 50 | + aclDataType dataType, aclTensor** tensor) |
| 49 | - auto size = GetShapeSize(shape) * sizeof(T); | 51 | +{ |
| 50 | - // 调用aclrtMalloc申请device侧引擎 | 52 | + auto size = GetShapeSize(shape) * sizeof(T); |
| 51 | - auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | 53 | + // 调用aclrtMalloc申请device侧引擎 |
| 52 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | 54 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); |
| 55 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | 56 | ||
| 54 | - // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | 57 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 |
| 55 | - ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | 58 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); |
| 56 | - if (ret != ACL_SUCCESS) { | 59 | + if (ret != ACL_SUCCESS) { |
| 57 | - LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); | 60 | + LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); |
| 58 | - aclrtFree(*deviceAddr); | 61 | + aclrtFree(*deviceAddr); |
| 59 | - *deviceAddr = nullptr; | 62 | + *deviceAddr = nullptr; |
| 60 | - return ret; | 63 | + return ret; |
| 61 | - } | 64 | + } |
| 62 | 65 | ||
| 63 | - // 计算连续tensor的strides | 66 | + // 计算连续tensor的strides |
| 64 | - std::vector<int64_t> strides(shape.size(), 1); | 67 | + std::vector<int64_t> strides(shape.size(), 1); |
| 65 | - for (int64_t i = shape.size() - 2; i >= 0; i--) { | 68 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { |
| 66 | - strides[i] = shape[i + 1] * strides[i + 1]; | 69 | + strides[i] = shape[i + 1] * strides[i + 1]; |
| 67 | - } | 70 | + } |
| 68 | 71 | ||
| 69 | - // 调用aclCreateTensor接口创建aclTensor | 72 | + // 调用aclCreateTensor接口创建aclTensor |
| 70 | - *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | 73 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, |
| 71 | - shape.data(), shape.size(), *deviceAddr); | 74 | + shape.data(), shape.size(), *deviceAddr); |
| 72 | - if (*tensor == nullptr) { | 75 | + if (*tensor == nullptr) { |
| 73 | - LOG_PRINT("aclCreateTensor failed.\n"); | 76 | + LOG_PRINT("aclCreateTensor failed.\n"); |
| 74 | - aclrtFree(*deviceAddr); | 77 | + aclrtFree(*deviceAddr); |
| 75 | - *deviceAddr = nullptr; | 78 | + *deviceAddr = nullptr; |
| 76 | - return -1; | 79 | + return -1; |
| 77 | - } | 80 | + } |
| 78 | - return 0; | 81 | + return 0; |
| 79 | } | 82 | } |
| 80 | 83 | ||
| 81 | -int main() { | 84 | +int main() |
| 82 | - // 1. (固定写法)device/stream初始化, 参考acl API手册 | 85 | +{ |
| 83 | - // 根据自己的实际device填写deviceId | 86 | + // 1. (固定写法)device/stream初始化, 参考acl API手册 |
| 84 | - int32_t deviceId = 0; | 87 | + // 根据自己的实际device填写deviceId |
| 85 | - aclrtStream stream; | 88 | + int32_t deviceId = 0; |
| 86 | - auto ret = Init(deviceId, &stream); | 89 | + aclrtStream stream; |
| 87 | - CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | 90 | + auto ret = Init(deviceId, &stream); |
| 88 | - // 2. 构造输入与输出,需要根据API的接口自定义构造 | 91 | + CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); |
| 89 | - std::vector<int64_t> selfShape = {4, 2}; | 92 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 |
| 90 | - std::vector<int64_t> gradOutputShape = {4, 2}; | 93 | + std::vector<int64_t> selfShape = {4, 2}; |
| 91 | - std::vector<int64_t> gradInputShape = {4, 2}; | 94 | + std::vector<int64_t> gradOutputShape = {4, 2}; |
| 92 | - void* selfDeviceAddr = nullptr; | 95 | + std::vector<int64_t> gradInputShape = {4, 2}; |
| 93 | - void* gradOutputDeviceAddr = nullptr; | 96 | + void* selfDeviceAddr = nullptr; |
| 94 | - void* gradInputDeviceAddr = nullptr; | 97 | + void* gradOutputDeviceAddr = nullptr; |
| 95 | - aclTensor* self = nullptr; | 98 | + void* gradInputDeviceAddr = nullptr; |
| 96 | - aclTensor* gradOutput = nullptr; | 99 | + aclTensor* self = nullptr; |
| 97 | - aclTensor* gradInput = nullptr; | 100 | + aclTensor* gradOutput = nullptr; |
| 98 | - std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | 101 | + aclTensor* gradInput = nullptr; |
| 99 | - std::vector<float> gradOutputHostData = {1, 1, 1, 1, 1, 1, 1, 1}; | 102 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; |
| 100 | - std::vector<float> gradInputHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | 103 | + std::vector<float> gradOutputHostData = {1, 1, 1, 1, 1, 1, 1, 1}; |
| 104 | + std::vector<float> gradInputHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 101 | 105 | ||
| 102 | - ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | 106 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); |
| 103 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 107 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 104 | - ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput); | 108 | + ret = CreateAclTensor(gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, |
| 105 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 109 | + &gradOutput); |
| 106 | - ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput); | 110 | + CHECK_RET(ret == ACL_SUCCESS, return ret); |
| 107 | - CHECK_RET(ret == ACL_SUCCESS, return ret); | 111 | + ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput); |
| 112 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 108 | 113 | ||
| 109 | - // 3. 调用CANN算子库API,需要修改为具体的API | 114 | + // 3. 调用CANN算子库API,需要修改为具体的API |
| 110 | - uint64_t workspaceSize = 0; | 115 | + uint64_t workspaceSize = 0; |
| 111 | - aclOpExecutor* executor; | 116 | + aclOpExecutor* executor; |
| 112 | - // 调用aclnnSeluBackward第一段接口 | 117 | + // 调用aclnnSeluBackward第一段接口 |
| 113 | - ret = aclnnSeluBackwardGetWorkspaceSize(gradOutput, self, gradInput, &workspaceSize, &executor); | 118 | + ret = aclnnSeluBackwardGetWorkspaceSize(gradOutput, self, gradInput, &workspaceSize, &executor); |
| 114 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSeluBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | 119 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSeluBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); |
| 115 | 120 | ||
| 116 | - // 根据第一段接口计算出的workspaceSize申请device内存 | 121 | + // 根据第一段接口计算出的workspaceSize申请device内存 |
| 117 | - void* workspaceAddr = nullptr; | 122 | + void* workspaceAddr = nullptr; |
| 118 | - if (workspaceSize > 0) { | 123 | + if (workspaceSize > 0) { |
| 119 | - ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | 124 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); |
| 120 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | 125 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); |
| 121 | - } | 126 | + } |
| 122 | - // 调用aclnnSeluBackward第二段接口 | 127 | + // 调用aclnnSeluBackward第二段接口 |
| 123 | - ret = aclnnSeluBackward(workspaceAddr, workspaceSize, executor, stream); | 128 | + ret = aclnnSeluBackward(workspaceAddr, workspaceSize, executor, stream); |
| 124 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSeluBackward failed. ERROR: %d\n", ret); return ret); | 129 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSeluBackward failed. ERROR: %d\n", ret); return ret); |
| 125 | - // 4. (固定写法)同步等待任务执行结束 | 130 | + // 4. (固定写法)同步等待任务执行结束 |
| 126 | - ret = aclrtSynchronizeStream(stream); | 131 | + ret = aclrtSynchronizeStream(stream); |
| 127 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | 132 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); |
| 128 | - // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | 133 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 |
| 129 | - auto size = GetShapeSize(gradInputShape); | 134 | + auto size = GetShapeSize(gradInputShape); |
| 130 | - std::vector<float> resultData(size, 0); | 135 | + std::vector<float> resultData(size, 0); |
| 131 | - ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr, size * sizeof(float), | 136 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr, |
| 132 | - ACL_MEMCPY_DEVICE_TO_HOST); | 137 | + size * sizeof(float), ACL_MEMCPY_DEVICE_TO_HOST); |
| 133 | - CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | 138 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); |
| 134 | - for (int64_t i = 0; i < size; i++) { | 139 | + for (int64_t i = 0; i < size; i++) { |
| 135 | - LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | 140 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); |
| 136 | - } | 141 | + } |
| 137 | - // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | 142 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 |
| 138 | - aclDestroyTensor(gradOutput); | 143 | + aclDestroyTensor(gradOutput); |
| 139 | - aclDestroyTensor(self); | 144 | + aclDestroyTensor(self); |
| 140 | - aclDestroyTensor(gradInput); | 145 | + aclDestroyTensor(gradInput); |
| 141 | 146 | ||
| 142 | - // 7. 释放device资源,需要根据具体API的接口定义修改 | 147 | + // 7. 释放device资源,需要根据具体API的接口定义修改 |
| 143 | - aclrtFree(selfDeviceAddr); | 148 | + aclrtFree(selfDeviceAddr); |
| 144 | - aclrtFree(gradOutputDeviceAddr); | 149 | + aclrtFree(gradOutputDeviceAddr); |
| 145 | - aclrtFree(gradInputDeviceAddr); | 150 | + aclrtFree(gradInputDeviceAddr); |
| 146 | - if (workspaceSize > 0) { | 151 | + if (workspaceSize > 0) { |
| 147 | - aclrtFree(workspaceAddr); | 152 | + aclrtFree(workspaceAddr); |
| 148 | - } | 153 | + } |
| 149 | - aclrtDestroyStream(stream); | 154 | + aclrtDestroyStream(stream); |
| 150 | - aclrtResetDevice(deviceId); | 155 | + aclrtResetDevice(deviceId); |
| 151 | - aclFinalize(); | 156 | + aclFinalize(); |
| 152 | - return 0; | 157 | + return 0; |
| 153 | -} | 158 | +} |
| @@ -1,12 +1,11 @@ | |||
| 1 | /** | 1 | /** |
| 2 | - * This program is free software, you can redistribute it and/or modify. | ||
| 3 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. | 2 | * Copyright (c) 2025 Huawei Technologies Co., Ltd. |
| 4 | - * This file is a part of the CANN Open Software. | 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of |
| 5 | - * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). |
| 6 | * Please refer to the License for details. You may not use this file except in compliance with the License. | 5 | * Please refer to the License for details. You may not use this file except in compliance with the License. |
| 7 | - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, |
| 8 | - * BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. See LICENSE in the root of | 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. |
| 9 | - * the software repository for the full text of the License. | 8 | + * See LICENSE in the root of the software repository for the full text of the License. |
| 10 | */ | 9 | */ |
| 11 | 10 | ||
| 12 | /*! | 11 | /*! |
| @@ -37,12 +36,12 @@ __aicore__ void AddcMulScalarAdapterForFloat(const LocalTensor<T>& tensorLocal1, | |||
| 37 | template <typename T> | 36 | template <typename T> |
| 38 | __aicore__ void AddcMulScalarAdapterForInt(const LocalTensor<T>& tensorLocal1, const LocalTensor<T>& tensorLocal2, | 37 | __aicore__ void AddcMulScalarAdapterForInt(const LocalTensor<T>& tensorLocal1, const LocalTensor<T>& tensorLocal2, |
| 39 | const LocalTensor<T>& tensorLocal3, const LocalTensor<float>& float32Tensor, | 38 | const LocalTensor<T>& tensorLocal3, const LocalTensor<float>& float32Tensor, |
| 40 | - const float scalarValue, const uint32_t maxCastDataCount, | 39 | + const int32_t scalarValue, const uint32_t maxCastDataCount, |
| 41 | const int64_t dataCount) | 40 | const int64_t dataCount) |
| 42 | { | 41 | { |
| 43 | Mul(tensorLocal2, tensorLocal2, tensorLocal3, dataCount); | 42 | Mul(tensorLocal2, tensorLocal2, tensorLocal3, dataCount); |
| 44 | PipeBarrier<PIPE_V>(); | 43 | PipeBarrier<PIPE_V>(); |
| 45 | - Muls(tensorLocal2, tensorLocal2, (int32_t)scalarValue, dataCount); | 44 | + Muls(tensorLocal2, tensorLocal2, scalarValue, dataCount); |
| 46 | PipeBarrier<PIPE_V>(); | 45 | PipeBarrier<PIPE_V>(); |
| 47 | Add(tensorLocal1, tensorLocal1, tensorLocal2, dataCount); | 46 | Add(tensorLocal1, tensorLocal1, tensorLocal2, dataCount); |
| 48 | } | 47 | } |
| @@ -38,12 +38,12 @@ __aicore__ void AddcMulScalarListAdapterForFloat(const LocalTensor<T>& tensor1Lo | |||
| 38 | template <typename T> | 38 | template <typename T> |
| 39 | __aicore__ void AddcMulScalarListAdapterForInt(const LocalTensor<T>& tensor1Local, const LocalTensor<T>& tensor2Local, | 39 | __aicore__ void AddcMulScalarListAdapterForInt(const LocalTensor<T>& tensor1Local, const LocalTensor<T>& tensor2Local, |
| 40 | const LocalTensor<T>& tensor3Local, | 40 | const LocalTensor<T>& tensor3Local, |
| 41 | - const LocalTensor<float>& float32Tensor, const float scalarValue, | 41 | + const LocalTensor<float>& float32Tensor, const int32_t scalarValue, |
| 42 | const uint32_t maxCastDataCount, const int64_t dataCount) | 42 | const uint32_t maxCastDataCount, const int64_t dataCount) |
| 43 | { | 43 | { |
| 44 | Mul(tensor2Local, tensor2Local, tensor3Local, dataCount); | 44 | Mul(tensor2Local, tensor2Local, tensor3Local, dataCount); |
| 45 | PipeBarrier<PIPE_V>(); | 45 | PipeBarrier<PIPE_V>(); |
| 46 | - Muls(tensor2Local, tensor2Local, (int32_t)scalarValue, dataCount); | 46 | + Muls(tensor2Local, tensor2Local, scalarValue, dataCount); |
| 47 | PipeBarrier<PIPE_V>(); | 47 | PipeBarrier<PIPE_V>(); |
| 48 | Add(tensor1Local, tensor1Local, tensor2Local, dataCount); | 48 | Add(tensor1Local, tensor1Local, tensor2Local, dataCount); |
| 49 | } | 49 | } |
| @@ -121,4 +121,4 @@ extern "C" __global__ __aicore__ void foreach_addcmul_scalar_list(GM_ADDR tensor | |||
| 121 | 121 | ||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | -} | 124 | +} |
| @@ -44,7 +44,7 @@ protected: | |||
| 44 | GlobalTensor<T> inScalarGM; | 44 | GlobalTensor<T> inScalarGM; |
| 45 | GM_ADDR inTensorsPtr_2 = nullptr; | 45 | GM_ADDR inTensorsPtr_2 = nullptr; |
| 46 | GM_ADDR inTensorsPtr_3 = nullptr; | 46 | GM_ADDR inTensorsPtr_3 = nullptr; |
| 47 | - float scalarValue = 0.0; | 47 | + ScalarT<T> scalarValue = 0; |
| 48 | 48 | ||
| 49 | private: | 49 | private: |
| 50 | __aicore__ inline void Compute(uint32_t index, int64_t dataCount, LocalTensor<float>& float32Tensor, | 50 | __aicore__ inline void Compute(uint32_t index, int64_t dataCount, LocalTensor<float>& float32Tensor, |
| @@ -104,7 +104,8 @@ private: | |||
| 104 | 104 | ||
| 105 | __aicore__ inline void valueScalar(const half& bVal) { scalarValue = (float)bVal; } | 105 | __aicore__ inline void valueScalar(const half& bVal) { scalarValue = (float)bVal; } |
| 106 | 106 | ||
| 107 | - __aicore__ inline void valueScalar(const int& bVal) { scalarValue = static_cast<float>(bVal); } | 107 | + // int32 标量按原始 int32_t 存储,避免 float() 强转丢精度 (issue #4519) |
| 108 | + __aicore__ inline void valueScalar(const int& bVal) { scalarValue = static_cast<int32_t>(bVal); } | ||
| 108 | 109 | ||
| 109 | __aicore__ inline void valueScalar(const float& bVal) { scalarValue = bVal; } | 110 | __aicore__ inline void valueScalar(const float& bVal) { scalarValue = bVal; } |
| 110 | 111 | ||
| @@ -206,4 +207,4 @@ __aicore__ inline void ForeachOneScalarListQuaternaryImplictOutput<T, op, buffer | |||
| 206 | } // namespace OpKernel | 207 | } // namespace OpKernel |
| 207 | } // namespace Common | 208 | } // namespace Common |
| 208 | 209 | ||
| 209 | -#endif // KERNEL_FOREACH_ONE_SCALAR_LIST_QUATERNARY_IMPLICT_OUTPUT_H | 210 | +#endif // KERNEL_FOREACH_ONE_SCALAR_LIST_QUATERNARY_IMPLICT_OUTPUT_H |
| @@ -22,15 +22,33 @@ namespace Common { | |||
| 22 | namespace OpKernel { | 22 | namespace OpKernel { |
| 23 | using namespace AscendC; | 23 | using namespace AscendC; |
| 24 | 24 | ||
| 25 | +// 标量存储类型萃取:int32 用原始 int32_t 存储避免 float() 强转丢精度 | ||
| 26 | +// half/bf16/float 仍用 float(计算本就提升到 float)。 | ||
| 27 | +template <typename T> | ||
| 28 | +struct ScalarStorageType { | ||
| 29 | + using type = float; | ||
| 30 | +}; | ||
| 31 | +template <> | ||
| 32 | +struct ScalarStorageType<int32_t> { | ||
| 33 | + using type = int32_t; | ||
| 34 | +}; | ||
| 35 | +// 注意:不再单独特化 ScalarStorageType<int>。 | ||
| 36 | +// 在该平台 int32_t 即为 int 的 typedef,同时特化二者会导致 "redefinition" 编译错误。 | ||
| 37 | +// int32_t 特化已覆盖 int。 | ||
| 38 | + | ||
| 39 | +template <typename T> | ||
| 40 | +using ScalarT = typename ScalarStorageType<T>::type; | ||
| 41 | + | ||
| 25 | template <typename T> | 42 | template <typename T> |
| 26 | using OneScalarQuaternaryImplictOutputOp = void(const LocalTensor<T>&, const LocalTensor<T>&, const LocalTensor<T>&, | 43 | using OneScalarQuaternaryImplictOutputOp = void(const LocalTensor<T>&, const LocalTensor<T>&, const LocalTensor<T>&, |
| 27 | - const LocalTensor<float>&, const float, const uint32_t, const int64_t); | 44 | + const LocalTensor<float>&, const ScalarT<T>, const uint32_t, |
| 45 | + const int64_t); | ||
| 28 | 46 | ||
| 29 | template <typename T, OneScalarQuaternaryImplictOutputOp<T>* op> | 47 | template <typename T, OneScalarQuaternaryImplictOutputOp<T>* op> |
| 30 | class InnerComputer { | 48 | class InnerComputer { |
| 31 | public: | 49 | public: |
| 32 | __aicore__ inline void Compute(LocalTensor<T>& inLocal_1, LocalTensor<T>& inLocal_2, LocalTensor<T>& inLocal_3, | 50 | __aicore__ inline void Compute(LocalTensor<T>& inLocal_1, LocalTensor<T>& inLocal_2, LocalTensor<T>& inLocal_3, |
| 33 | - LocalTensor<float>& float32Tensor, float scalarVal, uint32_t maxCastDataCount, | 51 | + LocalTensor<float>& float32Tensor, ScalarT<T> scalarVal, uint32_t maxCastDataCount, |
| 34 | int64_t dataCount) | 52 | int64_t dataCount) |
| 35 | { | 53 | { |
| 36 | PipeBarrier<PIPE_V>(); | 54 | PipeBarrier<PIPE_V>(); |
| @@ -61,7 +79,7 @@ protected: | |||
| 61 | GlobalTensor<DTYPE_SCALAR> inScalarGM; | 79 | GlobalTensor<DTYPE_SCALAR> inScalarGM; |
| 62 | GM_ADDR inTensorsPtr_2 = nullptr; | 80 | GM_ADDR inTensorsPtr_2 = nullptr; |
| 63 | GM_ADDR inTensorsPtr_3 = nullptr; | 81 | GM_ADDR inTensorsPtr_3 = nullptr; |
| 64 | - float scalarVal = 0.0; | 82 | + ScalarT<T> scalarVal = 0; |
| 65 | 83 | ||
| 66 | private: | 84 | private: |
| 67 | __aicore__ inline void Compute(uint32_t index, int64_t dataCount, LocalTensor<float>& float32Tensor, | 85 | __aicore__ inline void Compute(uint32_t index, int64_t dataCount, LocalTensor<float>& float32Tensor, |
| @@ -132,7 +150,8 @@ __aicore__ inline void ForeachOneScalarQuaternaryImplictOutput<T, op, bufferNum, | |||
| 132 | inTensorsPtr_3 = x3; | 150 | inTensorsPtr_3 = x3; |
| 133 | Base::outTensorsPtr = y; | 151 | Base::outTensorsPtr = y; |
| 134 | inScalarGM.SetGlobalBuffer((__gm__ DTYPE_SCALAR*)scalar, 1); | 152 | inScalarGM.SetGlobalBuffer((__gm__ DTYPE_SCALAR*)scalar, 1); |
| 135 | - scalarVal = float(inScalarGM.GetValue(0)); | 153 | + // int32 按 int32_t 存储避免 float() 强转丢精度;half/bf16/float 经 float 中转 |
| 154 | + scalarVal = ScalarT<T>(inScalarGM.GetValue(0)); | ||
| 136 | 155 | ||
| 137 | if (std::is_same_v<T, bfloat16_t> || std::is_same_v<T, half>) { | 156 | if (std::is_same_v<T, bfloat16_t> || std::is_same_v<T, half>) { |
| 138 | Base::Base::pipe.InitBuffer(Base::float32Queue, 1, Base::Base::inputsTensorUbSize * paramsCount); | 157 | Base::Base::pipe.InitBuffer(Base::float32Queue, 1, Base::Base::inputsTensorUbSize * paramsCount); |
| @@ -214,4 +233,4 @@ __aicore__ inline void ForeachOneScalarQuaternaryImplictOutput<T, op, bufferNum, | |||
| 214 | } // namespace OpKernel | 233 | } // namespace OpKernel |
| 215 | } // namespace Common | 234 | } // namespace Common |
| 216 | 235 | ||
| 217 | -#endif // KERNEL_FOREACH_ONE_SCALAR_QUATERNARY_IMPLICT_OUTPUT_H | 236 | +#endif // KERNEL_FOREACH_ONE_SCALAR_QUATERNARY_IMPLICT_OUTPUT_H |