Merged
feat: pad_v2 新增 COMPLEX64/COMPLEX128 支持,circular_pad_grad 修改参数校验 #6513
tan_xinAdd on 22 days ago
feat: pad_v2 新增 COMPLEX64/COMPLEX128 支持,circular_pad_grad 修改参数校验 #6513
Merged
Merged fromtan_xin/ops-mathmaster-tileintocann/ops-mathmaster
Total: 19 files changed+215-47
| @@ -86,7 +86,7 @@ aclnnStatus aclnnCircularPad2dBackward( | |||
| 86 | <td>输入</td> | 86 | <td>输入</td> |
| 87 | <td>反向时输入的梯度数据。</td> | 87 | <td>反向时输入的梯度数据。</td> |
| 88 | <td>shape维度需要与self和gradInput一致,shape需要与circular_pad2d正向传播的output一致。</td> | 88 | <td>shape维度需要与self和gradInput一致,shape需要与circular_pad2d正向传播的output一致。</td> |
| 89 | - <td>shape需要与circular_pad2d正向传播的output一致。</td> | 89 | + <td>与self一致</td> |
| 90 | <td>ND</td> | 90 | <td>ND</td> |
| 91 | <td>维度与self保持一致</td> | 91 | <td>维度与self保持一致</td> |
| 92 | <td>√</td> | 92 | <td>√</td> |
| @@ -242,8 +242,8 @@ aclnnStatus aclnnCircularPad2dBackward( | |||
| 242 | - aclnnCircularPad2dBackward默认确定性实现。 | 242 | - aclnnCircularPad2dBackward默认确定性实现。 |
| 243 | 243 | ||
| 244 | - gradOutput的最后一维在不同类型下的大小需满足如下约束: | 244 | - gradOutput的最后一维在不同类型下的大小需满足如下约束: |
| 245 | -float16/bfloat16:(0, 16362) | 245 | +float16/bfloat16:(0, 16384) |
| 246 | -float32:(0, 24544) | 246 | +float32:(0, 24576) |
| 247 | 247 | ||
| 248 | ## 调用示例 | 248 | ## 调用示例 |
| 249 | 249 | ||
| @@ -234,8 +234,8 @@ aclnnStatus aclnnCircularPad3dBackward( | |||
| 234 | - aclnnCircularPad3dBackward默认确定性实现。 | 234 | - aclnnCircularPad3dBackward默认确定性实现。 |
| 235 | 235 | ||
| 236 | gradOutput的最后一维在不同类型下的大小需满足如下约束: | 236 | gradOutput的最后一维在不同类型下的大小需满足如下约束: |
| 237 | -float16/bfloat16:(0, 16362) | 237 | +float16/bfloat16:(0, 16384) |
| 238 | -float32:(0, 24544) | 238 | +float32:(0, 24576) |
| 239 | 239 | ||
| 240 | ## 调用示例 | 240 | ## 调用示例 |
| 241 | 241 | ||
| @@ -37,6 +37,23 @@ static bool CheckShape(const aclTensor* gradOutput, const aclTensor* self, const | |||
| 37 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding length should be 4, but got %zu.", padding->Size()), | 37 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding length should be 4, but got %zu.", padding->Size()), |
| 38 | return false); | 38 | return false); |
| 39 | 39 | ||
| 40 | + // padding 各值必须小于对应 self 维度(文档承诺 161002;与 3d 接口校验一致) | ||
| 41 | + OP_CHECK((*padding)[0] < self->GetViewShape().GetDim(selfDimnum - 1) && | ||
| 42 | + (*padding)[1] < self->GetViewShape().GetDim(selfDimnum - 1) && | ||
| 43 | + (*padding)[2] < self->GetViewShape().GetDim(selfDimnum - 2) && | ||
| 44 | + (*padding)[3] < self->GetViewShape().GetDim(selfDimnum - 2), | ||
| 45 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding size should be less than the corresponding self dimension."), | ||
| 46 | + return false); | ||
| 47 | + | ||
| 48 | + // gradOutput 前导维度需与 self 一致(文档:gradOutput shape 与正向 output 一致) | ||
| 49 | + // 空 tensor 场景(gradOutput 前导维为 0)由下方"空tensor处理"分支短路,此处跳过校验 | ||
| 50 | + if (!gradOutput->IsEmpty()) { | ||
| 51 | + for (size_t i = 0; i + 2 < static_cast<size_t>(selfDimnum); ++i) { | ||
| 52 | + OP_CHECK(gradOutput->GetViewShape().GetDim(i) == self->GetViewShape().GetDim(i), | ||
| 53 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID, "gradOutput leading dim should be same as self."), return false); | ||
| 54 | + } | ||
| 55 | + } | ||
| 56 | + | ||
| 40 | // check the last 2 dim value of out. 0, 1, 2, 3 are indexes | 57 | // check the last 2 dim value of out. 0, 1, 2, 3 are indexes |
| 41 | OP_CHECK(gradOutput->GetViewShape().GetDim(selfDimnum - 2) == | 58 | OP_CHECK(gradOutput->GetViewShape().GetDim(selfDimnum - 2) == |
| 42 | self->GetViewShape().GetDim(selfDimnum - 2) + (*padding)[2] + (*padding)[3] && | 59 | self->GetViewShape().GetDim(selfDimnum - 2) + (*padding)[2] + (*padding)[3] && |
| @@ -47,6 +47,15 @@ inline static bool CheckShape(const aclTensor* gradOutput, const aclTensor* self | |||
| 47 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding size should be less than the corresponding self dimension."), | 47 | OP_LOGE(ACLNN_ERR_PARAM_INVALID, "padding size should be less than the corresponding self dimension."), |
| 48 | return false); | 48 | return false); |
| 49 | 49 | ||
| 50 | + // gradOutput 前导维度需与 self 一致(文档:gradOutput shape 与正向 output 一致) | ||
| 51 | + // 空 tensor 场景(gradOutput 前导维为 0)由下方"空tensor处理"分支短路,此处跳过校验 | ||
| 52 | + if (!gradOutput->IsEmpty()) { | ||
| 53 | + for (size_t i = 0; i + 3 < static_cast<size_t>(selfDimnum); ++i) { | ||
| 54 | + OP_CHECK(gradOutput->GetViewShape().GetDim(i) == self->GetViewShape().GetDim(i), | ||
| 55 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID, "gradOutput leading dim should be same as self."), return false); | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + | ||
| 50 | // check the last 2 dim value of out. 0, 1, 2, 3 are indexes | 59 | // check the last 2 dim value of out. 0, 1, 2, 3 are indexes |
| 51 | OP_CHECK(gradOutput->GetViewShape().GetDim(selfDimnum - 2) == | 60 | OP_CHECK(gradOutput->GetViewShape().GetDim(selfDimnum - 2) == |
| 52 | self->GetViewShape().GetDim(selfDimnum - 2) + (*padding)[2] + (*padding)[3] && | 61 | self->GetViewShape().GetDim(selfDimnum - 2) + (*padding)[2] + (*padding)[3] && |
| @@ -22,7 +22,7 @@ extern "C" { | |||
| 22 | * | 22 | * |
| 23 | * 算子功能:循环填充的反向传播。 | 23 | * 算子功能:循环填充的反向传播。 |
| 24 | * @param [in] gradOutput: npu device侧的aclTensor, 数据类型支持FLOAT16, FLOAT32, BFLOAT16, 数据格式支持ND, | 24 | * @param [in] gradOutput: npu device侧的aclTensor, 数据类型支持FLOAT16, FLOAT32, BFLOAT16, 数据格式支持ND, |
| 25 | - * 维度支持三维或四维且与self和gradInput一致,shape需要与circular_pad3d正向传播的output一致。 | 25 | + * 维度支持四维或五维且与self和gradInput一致,shape需要与circular_pad3d正向传播的output一致。 |
| 26 | * @param [in] self: npu device侧的aclTensor, | 26 | * @param [in] self: npu device侧的aclTensor, |
| 27 | * 数据类型与gradOutput一致,数据格式支持ND,维度支持四维或五维且与gradOutput和 gradInput一致,shape与gradInput一致。 | 27 | * 数据类型与gradOutput一致,数据格式支持ND,维度支持四维或五维且与gradOutput和 gradInput一致,shape与gradInput一致。 |
| 28 | * @param [in] padding: npu device侧的aclIntArray数组, 数据类型为INT64,长度为6,数值依次代表左右上下前后需要填充的值。 | 28 | * @param [in] padding: npu device侧的aclIntArray数组, 数据类型为INT64,长度为6,数值依次代表左右上下前后需要填充的值。 |
| @@ -113,4 +113,4 @@ | |||
| 113 | ] | 113 | ] |
| 114 | } | 114 | } |
| 115 | ] | 115 | ] |
| 116 | -} | 116 | +} |
| @@ -8,6 +8,6 @@ | |||
| 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 | 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 |
| 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 | 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 |
| 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 | 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 |
| 11 | -; 6)是否是AscendC算子,由 ops/build-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 | 11 | +; 6)是否是AscendC算子,由 ops/built-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 |
| 12 | [CircularPadGrad] | 12 | [CircularPadGrad] |
| 13 | -default=0 | 13 | +default=0 |
| @@ -113,4 +113,4 @@ | |||
| 113 | ] | 113 | ] |
| 114 | } | 114 | } |
| 115 | ] | 115 | ] |
| 116 | -} | 116 | +} |
| @@ -8,6 +8,6 @@ | |||
| 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 | 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 |
| 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 | 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 |
| 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 | 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 |
| 11 | -; 6)是否是AscendC算子,由 ops/build-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 | 11 | +; 6)是否是AscendC算子,由 ops/built-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 |
| 12 | [CircularPadGrad] | 12 | [CircularPadGrad] |
| 13 | -default=0 | 13 | +default=0 |
| @@ -122,4 +122,4 @@ | |||
| 122 | ] | 122 | ] |
| 123 | } | 123 | } |
| 124 | ] | 124 | ] |
| 125 | -} | 125 | +} |
| @@ -8,6 +8,6 @@ | |||
| 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 | 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 |
| 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 | 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 |
| 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 | 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 |
| 11 | -; 6)是否是AscendC算子,由 ops/build-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 | 11 | +; 6)是否是AscendC算子,由 ops/built-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 |
| 12 | [CircularPadGrad] | 12 | [CircularPadGrad] |
| 13 | -default=0 | 13 | +default=0 |
| @@ -15,7 +15,11 @@ import numpy as np | |||
| 15 | 15 | ||
| 16 | __golden__ = {"kernel": {"circular_pad_grad": "circular_pad_grad_golden"}} | 16 | __golden__ = {"kernel": {"circular_pad_grad": "circular_pad_grad_golden"}} |
| 17 | 17 | ||
| 18 | -__spec__ = {"circular_pad_grad": "CircularPadGradTestSpec"} | 18 | +__spec__ = { |
| 19 | + "circular_pad_grad": "CircularPadGradTestSpec", | ||
| 20 | + "aclnnCircularPad2dBackward": "AclnnCircularPad2dBackwardSpec", | ||
| 21 | + "aclnnCircularPad3dBackward": "AclnnCircularPad3dBackwardSpec", | ||
| 22 | +} | ||
| 19 | 23 | ||
| 20 | 24 | ||
| 21 | def _numpy_bfloat16(): | 25 | def _numpy_bfloat16(): |
| @@ -157,10 +161,79 @@ def circular_pad_grad_golden(x, paddings, **kwargs): | |||
| 157 | return grad | 161 | return grad |
| 158 | 162 | ||
| 159 | 163 | ||
| 164 | +def _aclnn_circular_pad_grad_golden(grad_output_np, self_np, padding): | ||
| 165 | + """ACLNN 反向参考:以 self 形状构造 circular 正向线性算子,torch autograd 取反向(torch 直通)。 | ||
| 166 | + | ||
| 167 | + padding 为扁平序列,[0,1] 作用于 self 最后一维、[2,3] 倒数第二维、[4,5] 倒数第三维, | ||
| 168 | + 与 F.pad 的 pad 元组顺序(末维在前)一致,可直接透传。 | ||
| 169 | + """ | ||
| 170 | + import torch | ||
| 171 | + | ||
| 172 | + pad_flat = np.array(padding).reshape(-1).tolist() | ||
| 173 | + pads = tuple(int(v) for v in pad_flat) | ||
| 174 | + origin_dtype = grad_output_np.dtype.name | ||
| 175 | + grad_output = _numpy_to_torch_tensor(grad_output_np) | ||
| 176 | + self_t = torch.zeros(list(self_np.shape), dtype=grad_output.dtype) | ||
| 177 | + if origin_dtype == "bfloat16": | ||
| 178 | + grad_output = grad_output.to(torch.float32) | ||
| 179 | + self_t = self_t.to(torch.float32) | ||
| 180 | + self_t.requires_grad_(True) | ||
| 181 | + out = torch.nn.functional.pad(self_t, pads, "circular") | ||
| 182 | + loss = (grad_output * out).sum() | ||
| 183 | + loss.backward() | ||
| 184 | + grad_input = self_t.grad | ||
| 185 | + if origin_dtype == "bfloat16": | ||
| 186 | + grad_input = grad_input.to(torch.bfloat16) | ||
| 187 | + return _torch_to_numpy_tensor(grad_input) | ||
| 188 | + | ||
| 189 | + | ||
| 190 | +class CircularPadGradTorchImpl: | ||
| 191 | + """third_party torch 实现:F.pad(circular) + autograd 反向(本算子无同名第三方算子)。""" | ||
| 192 | + | ||
| 193 | + def __init__(self, paddings=None, **kwargs): | ||
| 194 | + del kwargs | ||
| 195 | + self.paddings = paddings | ||
| 196 | + | ||
| 197 | + def __call__(self, x, paddings=None, **kwargs): | ||
| 198 | + del kwargs | ||
| 199 | + pads = self.paddings if paddings is None else paddings | ||
| 200 | + return [circular_pad_grad_golden(x, pads)] | ||
| 201 | + | ||
| 202 | + | ||
| 160 | class CircularPadGradTestSpec: | 203 | class CircularPadGradTestSpec: |
| 161 | def golden(x, paddings, **kwargs): | 204 | def golden(x, paddings, **kwargs): |
| 162 | return [circular_pad_grad_golden(x, paddings, **kwargs)] | 205 | return [circular_pad_grad_golden(x, paddings, **kwargs)] |
| 163 | 206 | ||
| 207 | + third_party = {"torch": CircularPadGradTorchImpl} | ||
| 208 | + | ||
| 209 | + tolerance = { | ||
| 210 | + "float32": {"standard": "mix_tolerance"}, | ||
| 211 | + "float16": {"standard": "mix_tolerance"}, | ||
| 212 | + "bfloat16": {"standard": "mix_tolerance"}, | ||
| 213 | + } | ||
| 214 | + | ||
| 215 | + | ||
| 216 | +class AclnnCircularPad2dBackwardSpec: | ||
| 217 | + def golden(gradOutput, self, padding, **kwargs): | ||
| 218 | + del kwargs | ||
| 219 | + return [_aclnn_circular_pad_grad_golden(gradOutput, self, padding)] | ||
| 220 | + | ||
| 221 | + third_party = {"torch": CircularPadGradTorchImpl} | ||
| 222 | + | ||
| 223 | + tolerance = { | ||
| 224 | + "float32": {"standard": "mix_tolerance"}, | ||
| 225 | + "float16": {"standard": "mix_tolerance"}, | ||
| 226 | + "bfloat16": {"standard": "mix_tolerance"}, | ||
| 227 | + } | ||
| 228 | + | ||
| 229 | + | ||
| 230 | +class AclnnCircularPad3dBackwardSpec: | ||
| 231 | + def golden(gradOutput, self, padding, **kwargs): | ||
| 232 | + del kwargs | ||
| 233 | + return [_aclnn_circular_pad_grad_golden(gradOutput, self, padding)] | ||
| 234 | + | ||
| 235 | + third_party = {"torch": CircularPadGradTorchImpl} | ||
| 236 | + | ||
| 164 | tolerance = { | 237 | tolerance = { |
| 165 | "float32": {"standard": "mix_tolerance"}, | 238 | "float32": {"standard": "mix_tolerance"}, |
| 166 | "float16": {"standard": "mix_tolerance"}, | 239 | "float16": {"standard": "mix_tolerance"}, |
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | ```text | 19 | ```text |
| 20 | 输入tensor([[0,1,2]]) | 20 | 输入tensor([[0,1,2]]) |
| 21 | - paddings([[2,2]]) | 21 | + paddings([[0,0],[2,2]]) |
| 22 | constant_values(0) | 22 | constant_values(0) |
| 23 | 23 | ||
| 24 | 输出为([[0,0,0,1,2,0,0]]) | 24 | 输出为([[0,0,0,1,2,0,0]]) |
| @@ -46,7 +46,7 @@ | |||
| 46 | <td>x</td> | 46 | <td>x</td> |
| 47 | <td>输入</td> | 47 | <td>输入</td> |
| 48 | <td>待进行填充的原始tensor。</td> | 48 | <td>待进行填充的原始tensor。</td> |
| 49 | - <td>FLOAT、FLOAT16、INT32、INT64、INT16、INT8、UINT8、UINT16、UINT32、UINT64、BOOL、DOUBLE、COMPLEX64、COMPLEX128、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT8_E8M0、FLOAT4_E2M1、FLOAT4_E1M2。</td> | 49 | + <td>FLOAT、FLOAT16、INT32、INT64、INT16、INT8、UINT8、UINT16、UINT32、UINT64、BOOL、DOUBLE、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT8_E8M0、FLOAT4_E2M1、FLOAT4_E1M2。</td> |
| 50 | <td>ND</td> | 50 | <td>ND</td> |
| 51 | </tr> | 51 | </tr> |
| 52 | <tr> | 52 | <tr> |
| @@ -60,14 +60,14 @@ | |||
| 60 | <td>constant_values</td> | 60 | <td>constant_values</td> |
| 61 | <td>输入</td> | 61 | <td>输入</td> |
| 62 | <td>填充常量值,标量tensor。</td> | 62 | <td>填充常量值,标量tensor。</td> |
| 63 | - <td>FLOAT、FLOAT16、INT32、INT64、INT16、INT8、UINT8、UINT16、UINT32、UINT64、BOOL、DOUBLE、COMPLEX64、COMPLEX128、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT8_E8M0、FLOAT4_E2M1、FLOAT4_E1M2。</td> | 63 | + <td>FLOAT、FLOAT16、INT32、INT64、INT16、INT8、UINT8、UINT16、UINT32、UINT64、BOOL、DOUBLE、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT8_E8M0、FLOAT4_E2M1、FLOAT4_E1M2。</td> |
| 64 | <td>ND</td> | 64 | <td>ND</td> |
| 65 | </tr> | 65 | </tr> |
| 66 | <tr> | 66 | <tr> |
| 67 | <td>y</td> | 67 | <td>y</td> |
| 68 | <td>输出</td> | 68 | <td>输出</td> |
| 69 | <td>填充后的tensor。</td> | 69 | <td>填充后的tensor。</td> |
| 70 | - <td>FLOAT、FLOAT16、INT32、INT64、INT16、INT8、UINT8、UINT16、UINT32、UINT64、BOOL、DOUBLE、COMPLEX64、COMPLEX128、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT8_E8M0、FLOAT4_E2M1、FLOAT4_E1M2。</td> | 70 | + <td>FLOAT、FLOAT16、INT32、INT64、INT16、INT8、UINT8、UINT16、UINT32、UINT64、BOOL、DOUBLE、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT8_E8M0、FLOAT4_E2M1、FLOAT4_E1M2。</td> |
| 71 | <td>ND</td> | 71 | <td>ND</td> |
| 72 | </tr> | 72 | </tr> |
| 73 | </tbody></table> | 73 | </tbody></table> |
| @@ -92,7 +92,11 @@ y.shape[d] = x.shape[d] + paddings[d][0] + paddings[d][1] | |||
| 92 | - x、constant_values、y必须使用相同的数据类型 | 92 | - x、constant_values、y必须使用相同的数据类型 |
| 93 | - paddings必须使用INT32或INT64 | 93 | - paddings必须使用INT32或INT64 |
| 94 | 94 | ||
| 95 | -3. **填充约束**: | 95 | +3. **fp8/fp4 类型约束**: |
| 96 | + - x为HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT8_E8M0、FLOAT4_E2M1、FLOAT4_E1M2时,paddings各维必须为非负值 | ||
| 97 | + - x为FLOAT4_E2M1、FLOAT4_E1M2时,输入尾轴shape必须为偶数,且尾轴paddings必须为偶数 | ||
| 98 | + | ||
| 99 | +4. **填充约束**: | ||
| 96 | - 负填充(slice)时,输出shape = x.shape[d] + left + right >= 0 | 100 | - 负填充(slice)时,输出shape = x.shape[d] + left + right >= 0 |
| 97 | 101 | ||
| 98 | 4. **paddings参数约束** | 102 | 4. **paddings参数约束** |
| @@ -107,6 +111,6 @@ y.shape[d] = x.shape[d] + paddings[d][0] + paddings[d][1] | |||
| 107 | 111 | ||
| 108 | ## 调用说明 | 112 | ## 调用说明 |
| 109 | 113 | ||
| 110 | -| 调用方式 | 调用样例 | 说明 | | 114 | +| 调用方式 | 样例代码 | 说明 | |
| 111 | | ------------| ---------------------------------------------------------| ----------------------------------------------------------------| | 115 | | ------------| ---------------------------------------------------------| ----------------------------------------------------------------| |
| 112 | -| aclnn调用 | [test_geir_pad_v2.cpp](./examples/arch35/test_geir_pad_v2.cpp) | 通过 [算子IR](op_graph/pad_v2_proto.h)接口方式调用PadV2算子 | | 116 | +| GE图模式 | [test_geir_pad_v2.cpp](./examples/arch35/test_geir_pad_v2.cpp) | 通过 [算子IR](op_graph/pad_v2_proto.h)接口方式调用PadV2算子 | |
| @@ -156,6 +156,10 @@ uint32_t GetDataTypeSize(DataType dt) | |||
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | // 生成float32数据 | 158 | // 生成float32数据 |
| 159 | +// 样例数据缓冲登记/释放(定义见 WriteDataToFile 前) | ||
| 160 | +std::vector<uint8_t*>& GetSampleBuffers(); | ||
| 161 | +void FreeSampleBuffers(); | ||
| 162 | + | ||
| 159 | int32_t GenDataFloat32(vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& input_tensor_desc) | 163 | int32_t GenDataFloat32(vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& input_tensor_desc) |
| 160 | { | 164 | { |
| 161 | input_tensor_desc.SetRealDimCnt(shapes.size()); | 165 | input_tensor_desc.SetRealDimCnt(shapes.size()); |
| @@ -165,6 +169,7 @@ int32_t GenDataFloat32(vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& | |||
| 165 | } | 169 | } |
| 166 | uint32_t data_len = size * 4; | 170 | uint32_t data_len = size * 4; |
| 167 | float* pData = new (std::nothrow) float[size]; | 171 | float* pData = new (std::nothrow) float[size]; |
| 172 | + GetSampleBuffers().push_back((uint8_t*)pData); | ||
| 168 | 173 | ||
| 169 | // 生成测试数据:0, 1, 2, 3, ... | 174 | // 生成测试数据:0, 1, 2, 3, ... |
| 170 | for (size_t i = 0; i < size; ++i) { | 175 | for (size_t i = 0; i < size; ++i) { |
| @@ -185,6 +190,7 @@ int32_t GenInt32Data(vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& i | |||
| 185 | } | 190 | } |
| 186 | uint32_t data_len = size * 4; | 191 | uint32_t data_len = size * 4; |
| 187 | int32_t* pData = new (std::nothrow) int32_t[size]; | 192 | int32_t* pData = new (std::nothrow) int32_t[size]; |
| 193 | + GetSampleBuffers().push_back((uint8_t*)pData); | ||
| 188 | 194 | ||
| 189 | // 使用传入的数据 | 195 | // 使用传入的数据 |
| 190 | for (size_t i = 0; i < size && i < dataVec.size(); ++i) { | 196 | for (size_t i = 0; i < size && i < dataVec.size(); ++i) { |
| @@ -202,6 +208,7 @@ int32_t GenScalarData(DataType dtype, Tensor& input_tensor, TensorDesc& input_te | |||
| 202 | 208 | ||
| 203 | if (dtype == ge::DT_FLOAT) { | 209 | if (dtype == ge::DT_FLOAT) { |
| 204 | float* pData = new (std::nothrow) float[1]; | 210 | float* pData = new (std::nothrow) float[1]; |
| 211 | + GetSampleBuffers().push_back((uint8_t*)pData); | ||
| 205 | pData[0] = value; | 212 | pData[0] = value; |
| 206 | input_tensor = Tensor(input_tensor_desc, (uint8_t*)pData, data_len); | 213 | input_tensor = Tensor(input_tensor_desc, (uint8_t*)pData, data_len); |
| 207 | } else { | 214 | } else { |
| @@ -212,6 +219,21 @@ int32_t GenScalarData(DataType dtype, Tensor& input_tensor, TensorDesc& input_te | |||
| 212 | } | 219 | } |
| 213 | 220 | ||
| 214 | // 写数据到文件 | 221 | // 写数据到文件 |
| 222 | +// 样例数据缓冲登记:Gen* 辅助函数分配的 new[] 缓冲在此登记,进程退出前统一释放 | ||
| 223 | +static std::vector<uint8_t*>& GetSampleBuffers() | ||
| 224 | +{ | ||
| 225 | + static std::vector<uint8_t*> buffers; | ||
| 226 | + return buffers; | ||
| 227 | +} | ||
| 228 | + | ||
| 229 | +void FreeSampleBuffers() | ||
| 230 | +{ | ||
| 231 | + for (uint8_t* buf : GetSampleBuffers()) { | ||
| 232 | + delete[] buf; | ||
| 233 | + } | ||
| 234 | + GetSampleBuffers().clear(); | ||
| 235 | +} | ||
| 236 | + | ||
| 215 | int32_t WriteDataToFile(string bin_file, uint64_t data_size, uint8_t* inputData) | 237 | int32_t WriteDataToFile(string bin_file, uint64_t data_size, uint8_t* inputData) |
| 216 | { | 238 | { |
| 217 | FILE* fp = fopen(bin_file.c_str(), "wb"); | 239 | FILE* fp = fopen(bin_file.c_str(), "wb"); |
| @@ -264,9 +286,6 @@ int CreateOppInGraph(DataType inDtype, std::vector<ge::Tensor>& input, std::vect | |||
| 264 | // 添加输入constant_values(可选输入) | 286 | // 添加输入constant_values(可选输入) |
| 265 | ADD_SCALAR_INPUT(3, constant_values, inDtype, 0.0f); | 287 | ADD_SCALAR_INPUT(3, constant_values, inDtype, 0.0f); |
| 266 | 288 | ||
| 267 | - // 添加属性mode | ||
| 268 | - ADD_ATTR(mode, "constant"); | ||
| 269 | - | ||
| 270 | // 添加输出y | 289 | // 添加输出y |
| 271 | ADD_OUTPUT(1, y, inDtype, yShape); | 290 | ADD_OUTPUT(1, y, inDtype, yShape); |
| 272 | 291 | ||
| @@ -303,6 +322,7 @@ int main(int argc, char* argv[]) | |||
| 303 | ret = CreateOppInGraph(inDtype, input, inputs, outputs, graph); | 322 | ret = CreateOppInGraph(inDtype, input, inputs, outputs, graph); |
| 304 | if (ret != SUCCESS) { | 323 | if (ret != SUCCESS) { |
| 305 | printf("%s - ERROR - [XIR]: Create graph failed\n", GetTime().c_str()); | 324 | printf("%s - ERROR - [XIR]: Create graph failed\n", GetTime().c_str()); |
| 325 | + GEFinalize(); | ||
| 306 | return FAILED; | 326 | return FAILED; |
| 307 | } | 327 | } |
| 308 | 328 | ||
| @@ -327,13 +347,20 @@ int main(int argc, char* argv[]) | |||
| 327 | std::map<AscendString, AscendString> graph_options = {}; | 347 | std::map<AscendString, AscendString> graph_options = {}; |
| 328 | uint32_t graph_id = 0; | 348 | uint32_t graph_id = 0; |
| 329 | ret = session->AddGraph(graph_id, graph, graph_options); | 349 | ret = session->AddGraph(graph_id, graph, graph_options); |
| 330 | - | 350 | + if (ret != SUCCESS) { |
| 351 | + printf("%s - ERROR - [XIR]: Session add ir compute graph to ir session failed\n", GetTime().c_str()); | ||
| 352 | + delete session; | ||
| 353 | + GEFinalize(); | ||
| 354 | + return FAILED; | ||
| 355 | + } | ||
| 331 | printf("%s - INFO - [XIR]: Session add ir compute graph to ir session success\n", GetTime().c_str()); | 356 | printf("%s - INFO - [XIR]: Session add ir compute graph to ir session success\n", GetTime().c_str()); |
| 332 | printf("%s - INFO - [XIR]: dump graph to txt\n", GetTime().c_str()); | 357 | printf("%s - INFO - [XIR]: dump graph to txt\n", GetTime().c_str()); |
| 333 | 358 | ||
| 334 | // dump图结构到文件 | 359 | // dump图结构到文件 |
| 335 | std::string file_path = "./dump"; | 360 | std::string file_path = "./dump"; |
| 336 | - aclgrphDumpGraph(graph, file_path.c_str(), file_path.length()); | 361 | + if (aclgrphDumpGraph(graph, file_path.c_str(), file_path.length()) != SUCCESS) { |
| 362 | + printf("%s - WARNING - [XIR]: Dump graph to txt failed\n", GetTime().c_str()); | ||
| 363 | + } | ||
| 337 | 364 | ||
| 338 | // 执行图 | 365 | // 执行图 |
| 339 | printf("%s - INFO - [XIR]: Start to run ir compute graph\n", GetTime().c_str()); | 366 | printf("%s - INFO - [XIR]: Start to run ir compute graph\n", GetTime().c_str()); |
| @@ -356,7 +383,12 @@ int main(int argc, char* argv[]) | |||
| 356 | int64_t input_shape = input[i].GetTensorDesc().GetShape().GetShapeSize(); | 383 | int64_t input_shape = input[i].GetTensorDesc().GetShape().GetShapeSize(); |
| 357 | std::cout << "this is " << i << "th input, input shape size =" << input_shape << std::endl; | 384 | std::cout << "this is " << i << "th input, input shape size =" << input_shape << std::endl; |
| 358 | uint32_t data_size = input_shape * GetDataTypeSize(input[i].GetTensorDesc().GetDataType()); | 385 | uint32_t data_size = input_shape * GetDataTypeSize(input[i].GetTensorDesc().GetDataType()); |
| 359 | - WriteDataToFile((const char*)input_file.c_str(), data_size, input_data_i); | 386 | + if (WriteDataToFile((const char*)input_file.c_str(), data_size, input_data_i) != SUCCESS) { |
| 387 | + printf("%s - ERROR - [XIR]: Write input bin %s failed\n", GetTime().c_str(), input_file.c_str()); | ||
| 388 | + delete session; | ||
| 389 | + GEFinalize(); | ||
| 390 | + return FAILED; | ||
| 391 | + } | ||
| 360 | 392 | ||
| 361 | // 打印输入数据(仅float类型) | 393 | // 打印输入数据(仅float类型) |
| 362 | if (input[i].GetTensorDesc().GetDataType() == ge::DT_FLOAT) { | 394 | if (input[i].GetTensorDesc().GetDataType() == ge::DT_FLOAT) { |
| @@ -377,7 +409,12 @@ int main(int argc, char* argv[]) | |||
| 377 | int64_t output_shape = output[i].GetTensorDesc().GetShape().GetShapeSize(); | 409 | int64_t output_shape = output[i].GetTensorDesc().GetShape().GetShapeSize(); |
| 378 | std::cout << "this is " << i << "th output, output shape size =" << output_shape << std::endl; | 410 | std::cout << "this is " << i << "th output, output shape size =" << output_shape << std::endl; |
| 379 | uint32_t data_size = output_shape * GetDataTypeSize(output[i].GetTensorDesc().GetDataType()); | 411 | uint32_t data_size = output_shape * GetDataTypeSize(output[i].GetTensorDesc().GetDataType()); |
| 380 | - WriteDataToFile((const char*)output_file.c_str(), data_size, output_data_i); | 412 | + if (WriteDataToFile((const char*)output_file.c_str(), data_size, output_data_i) != SUCCESS) { |
| 413 | + printf("%s - ERROR - [XIR]: Write output bin %s failed\n", GetTime().c_str(), output_file.c_str()); | ||
| 414 | + delete session; | ||
| 415 | + GEFinalize(); | ||
| 416 | + return FAILED; | ||
| 417 | + } | ||
| 381 | 418 | ||
| 382 | // 打印输出数据(仅float类型) | 419 | // 打印输出数据(仅float类型) |
| 383 | if (output[i].GetTensorDesc().GetDataType() == ge::DT_FLOAT) { | 420 | if (output[i].GetTensorDesc().GetDataType() == ge::DT_FLOAT) { |
| @@ -406,12 +443,15 @@ int main(int argc, char* argv[]) | |||
| 406 | 443 | ||
| 407 | // 清理资源 | 444 | // 清理资源 |
| 408 | printf("%s - INFO - [XIR]: Start to finalize ir graph session\n", GetTime().c_str()); | 445 | printf("%s - INFO - [XIR]: Start to finalize ir graph session\n", GetTime().c_str()); |
| 446 | + delete session; | ||
| 409 | ret = ge::GEFinalize(); | 447 | ret = ge::GEFinalize(); |
| 410 | if (ret != SUCCESS) { | 448 | if (ret != SUCCESS) { |
| 411 | printf("%s - ERROR - [XIR]: Finalize ir graph session failed\n", GetTime().c_str()); | 449 | printf("%s - ERROR - [XIR]: Finalize ir graph session failed\n", GetTime().c_str()); |
| 450 | + FreeSampleBuffers(); | ||
| 412 | return FAILED; | 451 | return FAILED; |
| 413 | } | 452 | } |
| 414 | printf("%s - INFO - [XIR]: Finalize ir graph session success\n", GetTime().c_str()); | 453 | printf("%s - INFO - [XIR]: Finalize ir graph session success\n", GetTime().c_str()); |
| 415 | 454 | ||
| 455 | + FreeSampleBuffers(); | ||
| 416 | return SUCCESS; | 456 | return SUCCESS; |
| 417 | } | 457 | } |
| @@ -35,9 +35,9 @@ namespace ge { | |||
| 35 | * paddings[i][1] specifies the number of padding elements to add after x in dimension i. | 35 | * paddings[i][1] specifies the number of padding elements to add after x in dimension i. |
| 36 | * Supported format list: ["ND"]. | 36 | * Supported format list: ["ND"]. |
| 37 | * | 37 | * |
| 38 | -* @li constant_values: An optional Tensor, dtype same as "x". | 38 | +* @li constant_values: A required Tensor whose data is optional, dtype same as "x". |
| 39 | -* Used only in "constant" mode to specify the value to fill in the padded regions. | 39 | +* Used to specify the value to fill in the padded regions. |
| 40 | -* If not provided, default value is 0. \n | 40 | +* When the data is not provided, default value is 0. \n |
| 41 | 41 | ||
| 42 | * @par Outputs: | 42 | * @par Outputs: |
| 43 | * y: A Tensor of the same type as "x". | 43 | * y: A Tensor of the same type as "x". |
| @@ -20,6 +20,31 @@ namespace optiling { | |||
| 20 | 20 | ||
| 21 | static ge::graphStatus Tiling4PadV2(gert::TilingContext* context) | 21 | static ge::graphStatus Tiling4PadV2(gert::TilingContext* context) |
| 22 | { | 22 | { |
| 23 | + // paddings 为 ValueDepend 输入,数据可能不下发;在进入共享 Tiling 前拦截空数据, | ||
| 24 | + // 避免下游解引用(CODE.02/1;共享实现归属 pad_v3 责任田,此处只防护 PadV2 通路) | ||
| 25 | + auto paddingsTensor = context->GetInputTensor(1); | ||
| 26 | + OP_CHECK_NULL_WITH_CONTEXT(context, paddingsTensor); | ||
| 27 | + OP_CHECK_IF(paddingsTensor->GetShapeSize() > 0 && paddingsTensor->GetAddr() == nullptr, | ||
| 28 | + OP_LOGE(context, "paddings const data cannot be nullptr"), return ge::GRAPH_FAILED); | ||
| 29 | + | ||
| 30 | + // PadV2 复用 PadV3 的 Tiling 类,PadV3 侧 constant_values 校验被 isPadV3_ 门控, | ||
| 31 | + // 这里补齐 PadV2 的入口契约校验(README 约束#2 / proto attention / 基线 TBE 行为): | ||
| 32 | + // 1) constant_values 与 x 同 dtype(基线 TBE 显式拒绝不匹配) | ||
| 33 | + auto xDesc = context->GetInputDesc(0); | ||
| 34 | + OP_CHECK_NULL_WITH_CONTEXT(context, xDesc); | ||
| 35 | + auto cvDesc = context->GetInputDesc(2); | ||
| 36 | + OP_CHECK_NULL_WITH_CONTEXT(context, cvDesc); | ||
| 37 | + OP_CHECK_IF(xDesc->GetDataType() != cvDesc->GetDataType(), | ||
| 38 | + OP_LOGE(context, "The dtype of constant_values must be the same as the dtype of input."), | ||
| 39 | + return ge::GRAPH_FAILED); | ||
| 40 | + // 2) constant_values 必须为标量(0 维或元素数为 1;空 tensor 会被 kernel 读元素 0 越界) | ||
| 41 | + auto cvTensor = context->GetInputTensor(2); | ||
| 42 | + OP_CHECK_NULL_WITH_CONTEXT(context, cvTensor); | ||
| 43 | + OP_CHECK_IF( | ||
| 44 | + cvTensor->GetShapeSize() != 1, | ||
| 45 | + OP_LOGE(context, "constant_values must be a scalar tensor, got shape size %ld", cvTensor->GetShapeSize()), | ||
| 46 | + return ge::GRAPH_FAILED); | ||
| 47 | + | ||
| 23 | // 直接使用 PadV3 的 Tiling 类 | 48 | // 直接使用 PadV3 的 Tiling 类 |
| 24 | PadACTiling tilingObject(context); | 49 | PadACTiling tilingObject(context); |
| 25 | return tilingObject.DoTiling(); | 50 | return tilingObject.DoTiling(); |
| @@ -8,6 +8,6 @@ | |||
| 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 | 8 | ; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理 |
| 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 | 9 | ; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。 |
| 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 | 10 | ; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式 |
| 11 | -; 6)是否是AscendC算子,由 ops/build-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 | 11 | +; 6)是否是AscendC算子,由 ops/built-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定 |
| 12 | [PadV2] | 12 | [PadV2] |
| 13 | default=0 | 13 | default=0 |
| @@ -1,6 +1,6 @@ | |||
| 1 | testcase_name,network_name,op_name,input_dtypes,input_ori_shapes,output_ori_shapes,input_ori_formats,output_ori_formats,attributes,input_shapes,output_dtypes,output_shapes,input_formats,output_formats,input_data_ranges,precision_tolerances,absolute_precision,output_inplace_indexes,output_shape_unknown_indexes,is_enabled,remark,soc_series,priority,dump_file_prefix,manual_input_binaries,manual_golden_binaries | 1 | testcase_name,network_name,op_name,input_dtypes,input_ori_shapes,output_ori_shapes,input_ori_formats,output_ori_formats,attributes,input_shapes,output_dtypes,output_shapes,input_formats,output_formats,input_data_ranges,precision_tolerances,absolute_precision,output_inplace_indexes,output_shape_unknown_indexes,is_enabled,remark,soc_series,priority,dump_file_prefix,manual_input_binaries,manual_golden_binaries |
| 2 | -pad_constant_normal_45742,UNKNOWN,pad_v2,"('bool', 'int32', 'bool')","((1, 4, 151, 21, 2180),)","((2, 11, 180, 24, 2191),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[0, 1], [5, 2], [22, 7], [3, 0], [7, 4]], 'constant_values': 100}","((1, 4, 151, 21, 2180), (10,), (1,))","('bool',)","((2, 11, 180, 24, 2191),)","('ND', 'ND', 'ND')","('ND',)","((-inf, inf), (-1, 1), (-1, 32))","((0, 0),)",1e-08,(),(),True,,,0,,(),() | 2 | +pad_constant_normal_45742,UNKNOWN,pad_v2,"('bool', 'int32', 'bool')","((1, 4, 151, 21, 2180),)","((2, 11, 180, 24, 2191),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[0, 1], [5, 2], [22, 7], [3, 0], [7, 4]], 'constant_values': 100}","((1, 4, 151, 21, 2180), (10,), (1,))","('bool',)","((2, 11, 180, 24, 2191),)","('ND', 'ND', 'ND')","('ND',)","((0, 1), (-1, 1), (0, 1))","((0, 0),)",1e-08,(),(),True,,,0,,(),() |
| 3 | -pad_constant_reverse_normal_442,UNKNOWN,pad_v2,"('int32', 'int32', 'int32')","((34, 46, 3),)","((135, 59, 508),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[60, 41], [7, 6], [401, 104]], 'constant_values': 100}","((34, 46, 3), (6,), (1,))","('int32',)","((135, 59, 508),)","('ND', 'ND', 'ND')","('ND',)","((-inf, inf), (-1, 1), (-1, 32))","((0, 0),)",1e-08,(),(),True,,,0,,(),() | 3 | +pad_constant_reverse_normal_442,UNKNOWN,pad_v2,"('int32', 'int32', 'int32')","((34, 46, 3),)","((135, 59, 508),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[60, 41], [7, 6], [401, 104]], 'constant_values': 100}","((34, 46, 3), (6,), (1,))","('int32',)","((135, 59, 508),)","('ND', 'ND', 'ND')","('ND',)","((-2147483648, 2147483647), (-1, 1), (-2147483648, 2147483647))","((0, 0),)",1e-08,(),(),True,,,0,,(),() |
| 4 | -pad_constant_huge_19224,UNKNOWN,pad_v2,"('float32', 'int32', 'float32')","((2, 1, 4, 1, 1, 1, 5476),)","((2, 2, 5, 7, 5, 9, 5476),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[0, 0], [1, 0], [0, 1], [3, 3], [3, 1], [4, 4], [0, 0]], 'constant_values': 100}","((2, 1, 4, 1, 1, 1, 5476), (14,), (1,))","('float32',)","((2, 2, 5, 7, 5, 9, 5476),)","('ND', 'ND', 'ND')","('ND',)","((-inf, inf), (-1, 1), (-1, 32))","((0, 0),)",1e-08,(),(),True,,,0,,(),() | 4 | +pad_constant_huge_19224,UNKNOWN,pad_v2,"('float32', 'int32', 'float32')","((2, 1, 4, 1, 1, 1, 5476),)","((2, 2, 5, 7, 5, 9, 5476),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[0, 0], [1, 0], [0, 1], [3, 3], [3, 1], [4, 4], [0, 0]], 'constant_values': 100}","((2, 1, 4, 1, 1, 1, 5476), (14,), (1,))","('float32',)","((2, 2, 5, 7, 5, 9, 5476),)","('ND', 'ND', 'ND')","('ND',)","((-3.4e38, 3.4e38), (-1, 1), (-3.4e38, 3.4e38))","((0, 0),)",1e-08,(),(),True,,,0,,(),() |
| 5 | -pad_constant_normal_3679,UNKNOWN,pad_v2,"('float16', 'int32', 'float16')","((1, 6, 2, 132, 107),)","((4, 14, 5, 142, 117),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[3, 0], [3, 5], [1, 2], [6, 4], [1, 9]], 'constant_values': 100}","((1, 6, 2, 132, 107), (10,), (1,))","('float16',)","((4, 14, 5, 142, 117),)","('ND', 'ND', 'ND')","('ND',)","((-inf, inf), (-1, 1), (-1, 32))","((0, 0),)",1e-08,(),(),True,,,0,,(),() | 5 | +pad_constant_normal_3679,UNKNOWN,pad_v2,"('float16', 'int32', 'float16')","((1, 6, 2, 132, 107),)","((4, 14, 5, 142, 117),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[3, 0], [3, 5], [1, 2], [6, 4], [1, 9]], 'constant_values': 100}","((1, 6, 2, 132, 107), (10,), (1,))","('float16',)","((4, 14, 5, 142, 117),)","('ND', 'ND', 'ND')","('ND',)","((-65504.0, 65504.0), (-1, 1), (-65504.0, 65504.0))","((0, 0),)",1e-08,(),(),True,,,0,,(),() |
| 6 | -pad_constant_normal_30358,UNKNOWN,pad_v2,"('uint16', 'int32', 'uint16')","((1, 3, 7, 3, 17, 57, 188),)","((1, 6, 9, 3, 30, 59, 199),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[0, 0], [1, 2], [2, 0], [0, 0], [5, 8], [1, 1], [6, 5]], 'constant_values': 100}","((1, 3, 7, 3, 17, 57, 188), (14,), (1,))","('uint16',)","((1, 6, 9, 3, 30, 59, 199),)","('ND', 'ND', 'ND')","('ND',)","((-inf, inf), (-1, 1), (-1, 32))","((0, 0),)",1e-08,(),(),True,,,0,,(),() | 6 | +pad_constant_normal_30358,UNKNOWN,pad_v2,"('uint16', 'int32', 'uint16')","((1, 3, 7, 3, 17, 57, 188),)","((1, 6, 9, 3, 30, 59, 199),)","('ND', 'ND', 'ND')","('ND',)","{'paddings': [[0, 0], [1, 2], [2, 0], [0, 0], [5, 8], [1, 1], [6, 5]], 'constant_values': 100}","((1, 3, 7, 3, 17, 57, 188), (14,), (1,))","('uint16',)","((1, 6, 9, 3, 30, 59, 199),)","('ND', 'ND', 'ND')","('ND',)","((0, 65535), (-1, 1), (0, 65535))","((0, 0),)",1e-08,(),(),True,,,0,,(),() |
| @@ -16,12 +16,12 @@ | |||
| 16 | - 算子功能:沿指定维度复制输入Tensor数据,扩展输出Tensor。 | 16 | - 算子功能:沿指定维度复制输入Tensor数据,扩展输出Tensor。 |
| 17 | 17 | ||
| 18 | - 计算示例: | 18 | - 计算示例: |
| 19 | - - 输入 x = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]],shape = (2, 3, 2) | 19 | + - 输入x = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]],shape = (2, 3, 2) |
| 20 | - axis = 1,tiles = 2 | 20 | - axis = 1,tiles = 2 |
| 21 | - - 输出 y = [[[1, 2], [3, 4], [5, 6], [1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12], [7, 8], [9, 10], [11, 12]]],shape = (2, 6, 2) | 21 | + - 输出y = [[[1, 2], [3, 4], [5, 6], [1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12], [7, 8], [9, 10], [11, 12]]],shape = (2, 6, 2) |
| 22 | 22 | ||
| 23 | - 计算公式: | 23 | - 计算公式: |
| 24 | - 输出 y 的 shape 与输入 x 相同,仅 axis 维度变为 `x.shape[axis] * tiles`。 | 24 | + 输出y的shape与输入x相同,仅axis维度变为 `x.shape[axis] * tiles`。 |
| 25 | 25 | ||
| 26 | ## 参数说明 | 26 | ## 参数说明 |
| 27 | 27 | ||
| @@ -34,12 +34,12 @@ | |||
| 34 | 34 | ||
| 35 | ## 约束说明 | 35 | ## 约束说明 |
| 36 | 36 | ||
| 37 | -- axis 必须在输入Tensor的维度范围内(支持负数索引,如 axis=-1 表示最后一维)。 | 37 | +- axis必须在输入Tensor的维度范围内(支持负数索引,如axis = -1表示最后一维)。 |
| 38 | -- tiles 必须大于0。 | 38 | +- tiles必须大于0。 |
| 39 | -- 输出Tensor在 axis 维度的大小必须等于输入Tensor在 axis 维度的大小乘以 tiles。 | 39 | +- 输出Tensor在axis维度的大小必须等于输入Tensor在axis维度的大小乘以tiles。 |
| 40 | - 输入Tensor维度不超过8维。 | 40 | - 输入Tensor维度不超过8维。 |
| 41 | -- 支持标量输入(rank=0):输出 shape 为 [tiles],即输入标量值复制 tiles 份;此时 axis 不生效。 | 41 | +- 支持标量输入(rank = 0):输出shape为[tiles],即输入标量值复制tiles份;此时axis不生效。 |
| 42 | -- 输入Tensor任一维允许为 0(空 Tensor):输出对应维仍为 0,输出Tensor为空。 | 42 | +- 输入Tensor任一维允许为0(空Tensor):输出对应维仍为0,输出Tensor为空。 |
| 43 | 43 | ||
| 44 | ## 调用说明 | 44 | ## 调用说明 |
| 45 | 45 | ||