conv2d_v2 correctness gate rejects kernels more accurate than its own reference
Board: conv2d_v2, ranked shape (256, k=32, C=128, batch=1) (seed 6252). Observed on
the L4 runner; the math is GPU-independent.
Summary
The correctness gate compares a submission against an fp32 cuDNN reference at
rtol=atol=1e-3. On this shape, fp32 cuDNN itself diverges ~3.76e-2 from the fp64
ground truth, because cuDNN selects an FFT-based convolution algorithm for the large
(k=32) kernel, and FFT-domain error scales with the global output magnitude
(sigma ~ sqrt(3232128) ~ 362), not each element's local value. At the many near-zero
output elements, that puts ~1e-2 of absolute error on the reference itself - 10x over the
gate's 1e-3 tolerance.
Consequence: a submission whose output is closer to the true fp64 result than cuDNN is
still gets flagged "incorrect" at those near-zero elements, because it differs from the
dirty reference by more than 1e-3. The gate rewards matching cuDNN's error, not
correctness.
Repro (attached conv2d_v2_reference_bug_repro.py, torch-only, ~15 lines)
fp32 cuDNN reference vs fp64 truth: max abs err = 3.762e-02
Deterministic mode (cudnn.deterministic=True, use_deterministic_algorithms(True)) gives the
bit-identical 3.762e-2 - it is the algorithm choice, not nondeterminism.
Suggested fixes (any one)
- Compute the reference in fp64, cast to fp32 for the comparison (
ref_kernel runs
conv2d(x.double(), w.double()).float()). fp64 conv is slower but the reference runs
rarely; this makes "correct" mean "correct," and a genuinely accurate kernel passes.
- Loosen the tolerance on the affected large-kernel shapes to bound cuDNN's own algo error
(less principled - it bakes the reference's dirt into the spec).
- Pin cuDNN to a non-FFT algorithm for the reference (fragile across versions).
Fix (1) is cleanest and matches how the tail-entry naive kernels already pass (they happen
to track cuDNN's error; a transform-based kernel does not).
Why this matters
The v2 boards are the community's practice ground. A gate that rejects correct-but-not-
cuDNN-matching kernels silently caps the achievable score at "however accurate cuDNN is,"
which quietly excludes exactly the transform-based approaches these large-kernel shapes
reward. The standings above the eager cluster may predate a reference change; today even
cudnn.benchmark=True in a different memory layout fails the gate the same way.
(Reported as part of independent kernel-optimization work. Repro is pure cuDNN-vs-fp64 and
reveals nothing about any specific submission.)
Full repro script
# Minimal repro: conv2d_v2 correctness gate rejects kernels MORE accurate than its
# fp32 cuDNN reference, on the ranked shape (256, k=32, C=128, batch=1).
# Zero dependencies beyond torch. Runs on any L4 (or the board's own runner).
import torch
torch.backends.cudnn.allow_tf32 = False # match the board's DeterministicContext
torch.backends.cuda.matmul.allow_tf32 = False
dev = "cuda"
g = torch.Generator(device=dev); g.manual_seed(6252) # the ranked benchmark's seed
x = torch.randn(1, 128, 256, 256, device=dev, generator=g)
w = torch.randn(128, 128, 32, 32, device=dev, generator=g)
# fp64 ground truth (what "correct" actually means)
truth = torch.nn.functional.conv2d(x.double(), w.double())
# the reference the gate compares against: fp32 cuDNN (reference.py ref_kernel)
ref_fp32 = torch.nn.functional.conv2d(x, w)
err = (ref_fp32.double() - truth).abs().max().item()
print(f"fp32 cuDNN reference vs fp64 truth: max abs err = {err:.3e}")
print(f"gate tolerance is atol=rtol=1e-3; near-zero output elements carry ~{err:.1e} of")
print(f"absolute error because cuDNN picks an FFT-class algo for k=32 (error scales with")
print(f"the global output magnitude ~sqrt(131072)~362, not each element's local value).")
print(f"=> ANY implementation closer to truth than cuDNN can still exceed the 1e-3 gate")
print(f" at those near-zero elements, and is rejected as 'incorrect' - even though it")
print(f" is MORE accurate than the reference it is graded against.")
conv2d_v2 correctness gate rejects kernels more accurate than its own reference
Board: conv2d_v2, ranked shape
(256, k=32, C=128, batch=1)(seed 6252). Observed onthe L4 runner; the math is GPU-independent.
Summary
The correctness gate compares a submission against an fp32 cuDNN reference at
rtol=atol=1e-3. On this shape, fp32 cuDNN itself diverges ~3.76e-2 from the fp64ground truth, because cuDNN selects an FFT-based convolution algorithm for the large
(k=32) kernel, and FFT-domain error scales with the global output magnitude
(sigma ~ sqrt(3232128) ~ 362), not each element's local value. At the many near-zero
output elements, that puts ~1e-2 of absolute error on the reference itself - 10x over the
gate's 1e-3 tolerance.
Consequence: a submission whose output is closer to the true fp64 result than cuDNN is
still gets flagged "incorrect" at those near-zero elements, because it differs from the
dirty reference by more than 1e-3. The gate rewards matching cuDNN's error, not
correctness.
Repro (attached
conv2d_v2_reference_bug_repro.py, torch-only, ~15 lines)Deterministic mode (cudnn.deterministic=True, use_deterministic_algorithms(True)) gives the
bit-identical 3.762e-2 - it is the algorithm choice, not nondeterminism.
Suggested fixes (any one)
ref_kernelrunsconv2d(x.double(), w.double()).float()). fp64 conv is slower but the reference runsrarely; this makes "correct" mean "correct," and a genuinely accurate kernel passes.
(less principled - it bakes the reference's dirt into the spec).
Fix (1) is cleanest and matches how the tail-entry naive kernels already pass (they happen
to track cuDNN's error; a transform-based kernel does not).
Why this matters
The v2 boards are the community's practice ground. A gate that rejects correct-but-not-
cuDNN-matching kernels silently caps the achievable score at "however accurate cuDNN is,"
which quietly excludes exactly the transform-based approaches these large-kernel shapes
reward. The standings above the eager cluster may predate a reference change; today even
cudnn.benchmark=Truein a different memory layout fails the gate the same way.(Reported as part of independent kernel-optimization work. Repro is pure cuDNN-vs-fp64 and
reveals nothing about any specific submission.)
Full repro script