Skip to content

Commit 9ff9ace

Browse files
Merge pull request #1 from ryanontheinside/docs/fp8-honest-stats
Report FP8 DiT parity as the full 47-prompt distribution
2 parents eb8a2fd + 4c3c1d5 commit 9ff9ace

2 files changed

Lines changed: 20 additions & 14 deletions

File tree

optimized/tensorRT/build/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ Naive `BuilderFlag.FP16` (without the surgery) catastrophically overflows in RMS
154154

155155
### FP8 DiT (opt-in, ~1.8x)
156156

157-
`build_dit_fp8.py` extends the FP16-mixed recipe with a ModelOpt FP8 GEMM trunk: it takes the `dit_fp16mixed.onnx` plus a calibration `.npz` (real DiT inputs across the pingpong schedule) and produces `dit_fp8.onnx`: fp8 weight/activation Q/DQ on the MatMuls, the same FP32 islands re-applied (plus the conditioning front-end, which must stay FP32 or the t>=0.984 timestep features flush), and per-channel weight scales. Validated on sa3-m vs the FP16-mixed engine: worst single-step velocity cosine 0.978 (latent cosine 0.998), 8-step compounded final-latent cosine ~0.96 to 0.976 (prompt-dependent), ~11.2 ms/step (vs ~19.9), ~1.8x. Under the stochastic pingpong sampler it yields a different but comparable sample.
157+
`build_dit_fp8.py` extends the FP16-mixed recipe with a ModelOpt FP8 GEMM trunk: it takes the `dit_fp16mixed.onnx` plus a calibration `.npz` (real DiT inputs across the pingpong schedule) and produces `dit_fp8.onnx`: fp8 weight/activation Q/DQ on the MatMuls, the same FP32 islands re-applied (plus the conditioning front-end, which must stay FP32 or the t>=0.984 timestep features flush), and per-channel weight scales. Validated on sa3-m vs the FP16-mixed engine over the 47 reprompt Music prompts x 8 sigmas (L=646): worst single-step latent cosine 0.9982, 8-step compounded euler final-latent cosine mean 0.953 / median 0.957 / worst 0.873 over the 47 prompts (the compounded rollout is chaotic at the early sigmas, so judge by the distribution and by ear; decoded audio under the production pingpong sampler tracks the FP16-mixed generation at ~0.90 RMS-curve correlation), ~10.6-11.0 ms/step (vs ~18.7-19.4), ~1.8x. TRT tactic selection is nondeterministic per build; if a fresh engine benches noticeably slower, rebuild it. Under the stochastic pingpong sampler it yields a different but comparable sample.
158158

159159
First capture the calibration data from the model checkpoint with `make_calib.py` (drives the model's own pingpong `generate()` to record real DiT inputs across the sampling schedule; prompts come from the repo's own `interface/reprompt.py` Music examples, the deployment-matched reprompt format):
160160

optimized/tensorRT/build/build_dit_fp8.py

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@
1111
Background — why this is more than ``mtq.quantize(...)``:
1212
- The DiT's per-step velocity error compounds over the 8 pingpong steps. BF16
1313
fails (final-latent cos ~0.81); naive FP8 PTQ lands ~0.91. The decisive
14-
fixes, in order, take it to ~0.96 to 0.976 compounded (final-latent, prompt-
15-
dependent) and 0.978 worst single-step velocity cosine vs the FP16-mixed
16-
engine; under the stochastic pingpong sampler the result is a different but
17-
comparable sample, judged by ear:
14+
fixes, in order, take it to 0.9982 worst single-step latent cosine (n=376)
15+
and a compounded euler final-latent cosine of mean 0.953 / worst 0.873 over
16+
the 47 reprompt prompts vs the FP16-mixed engine; under the stochastic
17+
pingpong sampler the result is a different but comparable sample, judged by
18+
ear:
1819
1. ModelOpt rejects the canonical ONNX because upstream's island surgery
1920
leaves it un-toposorted, and its opset bump leaves ReduceMean's pre-18
2021
attribute-form axes. We Kahn-sort + version_convert to opset 19 first.
@@ -47,15 +48,20 @@
4748
4849
Inputs/outputs stay FP32 so the runtime can swap engines transparently.
4950
50-
Validated (sa3-m, vs the FP16-mixed engine; measured at L=646, but the recipe is
51-
shape-independent: activation scales are per-tensor and the default profile below
52-
is dynamic, so the numbers carry over):
53-
- Worst single-step velocity cosine: 0.978
54-
- Worst single-step latent cosine (x + dt*v): 0.998
55-
- 8-step compounded euler final-latent cosine: ~0.96 to 0.976 (single-prompt
56-
and prompt-dependent; the FP16-mixed engine itself scores only ~0.998 vs PT
57-
eager, so this is a guide, not a gate, and final judgement is by ear)
58-
- Step time (B=1, L=646): ~11.2 ms (FP16-mixed: ~19.9 ms) -> ~1.8x
51+
Validated (sa3-m, vs the FP16-mixed engine, over the 47 reprompt Music prompts
52+
x 8 sigmas at L=646; the recipe is shape-independent: activation scales are
53+
per-tensor and the default profile below is dynamic, so the numbers carry over):
54+
- Worst single-step latent cosine (x + dt*v, n=376): 0.9982 (mean 0.9997)
55+
- 8-step compounded euler final-latent cosine, distribution over the 47
56+
prompts: mean 0.953, median 0.957, p5 0.915, worst 0.873. The compounded
57+
rollout is chaotic at the early sigmas (an eps=1e-3 input perturbation
58+
alone compounds to ~0.967) and the FP16-mixed engine itself scores only
59+
~0.998 vs PT eager, so this is a guide, not a gate; the shipped gate is
60+
decoded audio under the production pingpong sampler, judged by ear
61+
(RMS-curve correlation ~0.90 vs the FP16-mixed engine's generation).
62+
- Step time (B=1, L=646): ~10.6-11.0 ms (FP16-mixed: ~18.7-19.4 ms) -> ~1.8x.
63+
TRT tactic selection is nondeterministic per build; if a fresh engine
64+
benches noticeably slower, rebuild it.
5965
- A true batched forward amortizes (~1.4x at B=4) once compute drops, unlike
6066
FP16-mixed (<=1.09x): fp8 frees the SM throughput the FP16 engine saturated.
6167

0 commit comments

Comments
 (0)