已合并
修复real_div不同soc支持逻辑 #3880
jiangjiawei创建于 7月7日
修复real_div不同soc支持逻辑 #3880
已合并
共 1 个文件变更+124-119
| @@ -27,155 +27,160 @@ OP_TYPE_REGISTER(RealDiv); | |||
| 27 | static const int MODE_REAL_DIV = 0; | 27 | static const int MODE_REAL_DIV = 0; |
| 28 | static const int MODE_TRUNC_DIV = 1; | 28 | static const int MODE_TRUNC_DIV = 1; |
| 29 | 29 | ||
| 30 | static const std::initializer_list<op::DataType> AICORE_DTYPE_SUPPORT_LIST = {op::DataType::DT_FLOAT, | 30 | static const std::initializer_list<op::DataType> AICORE_DTYPE_SUPPORT_LIST = { |
| 31 | op::DataType::DT_FLOAT16, op::DataType::DT_BF16, op::DataType::DT_BOOL}; | 31 | op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16, op::DataType::DT_BOOL}; |
| 32 | 32 | ||
| 33 | static const std::initializer_list<op::DataType> ASCEND910B_AICORE_DTYPE_SUPPORT_LIST = {op::DataType::DT_FLOAT, | 33 | static const std::initializer_list<op::DataType> ASCEND910B_AICORE_DTYPE_SUPPORT_LIST = { |
| 34 | op::DataType::DT_FLOAT16, op::DataType::DT_BF16, op::DataType::DT_BOOL, op::DataType::DT_INT32}; | 34 | op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16, op::DataType::DT_BOOL, |
| 35 | op::DataType::DT_INT32}; | ||
| 35 | 36 | ||
| 36 | static const std::initializer_list<op::DataType> ASCEND610LITE_DTYPE_SUPPORT_LIST = {op::DataType::DT_FLOAT, | 37 | static const std::initializer_list<op::DataType> ASCEND610LITE_DTYPE_SUPPORT_LIST = { |
| 37 | op::DataType::DT_FLOAT16, op::DataType::DT_INT8, op::DataType::DT_UINT8, op::DataType::DT_INT32}; | 38 | op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_INT8, op::DataType::DT_UINT8, |
| 39 | op::DataType::DT_INT32}; | ||
| 38 | 40 | ||
| 39 | static const std::initializer_list<op::DataType> ASCEND950_DTYPE_SUPPORT_LIST = {op::DataType::DT_FLOAT, | 41 | static const std::initializer_list<op::DataType> ASCEND950_DTYPE_SUPPORT_LIST = { |
| 40 | op::DataType::DT_FLOAT16, op::DataType::DT_BF16, op::DataType::DT_BOOL, op::DataType::DT_INT32, | 42 | op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16, |
| 41 | op::DataType::DT_INT64}; | 43 | op::DataType::DT_BOOL, op::DataType::DT_INT32, op::DataType::DT_INT64}; |
| 42 | |||
| 43 | // 判断当前芯片是否支持int32精度的RealDiv kernel(仅910B/910C支持) | ||
| 44 | static bool IsInt32PrecisionSupported() { | ||
| 45 | auto socVersion = GetCurrentPlatformInfo().GetSocVersion(); | ||
| 46 | return socVersion == SocVersion::ASCEND910B || socVersion == SocVersion::ASCEND910_93; | ||
| 47 | } | ||
| 48 | 44 | ||
| 49 | // 根据芯片类型、dtype判断算子是否支持走aicore | 45 | // 根据芯片类型、dtype判断算子是否支持走aicore |
| 50 | static bool IsAiCoreSupport(const aclTensor* self) { | 46 | static bool IsAiCoreSupport(const aclTensor* self) |
| 51 | // 根据dtype返回决定是否走aicore:true则走aicore | 47 | { |
| 52 | auto socVersion = GetCurrentPlatformInfo().GetSocVersion(); | 48 | // 根据dtype返回决定是否走aicore:true则走aicore |
| 53 | if (IsRegBase()) { | 49 | auto socVersion = GetCurrentPlatformInfo().GetSocVersion(); |
| 54 | return CheckType(self->GetDataType(), ASCEND950_DTYPE_SUPPORT_LIST); | 50 | if (IsRegBase()) { |
| 55 | } | 51 | return CheckType(self->GetDataType(), ASCEND950_DTYPE_SUPPORT_LIST); |
| 56 | if (socVersion == SocVersion::ASCEND610LITE) { | 52 | } |
| 57 | return CheckType(self->GetDataType(), ASCEND610LITE_DTYPE_SUPPORT_LIST); | 53 | if (socVersion == SocVersion::ASCEND610LITE) { |
| 58 | } | 54 | return CheckType(self->GetDataType(), ASCEND610LITE_DTYPE_SUPPORT_LIST); |
| 59 | if (socVersion == SocVersion::ASCEND910B || socVersion == SocVersion::ASCEND910_93) { | 55 | } |
| 60 | return CheckType(self->GetDataType(), ASCEND910B_AICORE_DTYPE_SUPPORT_LIST); | 56 | if (socVersion == SocVersion::ASCEND910B || socVersion == SocVersion::ASCEND910_93) { |
| 61 | } | 57 | return CheckType(self->GetDataType(), ASCEND910B_AICORE_DTYPE_SUPPORT_LIST); |
| 62 | return CheckType(self->GetDataType(), AICORE_DTYPE_SUPPORT_LIST); | 58 | } |
| 59 | return CheckType(self->GetDataType(), AICORE_DTYPE_SUPPORT_LIST); | ||
| 63 | } | 60 | } |
| 64 | 61 | ||
| 65 | bool IsRealDivSupportNonContiguous(const aclTensor* self) { | 62 | static bool is910BInt32Supported(const aclTensor* self, const aclTensor* other) |
| 66 | bool isSupportNonContiguous = IsRegBase(); | 63 | { |
| 67 | return isSupportNonContiguous && IsAiCoreSupport(self); | 64 | auto socVersion = GetCurrentPlatformInfo().GetSocVersion(); |
| 65 | return (socVersion == SocVersion::ASCEND910B || socVersion == SocVersion::ASCEND910_93) && | ||
| 66 | self->GetDataType() == op::DataType::DT_INT32 && other->GetDataType() == op::DataType::DT_INT32; | ||
| 67 | } | ||
| 68 | |||
| 69 | bool IsRealDivSupportNonContiguous(const aclTensor* self) | ||
| 70 | { | ||
| 71 | bool isSupportNonContiguous = IsRegBase(); | ||
| 72 | return isSupportNonContiguous && IsAiCoreSupport(self); | ||
| 68 | } | 73 | } |
| 69 | 74 | ||
| 70 | // AICORE算子kernel | 75 | // AICORE算子kernel |
| 71 | static const aclTensor* RealDivAiCore(const aclTensor* self, const aclTensor* other, aclTensor* divOut, | 76 | static const aclTensor* RealDivAiCore(const aclTensor* self, const aclTensor* other, aclTensor* divOut, |
| 72 | aclOpExecutor* executor) { | 77 | aclOpExecutor* executor) |
| 73 | L0_DFX(RealDivAiCore, self, other, divOut); | 78 | { |
| 74 | // 使用框架宏ADD_TO_LAUNCHER_LIST_AICORE,将AiCore RealDiv算子加入任务队列 | 79 | L0_DFX(RealDivAiCore, self, other, divOut); |
| 75 | // RealDiv是算子的OpType,self、other是算子的输入,divOut是算子的输出 | 80 | // 使用框架宏ADD_TO_LAUNCHER_LIST_AICORE,将AiCore RealDiv算子加入任务队列 |
| 76 | ADD_TO_LAUNCHER_LIST_AICORE(RealDiv, OP_INPUT(self, other), OP_OUTPUT(divOut)); | 81 | // RealDiv是算子的OpType,self、other是算子的输入,divOut是算子的输出 |
| 77 | return divOut; | 82 | ADD_TO_LAUNCHER_LIST_AICORE(RealDiv, OP_INPUT(self, other), OP_OUTPUT(divOut)); |
| 83 | return divOut; | ||
| 78 | } | 84 | } |
| 79 | 85 | ||
| 80 | // AICPU算子kernel | 86 | // AICPU算子kernel |
| 81 | static const aclTensor *RealDivAiCpu(const aclTensor *self, const aclTensor *other, aclTensor *divOut, | 87 | static const aclTensor* RealDivAiCpu(const aclTensor* self, const aclTensor* other, aclTensor* divOut, |
| 82 | aclOpExecutor *executor) { | 88 | aclOpExecutor* executor) |
| 83 | L0_DFX(RealDivAiCpu); | 89 | { |
| 84 | static internal::AicpuTaskSpace space("RealDiv"); | 90 | L0_DFX(RealDivAiCpu); |
| 85 | auto ret = ADD_TO_LAUNCHER_LIST_AICPU(RealDiv, OP_ATTR_NAMES(), OP_INPUT(self, other), OP_OUTPUT(divOut)); | 91 | static internal::AicpuTaskSpace space("RealDiv"); |
| 86 | CHECK_RET(ret == ACLNN_SUCCESS, nullptr); | 92 | auto ret = ADD_TO_LAUNCHER_LIST_AICPU(RealDiv, OP_ATTR_NAMES(), OP_INPUT(self, other), OP_OUTPUT(divOut)); |
| 87 | return divOut; | 93 | CHECK_RET(ret == ACLNN_SUCCESS, nullptr); |
| 94 | return divOut; | ||
| 88 | } | 95 | } |
| 89 | 96 | ||
| 90 | const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, aclOpExecutor* executor) { | 97 | const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, aclOpExecutor* executor) |
| 91 | op::Shape broadcastShape; | 98 | { |
| 92 | if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) { | 99 | op::Shape broadcastShape; |
| 93 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(), | 100 | if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) { |
| 94 | op::ToString(other->GetViewShape()).GetString()); | 101 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(), |
| 95 | return nullptr; | 102 | op::ToString(other->GetViewShape()).GetString()); |
| 96 | } | 103 | return nullptr; |
| 104 | } | ||
| 97 | 105 | ||
| 98 | aclTensor* divOut; | 106 | aclTensor* divOut; |
| 99 | if (self->GetDataType() == op::DataType::DT_BOOL || | 107 | if (self->GetDataType() == op::DataType::DT_BOOL || is910BInt32Supported(self, other)) { |
| 100 | (self->GetDataType() == op::DataType::DT_INT32 && other->GetDataType() == op::DataType::DT_INT32 && | 108 | divOut = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT); |
| 101 | IsInt32PrecisionSupported())) { | 109 | } else { |
| 102 | divOut = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT); | 110 | divOut = executor->AllocTensor(broadcastShape, self->GetDataType()); |
| 103 | } else { | 111 | } |
| 104 | divOut = executor->AllocTensor(broadcastShape, self->GetDataType()); | ||
| 105 | } | ||
| 106 | 112 | ||
| 107 | if (IsAiCoreSupport(self)) { | 113 | if (IsAiCoreSupport(self)) { |
| 108 | return RealDivAiCore(self, other, divOut, executor); | 114 | return RealDivAiCore(self, other, divOut, executor); |
| 109 | } else { | 115 | } else { |
| 110 | return RealDivAiCpu(self, other, divOut, executor); | 116 | return RealDivAiCpu(self, other, divOut, executor); |
| 111 | } | 117 | } |
| 112 | return divOut; | 118 | return divOut; |
| 113 | } | 119 | } |
| 114 | 120 | ||
| 115 | const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, const int mode, aclOpExecutor* executor) { | 121 | const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, const int mode, aclOpExecutor* executor) |
| 116 | op::Shape broadcastShape; | 122 | { |
| 117 | if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) { | 123 | op::Shape broadcastShape; |
| 118 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(), | 124 | if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) { |
| 119 | op::ToString(other->GetViewShape()).GetString()); | 125 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(), |
| 120 | return nullptr; | 126 | op::ToString(other->GetViewShape()).GetString()); |
| 121 | } | 127 | return nullptr; |
| 128 | } | ||
| 122 | 129 | ||
| 123 | bool isOutDtypeFloat = false; | 130 | bool isOutDtypeFloat = false; |
| 124 | if (mode == MODE_REAL_DIV && | 131 | if (mode == MODE_REAL_DIV && |
| 125 | (self->GetDataType() == op::DataType::DT_BOOL || | 132 | (self->GetDataType() == op::DataType::DT_BOOL || self->GetDataType() == op::DataType::DT_INT32)) { |
| 126 | (self->GetDataType() == op::DataType::DT_INT32 && other->GetDataType() == op::DataType::DT_INT32 && | 133 | isOutDtypeFloat = true; |
| 127 | IsInt32PrecisionSupported()))) { | 134 | } |
| 128 | isOutDtypeFloat = true; | ||
| 129 | } | ||
| 130 | 135 | ||
| 131 | if (mode == MODE_TRUNC_DIV && self->GetDataType() == op::DataType::DT_BOOL) { | 136 | if (mode == MODE_TRUNC_DIV && self->GetDataType() == op::DataType::DT_BOOL) { |
| 132 | isOutDtypeFloat = true; | 137 | isOutDtypeFloat = true; |
| 133 | } | 138 | } |
| 134 | 139 | ||
| 135 | aclTensor* divOut; | 140 | aclTensor* divOut; |
| 136 | if (isOutDtypeFloat) { | 141 | if (isOutDtypeFloat) { |
| 137 | divOut = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT); | 142 | divOut = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT); |
| 138 | } else { | 143 | } else { |
| 139 | divOut = executor->AllocTensor(broadcastShape, self->GetDataType()); | 144 | divOut = executor->AllocTensor(broadcastShape, self->GetDataType()); |
| 140 | } | 145 | } |
| 141 | 146 | ||
| 142 | if (IsAiCoreSupport(self)) { | 147 | if (IsAiCoreSupport(self)) { |
| 143 | return RealDivAiCore(self, other, divOut, executor); | 148 | return RealDivAiCore(self, other, divOut, executor); |
| 144 | } else { | 149 | } else { |
| 145 | return RealDivAiCpu(self, other, divOut, executor); | 150 | return RealDivAiCpu(self, other, divOut, executor); |
| 146 | } | 151 | } |
| 147 | return divOut; | 152 | return divOut; |
| 148 | } | 153 | } |
| 149 | 154 | ||
| 150 | static const aclTensor* RealDivKernel(const aclTensor* self, const aclTensor* other, aclTensor* divOut, | 155 | static const aclTensor* RealDivKernel(const aclTensor* self, const aclTensor* other, aclTensor* divOut, |
| 151 | aclOpExecutor* executor) { | 156 | aclOpExecutor* executor) |
| 152 | if (IsAiCoreSupport(self)) { | 157 | { |
| 153 | return RealDivAiCore(self, other, divOut, executor); | 158 | if (IsAiCoreSupport(self)) { |
| 154 | } else { | 159 | return RealDivAiCore(self, other, divOut, executor); |
| 155 | return RealDivAiCpu(self, other, divOut, executor); | 160 | } else { |
| 156 | } | 161 | return RealDivAiCpu(self, other, divOut, executor); |
| 162 | } | ||
| 157 | } | 163 | } |
| 158 | 164 | ||
| 159 | const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, bool isScalar, aclOpExecutor* executor) { | 165 | const aclTensor* RealDiv(const aclTensor* self, const aclTensor* other, bool isScalar, aclOpExecutor* executor) |
| 160 | op::Shape broadcastShape; | 166 | { |
| 161 | if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) { | 167 | op::Shape broadcastShape; |
| 162 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(), | 168 | if (!BroadcastInferShape(self->GetViewShape(), other->GetViewShape(), broadcastShape)) { |
| 163 | op::ToString(other->GetViewShape()).GetString()); | 169 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Broadcast %s and %s failed.", op::ToString(self->GetViewShape()).GetString(), |
| 164 | return nullptr; | 170 | op::ToString(other->GetViewShape()).GetString()); |
| 165 | } | 171 | return nullptr; |
| 172 | } | ||
| 166 | 173 | ||
| 167 | aclTensor* divOut; | 174 | aclTensor* divOut; |
| 168 | bool isInt32Precision = self->GetDataType() == op::DataType::DT_INT32 && | ||
| 169 | other->GetDataType() == op::DataType::DT_INT32 && IsInt32PrecisionSupported(); | ||
| 170 | if ((isScalar && self->GetDataType() != op::DataType::DT_BOOL && !isInt32Precision) || | ||
| 171 | ((!isScalar) && self->GetDataType() == other->GetDataType() && self->GetDataType() != op::DataType::DT_BOOL && | ||
| 172 | !isInt32Precision)) { | ||
| 173 | divOut = executor->AllocTensor(broadcastShape, self->GetDataType()); | ||
| 174 | } else { | ||
| 175 | divOut = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT); | ||
| 176 | } | ||
| 177 | 175 | ||
| 178 | return RealDivKernel(self, other, divOut, executor); | 176 | if ((isScalar && self->GetDataType() != op::DataType::DT_BOOL) || |
| 177 | ((!isScalar) && self->GetDataType() == other->GetDataType() && self->GetDataType() != op::DataType::DT_BOOL)) { | ||
| 178 | divOut = executor->AllocTensor(broadcastShape, self->GetDataType()); | ||
| 179 | } else { | ||
| 180 | divOut = executor->AllocTensor(broadcastShape, op::DataType::DT_FLOAT); | ||
| 181 | } | ||
| 182 | |||
| 183 | return RealDivKernel(self, other, divOut, executor); | ||
| 179 | } | 184 | } |
| 180 | 185 | ||
| 181 | } // namespace l0op | 186 | } // namespace l0op |
🟠 High Priority
变更行: 第 133–134 行的 MODE_REAL_DIV 条件。
问题: 旧代码为: if (mode == MODE_REAL_DIV && (DT_BOOL || (DT_INT32 && DT_INT32 && IsInt32PrecisionSupported())))
IsInt32PrecisionSupported()仅在 910B/910_93 上返回 true。因此旧代码仅在 910B 上对 INT32+INT32 输出 DT_FLOAT。新代码为: if (mode == MODE_REAL_DIV && (DT_BOOL || DT_INT32)) 无条件对任何芯片上的
self = DT_INT32输出 DT_FLOAT,不再检查芯片是否支持 INT32 精度,也不再要求other也是 INT32。受影响芯片及路径:
CompatibleInferDivDtype直接以 INT32 输入调用此 API,AICORE_DTYPE_SUPPORT_LIST 不含 INT32 →IsAiCoreSupport返回 false → 走 AICPU 路径(RealDivAiCpu)。AICPU kernel 收到 INT32 输入 + DT_FLOAT 输出缓冲区的行为需确认。额外问题: 条件中还移除了
other->GetDataType() == DT_INT32检查。如果 API 被外部以(INT32, FLOAT16)调用 MODE_REAL_DIV,会错误输出 DT_FLOAT(旧代码输出 self 的 dtype = INT32)。