This is an automated email from the ASF dual-hosted git repository.

tlopex pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new ce9cfc06d6 [Test] Pin CUDA round ties-to-even on exact midpoints 
(#20274)
ce9cfc06d6 is described below

commit ce9cfc06d6d9ad03ea6da7bd22c2f94942110ec0
Author: LngelKyo <[email protected]>
AuthorDate: Tue Sep 8 12:50:40 2026 +0900

    [Test] Pin CUDA round ties-to-even on exact midpoints (#20274)
    
    `test_vectorized_intrin1` exercises `tvm.tirx.round` on the CUDA path
    with `np.random.uniform(0, 1)` inputs and `atol=1e-3`, which cannot
    distinguish ties-to-even from ties-away-from-zero: exact midpoints (0.5,
    1.5, 2.5, ...) never occur in random data. The CUDA rule lowers
    `tirx.round` to `nearbyint` / `nearbyintf`
    (src/backend/cuda/codegen/intrin_rule_cuda.cc:42-46, with the comment
    "Use nearbyint (ties-to-even) for round to match constant-folding
    semantics"), so the intended tie rule is already encoded — but nothing
    pinned it on this backend.
    
    Scope follows the review on #20252, verbatim:
    
    > Please limit this test to the regression-relevant host targets (llvm
    and c) instead of enumerating every backend. Most of these device
    targets are skipped in CI, so this list adds maintenance cost without
    guaranteeing coverage. Backend-specific lowering should be tested in the
    corresponding codegen tests when needed.
    
    A midpoint test in the CUDA codegen file is that instruction's second
    half.
    
    **What this test does**
    
    - Midpoint vector from #19368 / #20131 (`0.5, 1.5, 2.5, 3.5, -0.5, -1.5,
    -2.5, -3.5`), tiled ×16 to fill the 128 lanes `sched()` assumes (1 block
    × 32 threads × float4).
    - Zero-tolerance check against `np.round` (`rtol=0, atol=0`).
    `assert_allclose` treats -0.0 and +0.0 as equal, so a separate
    `np.signbit` assertion pins that `round(-0.5)` must produce -0.0.
    - Both compile paths (nvcc, nvrtc) are covered by the autouse fixture.
    - Scope: float32 only. fp16/bf16 `hrint` is not covered here, consistent
    with `test_vectorized_intrin1` skipping round on fp16.
    
    **Verification** (my run): RTX A6000, driver 610.43.02, CUDA 13.0.88,
    LLVM 15.0.7, TVM at eaf710e72 on 5e49b3430.
    
    - `test_round_ties_to_even[nvcc]` / `[nvrtc]`: both PASSED.
    - Negative control: reverting the CUDA rule to `round`/`roundf` makes
    both params FAIL, with 64 of 128 lanes off by one (0.5→1, 2.5→3,
    -0.5→-1, -2.5→-3). Restoring the rule turns both green again.
    - `uvx [email protected] check` and `format --check` clean.
    
    cc @tlopex @yongwww @swjng — follows up on #20252 (CI will likely need
    approval as before).
---
 tests/python/codegen/test_target_codegen_cuda.py | 28 ++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/tests/python/codegen/test_target_codegen_cuda.py 
b/tests/python/codegen/test_target_codegen_cuda.py
index c921393108..d0459f3e95 100644
--- a/tests/python/codegen/test_target_codegen_cuda.py
+++ b/tests/python/codegen/test_target_codegen_cuda.py
@@ -782,6 +782,34 @@ def test_vectorized_intrin1():
         run_test(*func, "float16")
 
 
[email protected]
[email protected](not env.has_cuda(), reason="need cuda")
+def test_round_ties_to_even():
+    # The CUDA rule lowers tirx.round to nearbyint/nearbyintf (ties-to-even,
+    # matching constant-folding semantics), so exact midpoints must round to
+    # even. np.random-based tests never produce midpoints; this pins the tie
+    # rule on both the nvcc and nvrtc compile paths (via the autouse fixture).
+    # sched() assumes 128 lanes, so the midpoints are tiled to fill it.
+    midpoints = np.array([0.5, 1.5, 2.5, 3.5, -0.5, -1.5, -2.5, -3.5], 
dtype="float32")
+    ties_to_even = np.array([0.0, 2.0, 2.0, 4.0, -0.0, -2.0, -2.0, -4.0], 
dtype="float32")
+    test_values = np.tile(midpoints, 16)  # 128 lanes, matches sched()
+    expected = np.tile(ties_to_even, 16)
+
+    f = sched(tvm.tirx.round, "float32")
+    dev = tvm.cuda(0)
+    a = tvm.runtime.tensor(test_values, dev)
+    b = tvm.runtime.tensor(np.zeros(len(test_values), dtype="float32"), dev)
+
+    def run_and_check():
+        f(a, b)
+        tvm.testing.assert_allclose(b.numpy(), expected, rtol=0, atol=0)
+        # every midpoint lane hit an exact tie: pin the sign too (round(-0.5)
+        # must produce -0.0, not +0.0)
+        assert np.signbit(b.numpy()[4::8]).all(), "negative midpoints must 
round to -0.0"
+
+    tvm.testing.run_with_gpu_lock(run_and_check)
+
+
 @pytest.mark.gpu
 @pytest.mark.skipif(not env.has_cuda(), reason="need cuda")
 def test_vectorized_intrin2(dtype="float32"):

Reply via email to