NVFP4 ONNX export fails when rotate=True (FWHT trace + post-processor)
I maintainer di solito rispondono entro 2 giorni
@ajrasane ci sta già lavorando.
Dal 12/5/2026.
Valutazione
Questa issue non è ancora stata valutata.
Descrizione
Before submitting an issue, please make sure it hasn't been already addressed by searching through the existing and past issues.
Describe the bug
When rotate: True is set on *weight_quantizer in an NVFP4 quant config (e.g. NVFP4_FP8_MHA_CONFIG), ONNX export breaks in two related ways that surface together:
-
Trace-side:
normalized_hadamard_transforminmodelopt/torch/quantization/nn/functional.pycallsfast_hadamard_transform.hadamard_transform(), which is a custom CUDA op without an ONNX symbolic function. Duringtorch.onnx.export, it gets evaluated eagerly — the rotated activation tensor is baked as aConstantin the exported graph, severing the runtime input flow. The compiled engine then produces output that's independent of its inputs. -
Post-processor:
NVFP4QuantExporter(inmodelopt/onnx/export/nvfp4_exporter.py) assumes weight tensors live ingraph.initializer. With rotation enabled, they end up in upstreamConstantnodes'valueattribute (or further upstream as a Reshape/MatMul subgraph). Three sites —compute_scales(L219),compress_weights(L263),post_process(L369) — hit:
AssertionError: Initializer for weight '/.../weight_quantizer/Constant_output_0' not found.
Discovered while compiling FLUX.2 Klein 4B for TensorRT. Investigation done with Claude's assistance.
Steps/Code to reproduce bug
import modelopt.torch.quantization as mtq
import torch.onnx
import onnx
from modelopt.onnx.export.nvfp4_exporter import NVFP4QuantExporter
cfg = mtq.NVFP4_FP8_MHA_CONFIG.copy()
cfg["quant_cfg"]["*weight_quantizer"]["rotate"] = True
mtq.quantize(model, cfg, forward_loop=...)
torch.onnx.export(model, ..., "model.onnx")
m = onnx.load("model.onnx")
NVFP4QuantExporter.process_model(m)
# AssertionError: Initializer for weight '/.../weight_quantizer/Constant_output_0' not found.
Expected behavior
rotate: True is documented as a supported flag in NVFP4 configs, so either:
- Export should produce a usable engine (rotation works end-to-end through ONNX), or
- The flag should fail clearly at config validation time if NVFP4-export + rotation isn't supported.
Workaround we used locally
Two user-side changes to unblock our pipeline:
-
Trace fix: monkey-patched
normalized_hadamard_transformto usetorch.matmul(x, H)against an explicit pre-computed Hadamard matrix. Mathematically identical (the FWHT butterfly is just a fast factorization ofx @ H), but pure PyTorch ops are ONNX-traceable. Slower at calibration time, no runtime cost (TRT folds the matmul against the constant H). -
Post-processor fix: added a
_resolve_weight_tensor()helper to handle three weight-source patterns:- Direct initializer (existing path, unchanged — non-rotation users see no change)
- Upstream
Constantnodevalueattribute - Upstream constant subgraph (Reshape/MatMul/Mul/Add/Sub/Div/Cast/Transpose) — evaluated to numpy at compile time
Plus
post_processpromotes any remaining inlineConstant≥ 64 KB to a graph initializer sosave_as_external_datacan externalize them. Without this, large rotation H matrices stay inline and the proto exceeds protobuf's 2 GB serialization limit, blocking the TRT parser.
End-to-end this produces a working rotated NVFP4 engine for FLUX.2 Klein 4B on RTX 5090 + TensorRT 10.15.1.
Question for maintainers
What's the right fix shape upstream? A few options:
- Replace the FWHT call in
normalized_hadamard_transformwith an ONNX-traceable equivalent (matmul against explicit H, or expressed as a Reshape/Add/Sub butterfly chain)? - Add an ONNX symbolic for
FastHadamardTransform.apply()so the existing CUDA op exports correctly? - Accept user-side post-processor patches that handle non-initializer weight sources (the
_resolve_weight_tensorapproach)? - Mark rotation as PyTorch-inference-only and reject it at config validation for ONNX export paths?
Happy to PR whichever direction you prefer. We can share the matmul-Hadamard + post-processor patches if useful.
Related: #614
Who can help?
Anyone familiar with the NVFP4 ONNX export path or the rotation/Hadamard helpers in modelopt.torch.quantization.nn.functional.
System information
- OS: Windows 11 (10.0.26100)
- CPU architecture: x86_64
- GPU: NVIDIA GeForce RTX 5090 (Blackwell SM_120)
- GPU memory size: 32 GB
- Number of GPUs: 1
- Library versions:
- Python: 3.12.10
- ModelOpt: 0.42.0
- CUDA: 13.0
- PyTorch: 2.11.0+cu130
- Transformers: 5.5.4
- TensorRT: 10.15.1.29
- Other: FLUX.2 Klein 4B (rectified flow distilled)
- Lingua principale
- Python
- Stelle
- 5.3k
- Fork
- 745
- Merge medio
- 4g 2h
- PR unite (30g)
- 160
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di NVIDIA/Model-Optimizer
-
[Bug] modelopt-mcp: all launcher subprocesses hang when the server runs as a stdio MCP server — missing stdin=DEVNULLForse già presa @ChenhanYu l’ha presa 14 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
NVIDIA/Model-Optimizer#2551 · 1 commento · 1 assegnatario ·
I maintainer di solito rispondono entro 2 giorni
-
Puzzletron Progress 6/8 (calculating one block scores) takes 10 to 20 times more than in tutorialForse di nuovo libera @tejasng053 l’ha presa 20 giorni fa e non c’è nessuna pull request aperta. Apertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
NVIDIA/Model-Optimizer#1667 ·
I maintainer di solito rispondono entro 2 giorni
-
fp4_kernel_hopper.py uses tl.make_block_ptr, which is removed in Triton main (breaks NVFP4 fake quant)Forse già presa @kinjalpatel27 l’ha presa 1 giorno fa. Aperta
Difficoltà 3/5 Mezza giornata Idoneità per principianti 72/100
NVIDIA/Model-Optimizer#2810 · 1 assegnatario ·
I maintainer di solito rispondono entro 2 giorni
-
test_cast_fp4_impl_gpu_mem is flaky on Jetson Thor: mem_get_info reports system-wide memory on integrated GPUsForse già presa @LinCanNerd l’ha presa 8 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 25/100
NVIDIA/Model-Optimizer#2706 ·
I maintainer di solito rispondono entro 2 giorni
-
test_cuda_pack_reconstruction_matches_pytorch_at_scale[iq1_m] fails on Jetson Thor: exact ties exceed the blocks // 1000 boundForse già presa @LinCanNerd l’ha presa 8 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 35/100
NVIDIA/Model-Optimizer#2705 ·
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di NVIDIA/Model-Optimizer
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
PolicyEngine/policyengine-us#10262 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
kellyjonbrazil/jc#788 ·
I maintainer di solito rispondono entro 2 giorni
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
`/search.json` ignores the documented `editions.sort` parameterForse già presa @PranavD2905 l’ha presa oggi. ApertaAffects: Server Good First Issue Module: Solr Needs: Triage Theme: Public APIs Theme: Search
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
internetarchive/openlibrary#13989 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug P2: misleading query
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
jeffknupp/association#478 ·