Skip to content

test(st): right-size too-tight golden tolerances across s-tests (bf16/fp16/fp32-K-split)#1945

Merged
Hzfengsy merged 3 commits into
hw-native-sys:mainfrom
tonibohnlein:fix/batch-softmax-prepare-bf16-tolerance
Jul 6, 2026
Merged

test(st): right-size too-tight golden tolerances across s-tests (bf16/fp16/fp32-K-split)#1945
Hzfengsy merged 3 commits into
hw-native-sys:mainfrom
tonibohnlein:fix/batch-softmax-prepare-bf16-tolerance

Conversation

@tonibohnlein

@tonibohnlein tonibohnlein commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Several device s-tests validate reduced-precision compute against a golden with a tolerance tighter than one ULP of the precision the kernel actually computes in — most at the default rtol=atol=1e-5, some at a bf16-insufficient 1e-3. That guarantees intermittent single-element flakes whenever a value lands on a rounding boundary (the device's hardware exp/sqrt/matmul-reduction rounds differently than torch). This PR right-sizes each to admit ≥ 1 ULP of its precision.

This started from batch_softmax_prepare (bf16 softmax at 1e-5) and, after an audit of tests/st/runtime/, was extended to the rest of the same flake class — two of which have since flaked live in CI (tensor_batch_matmul fp32 K-split; tile_sqrt_fp16).

Tolerance policy (admit ≥ 1 ULP of the compute precision)

class rtol / atol rationale
bf16 arithmetic / output 1.6e-2 / 1e-3 (softmax) · 2e-2 / 1e-3 (attention) bf16 ε = 2⁻⁷ ≈ 7.8e-3; one ULP up to 2⁻⁸ ≈ 3.9e-3. 1.6e-2 = PyTorch bf16 default; 2e-2 matches existing bf16 attention s-tests
fp16 transcendental 2e-3 / 2e-3 fp16 sqrt HW Newton approx differs from torch.sqrt by ~1–2 fp16 ULP (max ULP near 1 is 2⁻¹⁰ ≈ 9.8e-4). 2e-3 clears the observed flake (2⁻¹¹ ≈ 4.9e-4) with ~8× margin — 1e-3 gave only ~1 ULP, too thin
fp32 K-split matmul 1e-4 / 1e-4 device K-reduction order ≠ single-pass torch golden → ~K·eps_fp32 ≈ 1.5e-5 at K=128 (larger for cancellation-heavy elements). Same class the AutoL0 matmul s-tests already loosen

Tests fixed

  • bf16batch_softmax_prepare (1.6e-2); test_paged_attention_multi_config::SoftmaxPrepare (+ its PTOAS subclass, 1.6e-2); test_batch_paged_attention::BatchPagedAttention full attention (2e-2 — BF16 QK/PV matmuls dominate; its softmax pij intermediate is FP16); test_qwen3_decode_scope3_mixed (2e-2). Tolerance sets guarded by if kwargs.get("config") is None so a caller-supplied config is respected.
  • fp16test_unary_math::TileSqrtTestCase fp16 sqrt (set in _UnaryMathBase.__init__ for dtype==FP16, so it also covers any future fp16 sin/cos).
  • fp32 K-splittest_mat_slice_to_left; all 5 test_tensor_batch_matmul fp32 batch-matmul cases.

Each is a one-line tolerance edit (self.config.rtol/atol or the RunConfig(...) literal). No kernel or codegen change.

Deliberately not changed (audit found these safe)

Pure data-movement bf16/fp16 outputs (scatter/gather/copy/pad/reshape/transpose) are device-exact; device-order-matched goldens (e.g. test_col_reduction replicates the fp16 reduction tree); constant/integer-input matmuls (bf16-exact products); and ops already appropriately loosened. Two fp16 elementwise cases (test_vector_misc muls / col_expand_add) are borderline — a single fp16 mul/add is normally bit-exact — so they're left as-is pending an actual flake, to avoid loosening genuinely-exact ops.

Why the earlier reviewed part changed

The batch_softmax_prepare value was corrected from 1e-3 up to 1.6e-2 after review (a 1e-3 threshold at 0.5 is 1.5e-3, below one bf16 ULP of 3.9e-3). The same reasoning is applied consistently across the bf16 tests here.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the test configuration in test_batch_paged_attention.py by adjusting the absolute and relative tolerance (atol and rtol) to 1e-3 for BF16-precision. This change addresses intermittent test flakiness caused by hardware approximation differences in BF16 calculations. There are no review comments, and I have no additional feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7cd7f45a59

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +246 to +247
self.config.atol = 1e-3
self.config.rtol = 1e-3

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use a tolerance that covers a BF16 ULP

These tolerances still do not cover the BF16 one-ULP mismatch the comment is trying to admit. If a pij_batch value, or a lij_batch summand, around 0.5 lands on opposite sides of a BF16 rounding boundary, the actual/expected difference is 2^-8 ≈ 3.9e-3, while torch.allclose with rtol=atol=1e-3 only allows about 1.5e-3 for a 0.5 value. That leaves the same hardware-exp-vs-torch-exp flake in place for different random inputs; use a BF16-scale tolerance or per-output tolerance large enough for at least one BF16 ULP.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — addressed in 0d711ec9.

You're right that rtol=atol=1e-3 doesn't cover a full BF16 ULP for values near 0.5: a summand/pij_batch element in [0.5, 1) has ULP 2^-8 ≈ 3.9e-3, while 1e-3 only admits 1e-3 + 1e-3·0.5 = 1.5e-3 there — so the hardware-exp-vs-torch-exp flake would survive for different random inputs.

Fix: rtol now covers ≥ one BF16 ULP relative everywhere. BF16 eps = 2^-7 ≈ 7.8e-3 (max relative ULP, at the low end of each binade), so I set rtol=1.6e-2 (PyTorch's bf16 assert_close default, ~2-ULP margin) with atol=1e-3 for near-zero summands. At the 0.5 worst case the threshold is now 1e-3 + 1.6e-2·0.5 = 9e-3 > 3.9e-3 (covers even 2 ULP). The comment and commit message were updated to reflect the ULP analysis.

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This change updates a single test case's numerical comparison tolerances. BatchSoftmaxPrepareTestCase.__init__ now sets atol and rtol to 1e-3, accompanied by comments explaining BF16/device exp rounding-related flakiness.

Changes

Test tolerance adjustment

Layer / File(s) Summary
Adjust softmax test tolerances
tests/st/runtime/framework_and_models/test_batch_paged_attention.py
Sets self.config.atol and self.config.rtol to 1e-3 in BatchSoftmaxPrepareTestCase.__init__, with comments explaining BF16/device exp rounding causes ~1-2 ULP differences vs. PyTorch golden.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Poem

A rabbit checks the softmax math so fine,
BF16 wobbles, just a hair off-line.
With looser tolerance, tests now pass with glee,
No more flaky failures troubling me!
Hop, hop, hooray, the CI's calm and free 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: loosening overly tight tolerances across several s-tests.
Description check ✅ Passed The description is directly related and accurately explains the tolerance adjustments and rationale.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…sion

pij_batch is a BF16 output and lij is a row_sum of BF16-quantized exp
values (exp -> cast BF16 -> FP32 -> row_sum), but the test used the
default rtol=atol=1e-5. The device's hardware exp is a ~1-2 ULP
approximation, so an exp value near a BF16 rounding boundary rounds to a
different BF16 than the torch.exp golden -- a full one-ULP mismatch on
that element (observed on a2a3: 1/32 elements, diff = exactly 2^-10).

BF16 has 8 significand bits, so eps = 2^-7 ~= 7.8e-3 and one ULP is up to
2^-8 ~= 3.9e-3 absolute near 0.5. A tolerance that admits this flake must
allow >= one BF16 ULP relative, so set rtol=1.6e-2 (PyTorch's bf16
assert_close default, ~2 ULP margin) + atol=1e-3 -- e.g. at 0.5 the
threshold is 9e-3 > 3.9e-3. The previous 1e-5 (and an intermediate 1e-3)
were too tight to cover a single BF16 ULP.
@tonibohnlein tonibohnlein force-pushed the fix/batch-softmax-prepare-bf16-tolerance branch from 7cd7f45 to 0d711ec Compare July 3, 2026 13:00
…-K-split)

Companion to the batch_softmax_prepare fix: an audit of tests/st/runtime/
found the same too-tight-golden-tolerance flake class in other kernels that
validate reduced-precision compute against the default rtol=atol=1e-5 (or a
bf16-insufficient 1e-3). Right-size each to admit >= one ULP of the precision
it actually computes in:

- fp16 transcendentals (test_unary_math TileSqrtTestCase, fp16 sqrt): the HW
  Newton approx differs from torch.sqrt by ~1 fp16 ULP -> rtol=atol=1e-3.
- fp32 K-split matmuls (test_mat_slice_to_left, test_tensor_batch_matmul, all
  5 batch cases): device K-reduction order differs from the single-pass torch
  golden, drifting ~K*eps_fp32 (~1.5e-5 at K=128) -> rtol=atol=1e-4 (AutoL0).
- bf16 softmax/attention (test_paged_attention_multi_config SoftmaxPrepare,
  test_batch_paged_attention full attention, test_qwen3_decode_scope3_mixed):
  bf16 exp/matmul output at rtol=1e-3 is below one bf16 ULP (eps_bf16=2^-7) ->
  rtol 1.6e-2 (softmax-prepare) / 2e-2 (attention), matching existing bf16 s-tests.

All one-line tolerance edits; no kernel/codegen change. Surfaced by CI flakes
on tensor_batch_matmul (fp32 K-split) and tile_sqrt_fp16.
@tonibohnlein tonibohnlein changed the title test(st): loosen batch_softmax_prepare golden tolerance to bf16 precision test(st): right-size too-tight golden tolerances across s-tests (bf16/fp16/fp32-K-split) Jul 3, 2026
- fp16 transcendental (test_unary_math): bump rtol=atol 1e-3 -> 2e-3. 1e-3 gave
  only ~1 fp16 ULP of margin, so a full-ULP HW sqrt error plus golden rounding at
  a binade bottom could still flake. Fix the ULP comment (max ULP near 1 is
  2^-10 ~ 9.8e-4, not 2^-11) and pin the observed CI flake (2^-11 ~ 4.9e-4).
- BatchPagedAttention (full attention): the softmax pij intermediate is FP16
  (the assembled program's pij_b = pl.FP16; golden casts through torch.float16),
  not BF16 -- fix the comment. rtol=2e-2 stays, justified by the BF16 QK/PV
  matmul reductions (bf16 ULP > fp16 pij's).
- Override discipline: guard the BatchSoftmaxPrepare / BatchPagedAttention /
  multi_config SoftmaxPrepare tolerance sets with `if kwargs.get("config") is
  None` so a caller-supplied (e.g. stricter) config is respected, matching the
  matmul/sqrt cases.
- Pin the observed max diff on the fp32 K-split matmul comment (1.685e-5).

@Hzfengsy Hzfengsy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test tolerance right-sizing looks sound; the BF16-ULP tolerance concern from the automated reviewer was addressed. LGTM.

@Hzfengsy Hzfengsy merged commit 7eac282 into hw-native-sys:main Jul 6, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants