已合并
aclnnReplicationPad1dBackward在大paddings场景路由aicpu配置(9.1.0) #3871
sunhao_hw创建于 7月7日
aclnnReplicationPad1dBackward在大paddings场景路由aicpu配置(9.1.0) #3871
已合并
sunhao_hw创建于 7月7日
1 个文件变更+57-49
Mconversion/pad_v3_grad_replicate/op_host/op_api/aclnn_replication_pad1d_backward.cpp+57-49
@@ -16,6 +16,8 @@
16#include "aclnn_kernels/common/op_error_check.h"16#include "aclnn_kernels/common/op_error_check.h"
17#include "aclnn_kernels/cast.h"17#include "aclnn_kernels/cast.h"
18#include "opdev/op_dfx.h"18#include "opdev/op_dfx.h"
19#include "opdev/platform.h"
20#include "op_api/aclnn_check.h"
19 21 
20using namespace op;22using namespace op;
21#ifdef __cplusplus23#ifdef __cplusplus
@@ -23,13 +25,14 @@ extern "C" {
23#endif25#endif
24 26 
25static const string REPLICATION_MODE = "edge";27static const string REPLICATION_MODE = "edge";
28static const int64_t PADDING_FP32_MAX = 7200;
26// 根据API定义,需要列出所能支持的所有dtype29// 根据API定义,需要列出所能支持的所有dtype
27static const std::initializer_list<op::DataType> dtypeSupportList = {30static const std::initializer_list<op::DataType> dtypeSupportList = {
28 op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16,31 op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16,
29 op::DataType::DT_DOUBLE, op::DataType::DT_COMPLEX64, op::DataType::DT_COMPLEX128};32 op::DataType::DT_DOUBLE, op::DataType::DT_COMPLEX64, op::DataType::DT_COMPLEX128};
30 33 
31inline static bool CheckNotNull(const aclTensor *gradOutput, const aclTensor *self, const aclIntArray *padding,34inline static bool CheckNotNull(const aclTensor* gradOutput, const aclTensor* self, const aclIntArray* padding,
32 const aclTensor *gradInput)35 const aclTensor* gradInput)
33{36{
34 OP_CHECK_NULL(gradOutput, return false);37 OP_CHECK_NULL(gradOutput, return false);
35 OP_CHECK_NULL(self, return false);38 OP_CHECK_NULL(self, return false);
@@ -38,7 +41,7 @@ inline static bool CheckNotNull(const aclTensor *gradOutput, const aclTensor *se
38 return true;41 return true;
39}42}
40 43 
41inline static bool CheckDtypeValid(const aclTensor *gradOutput, const aclTensor *self, const aclTensor *gradInput)44inline static bool CheckDtypeValid(const aclTensor* gradOutput, const aclTensor* self, const aclTensor* gradInput)
42{45{
43 // 检查gradOutput的数据类型是否在支持列表内46 // 检查gradOutput的数据类型是否在支持列表内
44 OP_CHECK_DTYPE_NOT_SUPPORT(gradOutput, dtypeSupportList, return false);47 OP_CHECK_DTYPE_NOT_SUPPORT(gradOutput, dtypeSupportList, return false);
@@ -55,7 +58,7 @@ inline static bool CheckDtypeValid(const aclTensor *gradOutput, const aclTensor
55 return true;58 return true;
56}59}
57 60 
58inline static bool CheckFormat(const aclTensor *gradOutput, const aclTensor *self, const aclTensor *gradInput)61inline static bool CheckFormat(const aclTensor* gradOutput, const aclTensor* self, const aclTensor* gradInput)
59{62{
60 // 如果输入格式是私有格式,记录日志,直接报错63 // 如果输入格式是私有格式,记录日志,直接报错
61 if (op::IsPrivateFormat(gradOutput->GetStorageFormat()) || op::IsPrivateFormat(self->GetStorageFormat()) ||64 if (op::IsPrivateFormat(gradOutput->GetStorageFormat()) || op::IsPrivateFormat(self->GetStorageFormat()) ||
@@ -64,8 +67,9 @@ inline static bool CheckFormat(const aclTensor *gradOutput, const aclTensor *sel
64 return false;67 return false;
65 }68 }
66 69 
67 OP_CHECK(gradOutput->GetViewFormat() == self->GetViewFormat() &&70 OP_CHECK(
68 gradOutput->GetViewFormat() == gradInput->GetViewFormat(),71 gradOutput->GetViewFormat() == self->GetViewFormat() &&
72 gradOutput->GetViewFormat() == gradInput->GetViewFormat(),
69 OP_LOGE(ACLNN_ERR_PARAM_INVALID,73 OP_LOGE(ACLNN_ERR_PARAM_INVALID,
70 "Format of input and output should be equal, gradOutput [%s], self [%s], gradInput [%s].",74 "Format of input and output should be equal, gradOutput [%s], self [%s], gradInput [%s].",
71 op::ToString(gradOutput->GetViewFormat()).GetString(), op::ToString(self->GetViewFormat()).GetString(),75 op::ToString(gradOutput->GetViewFormat()).GetString(), op::ToString(self->GetViewFormat()).GetString(),
@@ -74,8 +78,8 @@ inline static bool CheckFormat(const aclTensor *gradOutput, const aclTensor *sel
74 return true;78 return true;
75}79}
76 80 
77static bool CheckShape(const aclTensor *gradOutput, const aclTensor *self, const aclIntArray *padding,81static bool CheckShape(const aclTensor* gradOutput, const aclTensor* self, const aclIntArray* padding,
78 const aclTensor *gradInput)82 const aclTensor* gradInput)
79{83{
80 auto selfDimnum = self->GetViewShape().GetDimNum();84 auto selfDimnum = self->GetViewShape().GetDimNum();
81 // self和gradInput的shape必须一致85 // self和gradInput的shape必须一致
@@ -86,28 +90,25 @@ static bool CheckShape(const aclTensor *gradOutput, const aclTensor *self, const
86 OP_CHECK_MAX_DIM(self, 3, return false);90 OP_CHECK_MAX_DIM(self, 3, return false);
87 91 
88 // gradOutput, self, gradInput维度需要一致92 // gradOutput, self, gradInput维度需要一致
89 OP_CHECK(gradOutput->GetViewShape().GetDimNum() == selfDimnum &&93 OP_CHECK(
90 gradInput->GetViewShape().GetDimNum() == selfDimnum,94 gradOutput->GetViewShape().GetDimNum() == selfDimnum && gradInput->GetViewShape().GetDimNum() == selfDimnum,
91 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "gradOutput, self, gradInput dim should be same."),95 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "gradOutput, self, gradInput dim should be same."), return false);
92 return false);
93 96 
94 // padding长度为297 // padding长度为2
95 OP_CHECK(padding->Size() == 2,98 OP_CHECK(padding->Size() == 2,
96 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding length should be 2, but got %lu.",99 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding length should be 2, but got %lu.", padding->Size()),
97 padding->Size()),
98 return false);100 return false);
99 101 
100 // check the last dim value of gradOutput. 0, 1 are indexes102 // check the last dim value of gradOutput. 0, 1 are indexes
101 OP_CHECK(gradOutput->GetViewShape().GetDim(selfDimnum - 1) ==103 OP_CHECK(gradOutput->GetViewShape().GetDim(selfDimnum - 1) ==
102 self->GetViewShape().GetDim(selfDimnum - 1) + (*padding)[0] + (*padding)[1],104 self->GetViewShape().GetDim(selfDimnum - 1) + (*padding)[0] + (*padding)[1],
103 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "wrong gradOutput shape."),105 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "wrong gradOutput shape."), return false);
104 return false);106 
105
106 return true;107 return true;
107}108}
108 109 
109inline static aclnnStatus CheckParams(const aclTensor *gradOutput, const aclTensor *self,110inline static aclnnStatus CheckParams(const aclTensor* gradOutput, const aclTensor* self, const aclIntArray* padding,
110 const aclIntArray *padding, const aclTensor *gradInput)111 const aclTensor* gradInput)
111{112{
112 // 1. 检查参数是否为空指针113 // 1. 检查参数是否为空指针
113 CHECK_RET(CheckNotNull(gradOutput, self, padding, gradInput), ACLNN_ERR_PARAM_NULLPTR);114 CHECK_RET(CheckNotNull(gradOutput, self, padding, gradInput), ACLNN_ERR_PARAM_NULLPTR);
@@ -124,18 +125,18 @@ inline static aclnnStatus CheckParams(const aclTensor *gradOutput, const aclTens
124 return ACLNN_SUCCESS;125 return ACLNN_SUCCESS;
125}126}
126 127 
127static const aclTensor *GetPaddingTensor(int64_t dim, const aclIntArray *padding, aclOpExecutor *executor)128static const aclTensor* GetPaddingTensor(int64_t dim, const aclIntArray* padding, aclOpExecutor* executor)
128{129{
129 FVector<int64_t, op::MAX_DIM_NUM> paddingsVector;130 FVector<int64_t, op::MAX_DIM_NUM> paddingsVector;
130 // 2 is the magnification131 // 2 is the magnification
131 for (size_t i = 2 * dim; i > 0; i -= 2) {132 for (size_t i = 2 * dim; i > 0; i -= 2) {
132 if (i <= (size_t)padding->Size()) {133 if (i <= (size_t)padding->Size()) {
133 // 2 and 1 indicate the element of padding is put into paddingsVector from the back to the front134 // 2 and 1 indicate the element of padding is put into paddingsVector from the back to the front
134 paddingsVector.emplace_back((*padding)[i - 2]);135 paddingsVector.emplace_back((*padding)[i - 2]);
135 paddingsVector.emplace_back((*padding)[i - 1]);136 paddingsVector.emplace_back((*padding)[i - 1]);
136 } else {137 } else {
137 paddingsVector.emplace_back(0);138 paddingsVector.emplace_back(0);
138 paddingsVector.emplace_back(0);139 paddingsVector.emplace_back(0);
139 }140 }
140 }141 }
141 // 2 is the magnification142 // 2 is the magnification
@@ -144,17 +145,24 @@ static const aclTensor *GetPaddingTensor(int64_t dim, const aclIntArray *padding
144 return paddingsTensor;145 return paddingsTensor;
145}146}
146 147 
147static bool CheckPaddingValue(const aclIntArray *padding) {148static bool CheckPaddingValue(const aclIntArray* padding, const aclTensor* gradOutput)
149{
148 // padding的每一维度的数值要大于等于0150 // padding的每一维度的数值要大于等于0
149 if ((*padding)[0] < 0 || (*padding)[1] < 0 ) {151 if ((*padding)[0] < 0 || (*padding)[1] < 0) {
150 OP_LOGW("on aicore situation, padding values should be greater than 0 or equal 0.");152 OP_LOGW("on aicore situation, padding values should be greater than 0 or equal 0.");
151 return false;153 return false;
152 }154 }
155 // fp32类型下,AtlasA2 padding最多不超过7200
156 if (!IsRegBase() && gradOutput->GetDataType() == op::DataType::DT_FLOAT &&
157 ((*padding)[0] >= PADDING_FP32_MAX || (*padding)[1] >= PADDING_FP32_MAX)) {
atomgit-bot
atomgit-botatomgit-bot7月7日

🟠 High Priority

变更后的 CheckPaddingValue(第 148-162 行)仅当 gradOutput->GetDataType() == op::DataType::DT_FLOAT 时检查 padding 阈值(>=7200),将 FP32 路由到 AICPU。但 FP16 和 BF16 输入在执行路径上同样会受影响:

  1. aclnnReplicationPad1dBackwardGetWorkspaceSize 第 235-237 行:当 padFlag == true 且原始 dtype 为 FP16/BF16 时,gradOutput 会被强制 Cast 为 FP32。
  2. 随后 l0op::PadV3Grad(..., padFlag=true) 被调用时,gradOutput 已是 FP32。
  3. PadV3Grad(padv3grad.cpp 第 283 行)中,IsPadV3GradReplicateAicoreSupport 检查的是 Cast 后的 dtype(FP32),而 FP32 在 REPLICATION_2D_AICORE_DTYPE_SUPPORT_LIST 中,因此会走 AICORE 路径 PadV3GradReplicateAiCore,以 FP32 数据 + 大 padding 执行 → 同样触发 507035 错误。

触发条件:910B1(A2) 平台,FP16 或 BF16 输入,padding[0] 或 padding[1] ≥ 7200。

修复方向:CheckPaddingValue 中应将 FP16 和 BF16 也纳入检查,或检查范围覆盖所有会经 Cast 变为 FP32 后走 AICORE replication 路径的 dtype(即 FP32、FP16、BF16)。

建议:将 dtype 检查从仅 DT_FLOAT 扩展为同时包含 DT_FLOAT16DT_BF16,使这三种经 AICORE FP32 kernel 执行的 dtype 在大 padding 场景下均能正确路由到 AICPU。

likedislike
158 OP_LOGW("on aicore situation, padding values should be less than 7200.");
159 return false;
160 }
153 return true;161 return true;
154}162}
155 163 
156static aclnnStatus InputPreprocess(const aclTensor *&gradOutput, const aclTensor *&self, const aclIntArray *dimArray,164static aclnnStatus InputPreprocess(const aclTensor*& gradOutput, const aclTensor*& self, const aclIntArray* dimArray,
157 int64_t dimCp, aclOpExecutor *executor)165 int64_t dimCp, aclOpExecutor* executor)
158{166{
159 // 如果非连续,需要转连续167 // 如果非连续,需要转连续
160 gradOutput = l0op::Contiguous(gradOutput, executor);168 gradOutput = l0op::Contiguous(gradOutput, executor);
@@ -173,11 +181,12 @@ static aclnnStatus InputPreprocess(const aclTensor *&gradOutput, const aclTensor
173 return ACLNN_SUCCESS;181 return ACLNN_SUCCESS;
174}182}
175 183 
176aclnnStatus aclnnReplicationPad1dBackwardGetWorkspaceSize(const aclTensor *gradOutput, const aclTensor *self,184aclnnStatus aclnnReplicationPad1dBackwardGetWorkspaceSize(const aclTensor* gradOutput, const aclTensor* self,
177 const aclIntArray *padding, aclTensor *gradInput, uint64_t *workspaceSize, aclOpExecutor **executor)185 const aclIntArray* padding, aclTensor* gradInput,
186 uint64_t* workspaceSize, aclOpExecutor** executor)
178{187{
179 OP_CHECK_COMM_INPUT(workspaceSize, executor);188 OP_CHECK_COMM_INPUT(workspaceSize, executor);
180 189 
181 L2_DFX_PHASE_1(aclnnReplicationPad1dBackward, DFX_IN(gradOutput, self, padding), DFX_OUT(gradInput));190 L2_DFX_PHASE_1(aclnnReplicationPad1dBackward, DFX_IN(gradOutput, self, padding), DFX_OUT(gradInput));
182 // 固定写法,创建OpExecutor191 // 固定写法,创建OpExecutor
183 auto uniqueExecutor = CREATE_EXECUTOR();192 auto uniqueExecutor = CREATE_EXECUTOR();
@@ -199,9 +208,9 @@ aclnnStatus aclnnReplicationPad1dBackwardGetWorkspaceSize(const aclTensor *gradO
199 if (self->GetViewShape().GetDimNum() == 3) {208 if (self->GetViewShape().GetDimNum() == 3) {
200 // 1, 2 are indexes209 // 1, 2 are indexes
201 if (self->GetViewShape().GetDim(1) == 0 || self->GetViewShape().GetDim(2) == 0) {210 if (self->GetViewShape().GetDim(1) == 0 || self->GetViewShape().GetDim(2) == 0) {
202 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Input should not be empty.");211 OP_LOGE(ACLNN_ERR_PARAM_INVALID, "Input should not be empty.");
203 return ACLNN_ERR_PARAM_INVALID;212 return ACLNN_ERR_PARAM_INVALID;
204 }213 }
205 }214 }
206 uniqueExecutor.ReleaseTo(executor);215 uniqueExecutor.ReleaseTo(executor);
207 return ACLNN_SUCCESS;216 return ACLNN_SUCCESS;
@@ -213,14 +222,14 @@ aclnnStatus aclnnReplicationPad1dBackwardGetWorkspaceSize(const aclTensor *gradO
213 // 0 is index222 // 0 is index
214 const int64_t appendDim[] = {0};223 const int64_t appendDim[] = {0};
215 // 1 is the dim num to be unsqueezed224 // 1 is the dim num to be unsqueezed
216 aclIntArray *dimArray = (uniqueExecutor.get())->AllocIntArray(appendDim, 1);225 aclIntArray* dimArray = (uniqueExecutor.get())->AllocIntArray(appendDim, 1);
217 ret = InputPreprocess(gradOutput, self, dimArray, dimCp, uniqueExecutor.get());226 ret = InputPreprocess(gradOutput, self, dimArray, dimCp, uniqueExecutor.get());
218 CHECK_RET(ret == ACLNN_SUCCESS, ret);227 CHECK_RET(ret == ACLNN_SUCCESS, ret);
219 228 
220 dim = self->GetViewShape().GetDimNum();229 dim = self->GetViewShape().GetDimNum();
221 auto paddingsTensor = GetPaddingTensor(dim, padding, uniqueExecutor.get());230 auto paddingsTensor = GetPaddingTensor(dim, padding, uniqueExecutor.get());
222 auto padFlag = CheckPaddingValue(padding);231 auto padFlag = CheckPaddingValue(padding, gradOutput);
223 const aclTensor *pad1dbackwardResult = nullptr;232 const aclTensor* pad1dbackwardResult = nullptr;
224 auto originOutDataType = gradOutput->GetDataType();233 auto originOutDataType = gradOutput->GetDataType();
225 // cast to fp32 from fp16 or bf16234 // cast to fp32 from fp16 or bf16
226 if (padFlag && (originOutDataType == op::DataType::DT_FLOAT16 || originOutDataType == op::DataType::DT_BF16)) {235 if (padFlag && (originOutDataType == op::DataType::DT_FLOAT16 || originOutDataType == op::DataType::DT_BF16)) {
@@ -228,8 +237,8 @@ aclnnStatus aclnnReplicationPad1dBackwardGetWorkspaceSize(const aclTensor *gradO
228 OP_LOGD("[PadV3Grad] FP16 or BF16 Cast to FP32: true");237 OP_LOGD("[PadV3Grad] FP16 or BF16 Cast to FP32: true");
229 }238 }
230 239 
231 pad1dbackwardResult = l0op::PadV3Grad(gradOutput, paddingsTensor,240 pad1dbackwardResult = l0op::PadV3Grad(gradOutput, paddingsTensor, REPLICATION_MODE, true, padFlag,
232 REPLICATION_MODE, true, padFlag, uniqueExecutor.get());241 uniqueExecutor.get());
233 CHECK_RET(pad1dbackwardResult != nullptr, ACLNN_ERR_INNER_NULLPTR);242 CHECK_RET(pad1dbackwardResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
234 pad1dbackwardResult = l0op::SqueezeNd(pad1dbackwardResult, dimArray, uniqueExecutor.get());243 pad1dbackwardResult = l0op::SqueezeNd(pad1dbackwardResult, dimArray, uniqueExecutor.get());
235 // 2 is dim244 // 2 is dim
@@ -237,8 +246,8 @@ aclnnStatus aclnnReplicationPad1dBackwardGetWorkspaceSize(const aclTensor *gradO
237 pad1dbackwardResult = l0op::SqueezeNd(pad1dbackwardResult, dimArray, uniqueExecutor.get());246 pad1dbackwardResult = l0op::SqueezeNd(pad1dbackwardResult, dimArray, uniqueExecutor.get());
238 }247 }
239 CHECK_RET(pad1dbackwardResult != nullptr, ACLNN_ERR_INNER_NULLPTR);248 CHECK_RET(pad1dbackwardResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
240 249 
241 // cast to fp16 or bf16 250 // cast to fp16 or bf16
242 if (padFlag && (originOutDataType == op::DataType::DT_FLOAT16 || originOutDataType == op::DataType::DT_BF16)) {251 if (padFlag && (originOutDataType == op::DataType::DT_FLOAT16 || originOutDataType == op::DataType::DT_BF16)) {
243 pad1dbackwardResult = l0op::Cast(pad1dbackwardResult, originOutDataType, uniqueExecutor.get());252 pad1dbackwardResult = l0op::Cast(pad1dbackwardResult, originOutDataType, uniqueExecutor.get());
244 OP_LOGD("[PadV3Grad] FP16 or BF16 Cast to FP32: true");253 OP_LOGD("[PadV3Grad] FP16 or BF16 Cast to FP32: true");
@@ -252,16 +261,15 @@ aclnnStatus aclnnReplicationPad1dBackwardGetWorkspaceSize(const aclTensor *gradO
252 *workspaceSize = uniqueExecutor->GetWorkspaceSize();261 *workspaceSize = uniqueExecutor->GetWorkspaceSize();
253 uniqueExecutor.ReleaseTo(executor);262 uniqueExecutor.ReleaseTo(executor);
254 return ACLNN_SUCCESS;263 return ACLNN_SUCCESS;
255 }264}
256 265 
257aclnnStatus aclnnReplicationPad1dBackward(void *workspace, uint64_t workspaceSize, aclOpExecutor *executor,266aclnnStatus aclnnReplicationPad1dBackward(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor,
258 aclrtStream stream)267 aclrtStream stream)
259{268{
260 L2_DFX_PHASE_2(aclnnReplicationPad1dBackward);269 L2_DFX_PHASE_2(aclnnReplicationPad1dBackward);
261 // 固定写法,调用框架能力,完成计算270 // 固定写法,调用框架能力,完成计算
262 return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);271 return CommonOpExecutorRun(workspace, workspaceSize, executor, stream);
263}272}
264 
265#ifdef __cplusplus273#ifdef __cplusplus
266}274}
267#endif275#endif