Module neuralops.tests.test_triton_hgrn2_scan
Comprehensive test suite for neuralops.core.triton_kernels.hgrn2_scan.
Coverage: - Numerical correctness vs PyTorch reference - Multiple dtypes: fp32, fp16, bf16 - Multiple shapes: batch, seq, dim variations - Edge cases: clipping, small/large dimensions - Fallback path & error handling - Determinism - Gradient correctness
Functions
def device()-
Expand source code
@pytest.fixture def device(): if torch.cuda.is_available(): return torch.device("cuda") return torch.device("cpu") def reference_hgrn2_scan_pytorch(f, iv, res_clip=None)-
Expand source code
def reference_hgrn2_scan_pytorch(f, iv, res_clip=None): """ Pure PyTorch sequential reference for HGRN2 selective scan. Recurrence: h_t = f_t * h_{t-1} + iv_t if res_clip: h_t = clamp(h_t, -res_clip, res_clip) """ B, L, D = f.shape f_f = f.float() iv_f = iv.float() h = torch.zeros(B, L, D, device=f.device, dtype=torch.float32) h_prev = torch.zeros(B, D, device=f.device, dtype=torch.float32) for t in range(L): ft = f_f[:, t, :] ivt = iv_f[:, t, :] ht = ft * h_prev + ivt if res_clip is not None and res_clip > 0: ht = torch.clamp(ht, -res_clip, res_clip) h[:, t, :] = ht h_prev = ht return h.to(f.dtype)Pure PyTorch sequential reference for HGRN2 selective scan.
Recurrence -----= h_t = f_t * h_{t-1} + iv_t if res_clip: h_t = clamp(h_t, -res_clip, res_clip)
def test_hgrn2_scan_triton_backward(device)-
Expand source code
@pytest.mark.skipif(not HAS_TRITON or not torch.cuda.is_available(), reason="Requires Triton and CUDA") def test_hgrn2_scan_triton_backward(device): """Verify backward gradient computation.""" B, L, D = 1, 16, 32 f = torch.sigmoid(torch.randn(B, L, D, device=device, requires_grad=True)) iv = torch.randn(B, L, D, device=device, requires_grad=True) out = hgrn2_scan_triton(f, iv, res_clip=1.0) loss = out.sum() loss.backward() assert f.grad is not None and torch.isfinite(f.grad).all() assert iv.grad is not None and torch.isfinite(iv.grad).all()Verify backward gradient computation.
def test_hgrn2_scan_triton_correctness(device, dtype, D, res_clip)-
Expand source code
@pytest.mark.skipif(not HAS_TRITON or not torch.cuda.is_available(), reason="Requires Triton and CUDA") @pytest.mark.parametrize("dtype", [torch.float32, torch.float16, torch.bfloat16]) @pytest.mark.parametrize("D", [32, 64, 128]) @pytest.mark.parametrize("res_clip", [None, 1.0]) def test_hgrn2_scan_triton_correctness(device, dtype, D, res_clip): """Verify Triton HGRN2 matches PyTorch reference on CUDA.""" B, L = 2, 16 f = torch.sigmoid(torch.randn(B, L, D, device=device, dtype=dtype)) iv = torch.randn(B, L, D, device=device, dtype=dtype) out = hgrn2_scan_triton(f, iv, res_clip=res_clip) ref = reference_hgrn2_scan_pytorch(f, iv, res_clip=res_clip) tol = 1e-2 if dtype != torch.float32 else 1e-4 assert torch.allclose(out, ref, atol=tol, rtol=tol)Verify Triton HGRN2 matches PyTorch reference on CUDA.
def test_reference_hgrn2_scan_pytorch_basic()-
Expand source code
def test_reference_hgrn2_scan_pytorch_basic(): """Verify PyTorch reference runs and outputs correct shape on CPU.""" B, L, D = 2, 16, 32 f = torch.sigmoid(torch.randn(B, L, D)) iv = torch.randn(B, L, D) out = reference_hgrn2_scan_pytorch(f, iv, res_clip=1.0) assert out.shape == (B, L, D) assert torch.isfinite(out).all()Verify PyTorch reference runs and outputs correct shape on CPU.