Numeric tweaks to fp8 - #2731
Conversation
stack-info: PR: #2731, branch: drisspg/stack/49
019817b to
16fe0cd
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 16fe0cd0db
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
0.75 is what I used here and it works well: vllm-project#166 |
|
@MatthewBonanni hey thanks for pinging, I did a bunch of tests and came to a slightly different conclusion.. although I think we can re-assess. I am working on a fwd config like system and honestly this feels like it should be user overridable in the limit |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 16fe0cd0db
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
stack-info: PR: #2731, branch: drisspg/stack/49
16fe0cd to
896ea75
Compare
stack-info: PR: #2731, branch: drisspg/stack/49
896ea75 to
0272b9c
Compare
stack-info: PR: #2731, branch: drisspg/stack/49
0272b9c to
c589077
Compare
stack-info: PR: Dao-AILab#2731, branch: drisspg/stack/49 (cherry picked from commit 849f660) Signed-off-by: StevenWang-CY <stevenwang0805@outlook.com>
Numeric tweaks to fp8 rescale and offset
Addressing: #2577
This however has some tradeoffs ill show. And this is choice is not yet finalized;
Summary
The summary in that issue is pretty much spot on and I agree with its fix although there is some interesting perf/ numeric trade offs, and fundamentally the optimal choice is data dependent so we might wanna think about exposing this somehow.
TLDR: With
offset=8andrescale_threshold=4, the max intermediate value in the firstPblock is2^8 = 256. A later block can have an unshifted max up to 3.999 log2 units above the tracked max. Because this increase is below the threshold, we keep the oldMand skip rescaling the accumulator. The second block's max intermediatePvalue can then approach2^(8+4) = 4096.This exceeds E4M3's max value of 448. The denominator
l_iis accumulated in FP32, butPis cast to E4M3 beforeP @ V, causing these large values to saturate. The denominator includes the original values while the numerator includes only their clipped contributions. Final normalization therefore can destroy these values that should contribute to the outputlets say we set rescale threshold to zero, then any increase in the block max also updates
M. The previous accumulator andl_iare rescaled byalpha = 2^(M_old - M_new), and the new block is evaluated relative toM_new. Its max intermediatePvalue is therefore2^8 = 256, rather than 4096.The current Pr uses a threshold of
0.75; it allows the maximum to reach2^8.75 ≈ 431, which remains below 448, while still avoiding some accumulator rescales, but there are many ways to accomplish the same affectPerf Numeric Summary
-- agent notes --
Pareto frontier
The full confirmation supports
max_offset=8, rescale_threshold=0as the best global policy measured. Relative to upstream(4,4):Lower is better. Threshold zero produced the stable prefill improvement. Offsets 6–8 had no reproducible performance ordering in the focused recheck, so offset 8 is preferred for its wider retained probability-tail range and slightly better aggregate prefill numerics. The tradeoff is roughly 1% slower forced-one-split decode; production auto-SplitKV decode remained neutral.
Why
(8, 0)vs(8, 0.75)0.75does genuinely help decode: it skips accumulator corrections when the running maximum increases by less than the threshold. Relative to(8,0),(8,0.75)was 0.12% faster time-weighted across the broad 72-case auto-SplitKV decode set and 0.61% faster across the 72 forced-one-split cases. In a focused two-case long-context recheck, the gains were larger—1.67% and 4.26%, respectively—showing that correction cost can be exposed in long unsplit decode.Threshold zero, however, is a distinct compile-time specialization that removes the positive-threshold compare/select sequence. A codegen isolation test compared
0with1e-6: their BF16 outputs matched bit-for-bit in 8/8 cases, but1e-6was 7.66% slower time-weighted for prefill.0.75recovered some work by skipping real corrections, but remained 6.24% slower than zero for prefill. It also had slightly worse aggregate numerics than zero.I am going to stick with (8, 0) for now but int eh future this should maybe be user configurable ..
Methodology
Q=1,SK={129,512,2048,8192}, both auto-SplitKV and forced one split. Paged causal prefill usedQ=K,S={512,2048,4096,8192}.Full 2D discovery heatmaps
Green is better than upstream
(4,4). Unsafe pairs are retained as diagnostic controls and show the expected rapid saturation.E5M2 follow-up
I repeated the performance/numerics sweep with the captured inputs quantized to E5M2. This supports retaining
max_offset=8and changing E5M2 fromrescale_threshold=4torescale_threshold=0. Relative to inherited(8,4):(8,4)Threshold zero again removes the positive-threshold compare/select path and improves prefill while remaining slightly faster for production auto-SplitKV decode. A focused 8K forced-one-split decode recheck exposed the path-specific downside more clearly:
(8,0)was about 3.1% slower than(8,4)there.E5M2's extra exponent range is still being used at offset 8: its effective probability floor is
2^-24, versus2^-17for E4M3 at the same offset. Threshold-zero offsets 8, 12, and 15 produced essentially identical numerics, so spending more saturation headroom on a larger offset did not help. The grid did not test offsets below 8; this supports retaining the existing offset, not claiming that 8 is the global E5M2 optimum for every context length.E5M2 methodology
Full E5M2 2D discovery heatmaps