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
tan_xinAdd on 22 days ago
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 
236gradOutput的最后一维在不同类型下的大小需满足如下约束:236gradOutput的最后一维在不同类型下的大小需满足如下约束:
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 indexes57 // 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 indexes59 // 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=013+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=013+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=013+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 
21def _numpy_bfloat16():25def _numpy_bfloat16():
@@ -157,10 +161,79 @@ def circular_pad_grad_golden(x, paddings, **kwargs):
157 return grad161 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+ 
160class CircularPadGradTestSpec:203class 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 ```text19 ```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或INT6493 - 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 >= 0100 - 负填充(slice)时,输出shape = x.shape[d] + left + right >= 0
97 101 
984. **paddings参数约束**1024. **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+ 
159int32_t GenDataFloat32(vector<int64_t> shapes, Tensor& input_tensor, TensorDesc& input_tensor_desc)163int32_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+ 
215int32_t WriteDataToFile(string bin_file, uint64_t data_size, uint8_t* inputData)237int32_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 // 添加输出y289 // 添加输出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. \n40+* 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 
21static ge::graphStatus Tiling4PadV2(gert::TilingContext* context)21static 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]
13default=013default=0
@@ -1,6 +1,6 @@
1testcase_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_binaries1testcase_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 = 220 - 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