已合并
[feat] add new aten #5718
culechan创建于 14 天前
[feat] add new aten #5718
已合并
culechan创建于 14 天前
4 个文件变更+95-0
Mop_plugin/config/op_plugin_functions.yaml+6-0
@@ -4294,6 +4294,9 @@ official:
4294 acl_op: v2.14294 acl_op: v2.1
4295 op_api: v2.14295 op_api: v2.1
4296 4296 
4297+ - func: repeat_interleave.Tensor(Tensor repeats, *, SymInt? output_size=None) -> Tensor
4298+ op_api: [v2.2, newest]
4299+ 
4297 - func: replication_pad1d(Tensor self, SymInt[2] padding) -> Tensor4300 - func: replication_pad1d(Tensor self, SymInt[2] padding) -> Tensor
4298 acl_op: [v2.1, newest]4301 acl_op: [v2.1, newest]
4299 op_api: [v2.1, newest]4302 op_api: [v2.1, newest]
@@ -7700,6 +7703,9 @@ symint:
7700 acl_op: [v2.2, newest]7703 acl_op: [v2.2, newest]
7701 op_api: [v2.2, newest]7704 op_api: [v2.2, newest]
7702 7705 
7706+ - func: repeat_interleave.Tensor(Tensor repeats, *, SymInt? output_size=None) -> Tensor
7707+ op_api: [v2.2, newest]
7708+ 
7703 - func: repeat_interleave.self_int(Tensor self, SymInt repeats, int? dim=None, *, SymInt? output_size=None) -> Tensor7709 - func: repeat_interleave.self_int(Tensor self, SymInt repeats, int? dim=None, *, SymInt? output_size=None) -> Tensor
7704 acl_op: [v2.2, newest]7710 acl_op: [v2.2, newest]
7705 op_api: [v2.2, newest]7711 op_api: [v2.2, newest]
Mop_plugin/ops/opapi/RepeatInterLeaveKernelNpuOpApi.cpp+27-0
@@ -215,5 +215,32 @@ at::Tensor repeat_interleave_symint(
215 }215 }
216 return result;216 return result;
217}217}
218+ 
219+ 
220+at::Tensor repeat_interleave_symint(
221+ const at::Tensor& repeats,
222+ c10::optional<c10::SymInt> output_size)
223+{
224+ TORCH_CHECK(
225+ repeats.dim() == 1, "repeat_interleave only accept 1D vector as repeat");
226+ TORCH_CHECK(
227+ repeats.scalar_type() == at::kLong || repeats.scalar_type() == at::kInt,
228+ "repeats has to be Long or Int tensor");
229+ if (repeats.size(0) == 0) {
230+ return at::empty_like(repeats, LEGACY_CONTIGUOUS_MEMORY_FORMAT);
231+ }
232+ at::Tensor cumsum = repeats.cumsum(0);
233+ int64_t total = 0;
234+ if (output_size.has_value()) {
235+ total = output_size.value().expect_int();
236+ } else {
atomgit-bot
atomgit-botatomgit-bot14 天前

🟡 Medium Priority

变更行 226-228:当 output_size.has_value() 为 true 时,total 被直接设为 output_size.value().expect_int(),但未校验该值是否与 repeats 各元素之和一致。

对比同文件中其他重载(如行 200-208),它们通过 apply_result_tensor 中的 TORCH_CHECK(output_size_expected == output_size, ...) 进行此项校验。新增重载完全缺失此校验链。

触发条件:output_sizerepeats.sum() 不一致。例如 repeat_interleave(tensor([2,3]), output_size=10) —— 实际 repeats 和为 5,但 output_size=10。 失败模式:创建的 result tensor 大小为 output_size(10),但 aclnnRepeatInterleaveTensor 可能按实际 repeats 写入数据(5 个元素),导致 result 后半部分未初始化 / 越界写入,产生数据错乱。

建议:在 output_size.has_value() 分支内增加校验:用 cumsum[-1].item<int64_t>() 得到实际 repeats 总和,与 output_size 值做 TORCH_CHECK 比对,确保二者一致。或将 cumsum 计算移到 if 之前共享,并在 output_size 分支中校验。

likedislike
culechan
culechan
12 天前 评论:
237+ total = cumsum[-1].item<int64_t>();
atomgit-bot
atomgit-botatomgit-bot14 天前

🟡 Medium Priority

变更行 224、229:当 repeats 是空的一维张量(shape [0])时,repeats.cumsum(0) 返回空张量,紧接着 cumsum[-1] 会访问越界索引,导致运行时崩溃。

该函数无任何对 repeats.numel() == 0 的前置保护。其他重载通过 check_tensor_repeats 间接约束了形状(需要与 self 张量维度匹配),但本重载无 self 参数,完全依赖 repeats 自身形状。

触发条件:repeat_interleave_symint(torch.tensor([]), c10::nullopt)。 失败模式:cumsum[-1] 抛出 IndexError 或段错误。

建议:在函数开头增加 TORCH_CHECK(repeats.numel() > 0, ...)TORCH_CHECK(repeats.dim() == 1 && repeats.numel() > 0, ...) 校验 repeats 非空且为一维张量,与其他重载中 check_tensor_repeats 的防护水平对齐。

likedislike
culechan
culechan
12 天前 评论:
238+ TORCH_CHECK((repeats >= 0).all().to(at::kBool).item<bool>(), "repeats cannot be negative.");
239+ }
atomgit-bot
atomgit-botatomgit-bot14 天前

🟡 Medium Priority

变更行 226-231:新增的 repeat_interleave_symint 重载中,TORCH_CHECK((repeats >= 0).all().item<uint8_t>, ...) 仅位于 else 分支(即 output_size 无值时的路径)。当调用者同时传入 output_size 和负数 repeats 时,负数校验被完全跳过,repeats 中的负值不会被拦截。

对比同一文件中其他所有 repeat_interleave_symint 重载(行 97、161、197),它们的 repeats 非负校验均在 if-else 之外独立执行,无论 output_size 是否有值都会生效。此新增重载与此模式不一致,构成逻辑缺陷。

触发条件:调用 repeat_interleave.Tensor(repeats_tensor_with_negative, output_size=some_val)。 失败模式:负数 repeats 未被拒绝,aclnnRepeatInterleaveTensor 可能产生未定义行为或静默错误结果。

建议:将 TORCH_CHECK 移到 if-else 之外,使其无论 output_size 是否有值都执行。参照行 161 的模式:在参数校验阶段(即 if-else 之前)单独执行 repeats 的非负检查。

likedislike
240+ at::Tensor result = at::empty({total}, repeats.options());
241+ EXEC_NPU_CMD(aclnnRepeatInterleaveTensor, repeats, total, result);
242+ return result;
243+}
244+ 
218#endif245#endif
219}246}
Mtest/core_tests/torch_npu_OpApi_schema_all.json+3-0
@@ -4823,6 +4823,9 @@
4823 "func: repeat_interleave.self_Tensor(Tensor self, Tensor repeats, int? dim=None, *, SymInt? output_size=None) -> Tensor": {4823 "func: repeat_interleave.self_Tensor(Tensor self, Tensor repeats, int? dim=None, *, SymInt? output_size=None) -> Tensor": {
4824 "version": ["v2.3", "newest"]4824 "version": ["v2.3", "newest"]
4825 },4825 },
4826+ "func: repeat_interleave.Tensor(Tensor repeats, *, SymInt? output_size=None) -> Tensor": {
4827+ "version": ["v2.2", "newest"]
4828+ },
4826 "func: repeat_interleave.self_int(Tensor self, SymInt repeats, int? dim=None, *, SymInt? output_size=None) -> Tensor": {4829 "func: repeat_interleave.self_int(Tensor self, SymInt repeats, int? dim=None, *, SymInt? output_size=None) -> Tensor": {
4827 "version": ["v2.3", "newest"]4830 "version": ["v2.3", "newest"]
4828 },4831 },
Mtest/test_base_ops/test_repeat_interleave.py+59-0
@@ -124,6 +124,65 @@ class TestRepeatInterleave(TestCase):
124 npu_output = self.npu_op_exec_without_dim(cpu_input1.npu(), input2)124 npu_output = self.npu_op_exec_without_dim(cpu_input1.npu(), input2)
125 self.assertRtolEqual(cpu_output, npu_output)125 self.assertRtolEqual(cpu_output, npu_output)
126 126 
127+ def cpu_op_exec_repeats_only(self, repeats):
128+ output = torch.repeat_interleave(repeats)
129+ output = output.numpy()
130+ return output
131+ 
132+ def npu_op_exec_repeats_only(self, repeats):
133+ output = torch.repeat_interleave(repeats)
134+ output = output.cpu()
135+ output = output.numpy()
136+ return output
137+ 
138+ def cpu_op_exec_repeats_output_size(self, repeats, output_size):
139+ output = torch.repeat_interleave(repeats, output_size=output_size)
140+ output = output.numpy()
141+ return output
142+ 
143+ def npu_op_exec_repeats_output_size(self, repeats, output_size):
144+ output = torch.repeat_interleave(repeats, output_size=output_size)
145+ output = output.cpu()
146+ output = output.numpy()
147+ return output
148+ 
149+ def test_repeat_interleave_repeats_tensor_int64(self):
150+ repeats = torch.tensor([2, 3, 1, 4], dtype=torch.int64)
151+ cpu_output = self.cpu_op_exec_repeats_only(repeats)
152+ npu_output = self.npu_op_exec_repeats_only(repeats.npu())
153+ self.assertRtolEqual(cpu_output, npu_output)
154+ 
155+ def test_repeat_interleave_repeats_tensor_int32(self):
156+ repeats = torch.tensor([2, 3, 1, 4], dtype=torch.int32)
157+ cpu_output = self.cpu_op_exec_repeats_only(repeats)
158+ npu_output = self.npu_op_exec_repeats_only(repeats.npu())
159+ self.assertRtolEqual(cpu_output, npu_output)
160+ 
161+ def test_repeat_interleave_repeats_tensor_with_output_size(self):
162+ repeats = torch.tensor([2, 3, 1, 4], dtype=torch.int64)
163+ output_size = 10
164+ cpu_output = self.cpu_op_exec_repeats_output_size(repeats, output_size)
165+ npu_output = self.npu_op_exec_repeats_output_size(repeats.npu(), output_size)
166+ self.assertRtolEqual(cpu_output, npu_output)
167+ 
168+ def test_repeat_interleave_repeats_tensor_large(self):
169+ repeats = torch.randint(1, 5, (100,), dtype=torch.int64)
170+ cpu_output = self.cpu_op_exec_repeats_only(repeats)
171+ npu_output = self.npu_op_exec_repeats_only(repeats.npu())
172+ self.assertRtolEqual(cpu_output, npu_output)
173+ 
174+ def test_repeat_interleave_repeats_tensor_single_element(self):
175+ repeats = torch.tensor([5], dtype=torch.int64)
176+ cpu_output = self.cpu_op_exec_repeats_only(repeats)
177+ npu_output = self.npu_op_exec_repeats_only(repeats.npu())
178+ self.assertRtolEqual(cpu_output, npu_output)
179+ 
180+ def test_repeat_interleave_repeats_tensor_empty(self):
181+ repeats = torch.tensor([], dtype=torch.int64)
182+ cpu_output = self.cpu_op_exec_repeats_only(repeats)
183+ npu_output = self.npu_op_exec_repeats_only(repeats.npu())
184+ self.assertRtolEqual(cpu_output, npu_output)
185+ 
127 186 
128if __name__ == '__main__':187if __name__ == '__main__':
129 run_tests()188 run_tests()