[NVFP4 4over6] Add the dense four-over-six linear converter - #13
Draft
wolfcomos wants to merge 1 commit into
Draft
[NVFP4 4over6] Add the dense four-over-six linear converter#13wolfcomos wants to merge 1 commit into
wolfcomos wants to merge 1 commit into
Conversation
This was referenced Aug 30, 2026
wolfcomos
force-pushed
the
4over6/titan1-dense
branch
from
August 30, 2026 11:16
04ce11d to
7652f2d
Compare
Add NVFP4FourOverSixLinear and a recipe selector on NVFP4LinearConverter, wiring TorchAO's four-over-six training prototype (torchao.prototype.moe_training.nvfp4_training.four_over_six) into the existing converter. Four-over-six encodes every FP4 block twice (the standard map-to-6 scale and a 1.5x-expanded map-to-4 scale) and keeps the candidate with the lower dequantization error; no RHT and no stochastic rounding, targeting RL and post-training. Callers pick a quantization recipe, not a converter class, so the recipe lives on NVFP4LinearConverter: recipe="default" keeps torchao's NVFP4 recipe (random Hadamard transform + stochastic rounding, stateful per-rank buffers) and recipe="four_over_six" selects the stateless adaptive block-scale recipe. The two module implementations stay separate -- the upstream NVFP4Linear hard-inherits torchao's stateful RHT/SR module (sr_seed / rht_sign_vector buffers), which four-over-six rejects. The five four-over-six knobs (err_mode, e4m3_scale_bound, row_scaled_activation, backward_override, weight_block) are read only under recipe="four_over_six"; a non-default value under recipe="default" raises one ValueError naming every offending knob, so a mis-paired recipe fails at converter build instead of being silently ignored. Knob combinations are validated when the config tree is built via _validate_four_over_six_knobs, per converter convention, so a bad recipe fails at config time instead of on the first forward. Also add the llama3_debugmodel_nvfp4_four_over_six debug recipe, a Four-over-six subsection in the NVFP4 doc, and CPU unit tests for knob validation, converter targeting, and the recipe-surface rejections. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
wolfcomos
force-pushed
the
4over6/titan1-dense
branch
from
August 31, 2026 02:01
7652f2d to
75ecab9
Compare
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.
Stack (emulated ghstack, oldest at bottom):
Companion torchao PR providing
torchao.prototype.moe_training.nvfp4_training.four_over_six: wolfcomos/ao#12.Summary
Adds
NVFP4FourOverSixLinearand arecipeselector on the existingNVFP4LinearConverter, wiring TorchAO's NVFP4 four-over-six training prototype (torchao.prototype.moe_training.nvfp4_training.four_over_six) into the quantization converter registry. Four-over-six encodes every 16-value FP4 block twice — the standard map-to-6 block scale and a 1.5x-expanded map-to-4 scale — and stores the candidate with the lower dequantization error. The recipe uses no random Hadamard transform and no stochastic rounding; it targets RL and post-training, where TransformerEngine ships the same recipe (NVTE_NVFP4_4OVER6=1).Also included:
_validate_four_over_six_knobs(config-time knob validation shared with the follow-up grouped-experts converter), thellama3_debugmodel_nvfp4_four_over_sixdebug recipe, a "Four-over-six Recipe" subsection intorchtitan/components/quantization/nvfp4.md, and CPU unit tests.Design notes
NVFP4LinearConverterwith arecipeselector, per review feedback (an earlier revision shipped a siblingNVFP4FourOverSixLinearConverterclass): callers pick a quantization recipe, not a converter class, so the converter takesrecipe="default"(torchao's stock NVFP4 recipe: random Hadamard transform + stochastic rounding) orrecipe="four_over_six". The module implementations stay separate: the default recipe'sNVFP4Linearhard-inherits torchao's stateful RHT/SR module (it registerssr_seed/rht_sign_vectorbuffers and shards_sr_seed), whileNVFP4FourOverSixLinearstays stateless (no RHT, no SR). The five four-over-six knobs live on the consolidated Config and are read only underrecipe="four_over_six"; a non-default value underrecipe="default"is rejected at converter build with oneValueErrornaming every offending knob, rather than being silently ignored._validate_four_over_six_knobschecks all five knobs, includingerr_modeande4m3_scale_bound, so a bad recipe fails when the config tree is built rather than on the first forward; the converter's__init__also fail-fasts underrecipe="four_over_six", so a bad recipe errors even when no Linear matches thefqns. In particularbackward_override="quantized"+row_scaled_activation=Trueis rejected: a row-scaled four-over-six tensor has no columnwise form for the quantized wgrad operand.MXFP8Linear, this is a pure leaf swap; TP wiring for the four-over-six linear is not included (the class docstring says so).err_modedefaults to"mae", matching TransformerEngine's library default (NVTE_NVFP4_4OVER6_ERR_MODE="MAE"); recipes mirroring the miles RL setup seterr_mode="mse"explicitly.Numerics evidence
Numerics live in the companion torchao PRs; parity results are maintained in a local TE harness (not in-tree): pure-torch quantizer 384/384 bitwise vs TE 2.17 kernels; CuTe DSL kernel 1920/1920 bitwise vs the torch oracle plus 12/12 vs TE; re-verified 2026-08-24 vs TE main.
Test plan
CPU-only (container without
--gpus; requires a torchao build providing the four-over-six prototype onPYTHONPATH, otherwise the new tests skip):Import checks of every touched module pass (
torchtitan.components.quantization{,.nvfp4,.utils},torchtitan.models.llama3.config_registry). Lint: ufmt (black 22.12.0 / usort 1.0.5), flake8 with the repo plugin pins, pydoclint, and codespell all clean on the changed files.GPU results come from the assembled stack tip on GB200 (RL-parity phases A-D2 plus a 6-arm Qwen3 recipe ablation), since CI has no SM100 runner for the four-over-six kernels.
Draft on the fork to stage the upstream submission; supersedes the exploratory stack (#8)
Review pass (2026-08-30)
_validate_four_over_six_knobsnow validateserr_modeande4m3_scale_bound(config-build time), with matching test cases; the grouped-only parameter moved up the stack to the grouped-converter PR where it is used.__init__fail-fasts on invalid four-over-six knobs even whenfqnsmatch nothing.has_quantizationnow countsNVFP4FourOverSixLinear.Config, with a dense-converter test (moved into this PR from the grouped one, where it belonged by scope).four_over_sixImportError andnvfp4.mdnow name the actual module (nvfp4_training.four_over_six); md em-dash consistency fix.