已合并
fix(triton_experimental): propagate NaN in min/max reductions #44773
fix(triton_experimental): propagate NaN in min/max reductions #44773
已合并
创建于 19 天前
3 个文件变更+44-4
@@ -4,9 +4,15 @@
4from unittest import mock4from unittest import mock
5 5 
6import sympy6import sympy
7+import torch
7from torch._inductor.codegen.triton import IndexingOptions, TritonKernel8from torch._inductor.codegen.triton import IndexingOptions, TritonKernel
8from torch._inductor.fx_passes.control_dependencies import control_deps9from torch._inductor.fx_passes.control_dependencies import control_deps
9-from torch.testing._internal.common_utils import TestCase, run_tests10+from torch.testing._internal.common_utils import (
11+ TestCase,
12+ instantiate_parametrized_tests,
13+ parametrize,
14+ run_tests,
15+)
10from torch.utils._ordered_set import OrderedSet16from torch.utils._ordered_set import OrderedSet
11 17 
12from torch_npu._inductor.triton_experimental import lowering as experimental_lowering18from torch_npu._inductor.triton_experimental import lowering as experimental_lowering
@@ -14,6 +20,7 @@ from torch_npu._inductor.triton_experimental import lowering_override_list
14from torch_npu._inductor.triton_experimental.codegen import triton as npu_triton_codegen20from torch_npu._inductor.triton_experimental.codegen import triton as npu_triton_codegen
15 21 
16 22 
23+@instantiate_parametrized_tests
17class TestTritonExperimentalRegressions(TestCase):24class TestTritonExperimentalRegressions(TestCase):
18 def test_control_deps_is_not_replaced_with_fallback(self):25 def test_control_deps_is_not_replaced_with_fallback(self):
19 self.assertIn(control_deps, lowering_override_list.KEEP_UPSTREAM_LOWERING)26 self.assertIn(control_deps, lowering_override_list.KEEP_UPSTREAM_LOWERING)
@@ -86,5 +93,32 @@ class TestTritonExperimentalRegressions(TestCase):
86 self.assertEqual(result.expand_str, "[1, 1]")93 self.assertEqual(result.expand_str, "[1, 1]")
87 self.assertEqual(result.expand_shape, (1, 1))94 self.assertEqual(result.expand_shape, (1, 1))
88 95 
96+ @parametrize("op_name", ["amin", "amax", "min", "max"])
97+ @parametrize("dim", [-1, 1])
98+ def test_min_max_reductions_propagate_nan(self, op_name, dim):
99+ # Regression: split reduction's accumulate loop used bare tl.minimum/
100+ # tl.maximum, which drops NaN on Ascend, so compiled min/max returned
101+ # non-NaN where eager does. The fix adds tl.PropagateNan.ALL.
102+ x = torch.randn(8, 64, 1024, device="npu") * 2000
103+ x[3, 5, :] = float("nan")
104+ 
105+ def reduce_values(t):
106+ # torch.min/max(dim=) return (values, indices); amin/amax return a
107+ # tensor directly. Normalize to values-only so [0] never slices a
108+ # data row.
109+ out = getattr(torch, op_name)(t, dim=dim)
110+ return out[0] if isinstance(out, tuple) else out
111+ 
112+ eager_out = reduce_values(x)
113+ 
114+ compiled = torch.compile(
115+ reduce_values,
116+ options={"npu_backend": "triton_experimental"},
117+ )
118+ compiled_out = compiled(x)
119+ 
120+ self.assertEqual(eager_out, compiled_out)
121+ self.assertTrue(bool(compiled_out.isnan().any()))
122+ 
89if __name__ == "__main__":123if __name__ == "__main__":
90 run_tests()124 run_tests()
@@ -1371,11 +1371,11 @@ class NPUTritonKernelOverrides(TritonKernelOverrides):
1371 1371 
H
Hhtchu18 天前

bugfix建议同步新增ut用例看护,pr描述中需要贴用例执行结果

likedislike
伦
16 天前 评论:
1372 @staticmethod1372 @staticmethod
1373 def minimum(a, b):1373 def minimum(a, b):
1374- return f"tl.minimum({a}, {b})"1374+ return f"tl.minimum({a}, {b}, tl.PropagateNan.ALL)"
1375 1375 
1376 @staticmethod1376 @staticmethod
1377 def maximum(a, b):1377 def maximum(a, b):
1378- return f"tl.maximum({a}, {b})"1378+ return f"tl.maximum({a}, {b}, tl.PropagateNan.ALL)"
1379 1379 
1380 @staticmethod1380 @staticmethod
1381 def to_dtype(x, dtype: torch.dtype, src_dtype=None, use_compute_types=True):1381 def to_dtype(x, dtype: torch.dtype, src_dtype=None, use_compute_types=True):
@@ -16,6 +16,7 @@
16 16 
17import triton17import triton
18import triton.language as tl18import triton.language as tl
19+from triton.language import core
19from torch._inductor.runtime import triton_helpers20from torch._inductor.runtime import triton_helpers
20 21 
21try:22try:
@@ -30,9 +31,14 @@ def max2(a, dim):
30 return tl.max(a, dim, propagate_nan=True)31 return tl.max(a, dim, propagate_nan=True)
31 32 
32 33 
34+@triton.jit
35+def _min_prop_nan(a, b):
36+ return core.minimum(a, b, propagate_nan=core.PropagateNan.ALL)
37+ 
38+ 
33@triton.jit39@triton.jit
34def min2(a, dim):40def min2(a, dim):
35- return tl.min(a, dim, propagate_nan=True)41+ return tl.reduce(a, dim, _min_prop_nan)
36 42 
37 43 
38triton_helpers.max2 = max244triton_helpers.max2 = max2