tensorRT: fix verify_fp8_rope's CHECK 3, which failed on the engine it validates - #88
Merged
Conversation
…t validates
CHECK 3 reported False for the shipped fp8 engine on BOTH architectures, so the
documented identity check for that tier has never actually passed. Two separate causes,
both about what this metadata can tell you.
Its condition was `len(rope_fp32) > 0 and prec_any["FP32"] > 100`.
The ">100 FP32 layers" clause describes the fp32-TRUNK recipe. The shipped engine BAKES
RoPE's cos/sin as fp32 constants, so there is no fp32 trunk — only the two runtime
Fourier chains stay fp32, which is 6 FP32 layers on sm_120 and 16 on sm_90. Neither will
ever exceed 100.
The other clause tried to prove an internal fp32 island from per-layer dtypes, but those
are the dtypes at the FUSED BLOB BOUNDARY and Myelin fuses boundaries differently per
arch. Same ONNX, same recipe, same measured fidelity:
sm_120 __myl_MaxMinDivReshMulSinCastCosCastConc I/O ['Float','BFloat16']
sm_90 __myl_CastMaxMinDivReshMulCosSinCastCastConc I/O ['BFloat16','BFloat16']
sm_90 absorbed the cast into the blob, so its boundary reads BF16. Opposite verdicts
from a check that cannot see inside either blob. "Is the island fp32 internally" is not
decidable from this metadata, so the check no longer pretends it is — the boundary
dtypes are still printed, labelled informational.
CHECK 3 now asserts what IS decidable and does matter: RoPE must be BAKED, i.e. no
runtime cos/sin beyond the two Fourier chains (timestep_features, seconds_total), plus
some fp32 surviving. If the bake silently failed, RoPE would be computed at runtime in
reduced precision and drift at long sequence — the exact bug this recipe exists to
prevent. Fidelity belongs to a numerical test, and the check now says so: sweep
velocity-cos vs the fp32 engine across t, because calibration and RoPE damage both show
up near t=1.0 and are invisible mid-schedule.
Also added the diagnostic whose absence cost me the most time: an engine built without
ProfilingVerbosity.DETAILED serializes layer names only, the inspector returns strings,
and all three checks report False — indistinguishable from "fp8 did not fire". The tool
now detects that and says to rebuild with DETAILED, noting that verbosity is
metadata-only (measured: identical velocity-cos, speed within 0.7%) so the twin is a
valid stand-in for the shipped engine.
Verified: True/True/True on DETAILED builds of both arches, with identical counts
(176/181 fp8 GEMMs, 96 BF16 fused MHA, 2 cos/sin layers). Still False on a names-only
engine, which is correct — unverifiable is not the same as verified.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found while validating the fp8 medium DiT for sm_120:
verify_fp8_rope.pyreportsCHECK3=Falsefor the shipped fp8 engine on both architectures, so the documentedidentity check for that tier has never passed.
Why it failed
The condition was
len(rope_fp32) > 0 and prec_any["FP32"] > 100.">100 FP32 layers" describes the fp32-trunk recipe. The shipped engine bakes RoPE's
cos/sin as fp32 constants, so there is no fp32 trunk — only the two runtime Fourier chains
stay fp32. That is 6 FP32 layers on sm_120 and 16 on sm_90; neither can exceed 100.
The other clause tried to prove an internal fp32 island from per-layer dtypes, but
those are dtypes at the fused blob boundary, and Myelin fuses boundaries differently per
arch. Same ONNX, same recipe, same measured fidelity:
sm_90 absorbed the cast into the blob so its boundary reads BF16 — opposite verdicts from
a check that cannot see inside either blob. Whether the island is fp32 internally is not
decidable from this metadata, so CHECK 3 stops pretending it is. The boundary dtypes are
still printed, explicitly labelled informational.
What it checks now
RoPE must be baked: no runtime cos/sin beyond the two Fourier chains
(
timestep_features,seconds_total), plus some fp32 surviving. That is arch-independentand it catches the failure that matters — a silently failed bake means RoPE is computed at
runtime in reduced precision and drifts at long sequence, which is the bug the recipe
exists to prevent.
Fidelity belongs to a numerical test, and the check now says so: sweep velocity-cos vs the
fp32 engine across
t. Calibration damage and RoPE damage both concentrate neart=1.0and are invisible mid-schedule — a spot check at
t=0.7cannot tell a calibrated enginefrom an uncalibrated one.
Also: the diagnostic whose absence cost the most time
An engine built without
ProfilingVerbosity.DETAILEDserializes layer names only. Theinspector returns a list of strings, every per-layer lookup finds nothing, and all three
checks report False — indistinguishable from "fp8 did not fire".
build_from_onnx.pyneversets that flag, so this is the default experience for every engine in the repo.
The tool now detects it and says to rebuild with DETAILED, noting that verbosity is
metadata-only so the twin is a valid stand-in for the shipped engine. Measured on sm_120:
DETAILED twin vs shipping engine gives identical velocity-cos and speed within 0.7%.
Verification
Still False on a names-only engine — unverifiable is not the same as verified.
🤖 Generated with Claude Code