Cosmos 3 docs: FP8 snippet fails at the first W8A8 step without importing ModelOpt's FP8 GEMM backend
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Newbie friendliness
- 78/100
- Issue type
- Documentation
- Clarity
- Clearly specified
- Activity status
- Active
- Domain
- documentation
Research direction
The FP8 snippet to change is in docs/source/en/api/pipelines/cosmos3.md around lines 56-69; the ModelOpt guide it points to is docs/source/en/quantization/modelopt.md around lines 98-100. Add the fp8_per_tensor_gemm import and the enable_huggingface_checkpointing() call to the snippet, with a short comment on each. Done when the snippet shows both lines before from_pretrained and the docs build renders it cleanly.
Written by the indexing model from the issue text.
Description
Describe the bug
The FP8 section of the Cosmos 3 docs loads the ModelOpt FP8 checkpoint with from_pretrained(..., revision="fp8", device_map="cuda") and points to the ModelOpt guide for the restore path:
The ModelOpt guide adds enable_huggingface_checkpointing():
With both, a multi-step video generation runs the first W8A16 steps and then fails at the first W8A8 step. ModelOpt finds no real-quant GEMM for the restored RealQuantLinear layers ("RealQuantLinear: No real-quant GEMM found"), builds its fallback extension, and its tensor quantizer raises. The FP8 GEMM backend is registered only by importing modelopt.torch.quantization.backends.fp8_per_tensor_gemm, which neither page shows. NVIDIA's Cosmos cookbook does that import before loading:
Without enable_huggingface_checkpointing() (the snippet as shown), the FP8 weights load into plain nn.Linear and the first denoising step raises ValueError: Cosmos3 mixed precision found no compatible serialized ModelOpt FP8 linears under ['reasoner', 'generation']; discovered counts={'reasoner': 0, 'generation': 0}.
Unchanged on main: docs/source/en/api/pipelines/cosmos3.md mentions neither call, and no docs page mentions fp8_per_tensor_gemm.
Reproduction
import torch
from diffusers import Cosmos3OmniPipeline
from modelopt.torch.opt import enable_huggingface_checkpointing
enable_huggingface_checkpointing()
pipe = Cosmos3OmniPipeline.from_pretrained("nvidia/Cosmos3-Nano", revision="fp8", dtype=torch.bfloat16, device_map="cuda")
video = pipe(
prompt="A robot arm stacks colored blocks on a wooden table.",
num_frames=49, height=480, width=848, num_inference_steps=8,
generator=torch.Generator(device="cuda").manual_seed(123),
).video
(Our run used the prompt and negative prompt from nvidia/Cosmos3-Nano assets/; the failure happens at step 3 of 8, the first W8A8 step, independently of the prompt.)
Logs
RealQuantLinear: No real-quant GEMM found: RealQuantQuantLinear(
in_features=4096, out_features=4096, bias=False
(input_quantizer): TensorQuantizer((4, 3) bit fake per-tensor amax=0.5430 calibrator=MaxCalibrator quant)
(output_quantizer): TensorQuantizer(disabled)
(weight_quantizer): TensorQuantizer((4, 3) bit per-tensor amax=0.5039 calibrator=MaxCalibrator quant)
).
Loading extension modelopt_cuda_ext_fp8...
Loaded extension modelopt_cuda_ext_fp8 in 67.1 seconds
Traceback (most recent call last):
File "repro.py", line 51, in <module>
video = pipe(
^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/utils/_contextlib.py", line 120, in decorate_context
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/diffusers/pipelines/cosmos/pipeline_cosmos3_omni.py", line 1756, in __call__
preds_vision, preds_sound, preds_action = self.transformer(
^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1775, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1786, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/diffusers/models/transformers/transformer_cosmos3.py", line 818, in forward
und_out, gen_out = self._run_decoder_stack(und_seq, gen_seq, rotary_emb)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/diffusers/models/transformers/transformer_cosmos3.py", line 662, in _run_decoder_stack
und_seq, gen_seq = decoder_layer(und_seq, gen_seq, rotary_emb)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1775, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1786, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/diffusers/models/transformers/transformer_cosmos3.py", line 364, in forward
und_attn_out, gen_attn_out = self.self_attn(und_norm, gen_norm, rotary_emb)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1775, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1786, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/diffusers/models/transformers/transformer_cosmos3.py", line 301, in forward
return self.processor(self, und_seq, gen_seq, rotary_emb)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/diffusers/models/transformers/transformer_cosmos3.py", line 68, in __call__
q_und = attn.to_q(und_seq).view(-1, attn.num_attention_heads, attn.head_dim)
^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1775, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1786, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/diffusers/pipelines/cosmos/mixed_precision.py", line 240, in mixed_forward
return __base(inputs, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/modelopt/torch/quantization/nn/modules/quant_linear.py", line 240, in forward
return super().forward(input, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/modelopt/torch/quantization/nn/modules/quant_module.py", line 240, in forward
return super().forward(input, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/modelopt/torch/quantization/nn/modules/quant_module.py", line 192, in forward
output = super().forward(input, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/linear.py", line 134, in forward
return F.linear(input, self.weight, self.bias)
^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/modelopt/torch/opt/dynamic.py", line 782, in __getattr__
return manager.get_da_cb(name)(self, value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/modelopt/torch/opt/dynamic.py", line 76, in __call__
val = cb(self_module, val)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/modelopt/torch/quantization/nn/modules/quant_module.py", line 230, in _get_quantized_weight
return module.weight_quantizer(weight)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1775, in _wrapped_call_impl
return self._call_impl(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/torch/nn/modules/module.py", line 1786, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/modelopt/torch/quantization/nn/modules/tensor_quantizer.py", line 1105, in forward
raise ValueError(
ValueError: self._dequantize is True and self.fake_quant is False. This case should have been handled.
With import modelopt.torch.quantization.backends.fp8_per_tensor_gemm added before loading (otherwise the same load), generation completes and the W8A8 steps compile and use ModelOpt's FP8 GEMM. We verified that with enable_group_offload on a 16 GB GPU (35 steps × 189 frames and 8 steps × 49 frames); the traceback above is from the device_map="cuda" run on a 32 GB GPU.
Suggested fix
Add both lines to the Cosmos 3 FP8 snippet:
import modelopt.torch.quantization.backends.fp8_per_tensor_gemm # noqa: F401 - registers ModelOpt's FP8 GEMM
from modelopt.torch.opt import enable_huggingface_checkpointing
enable_huggingface_checkpointing() # restores the ModelOpt FP8 linears while loading
Happy to open a docs PR.
System Info
- diffusers 0.41.0, nvidia-modelopt 0.44.0, transformers 5.20.2, accelerate 1.15.0
- torch 2.9.0a0+145a3a7 (container
nvcr.io/nvidia/pytorch:25.10-py3), CUDA 13.0, Python 3.12 - NVIDIA GeForce RTX 5090 32 GB, driver 620.62
- Dominant language
- Python
- Stars
- 34.8k
- Forks
- 7.4k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 55
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from huggingface/diffusers
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
huggingface/diffusers#15163 · 3 comments ·
Maintainers usually reply within 1 day
-
Clarify set_adapters() adapter_weights documentation and type hintsPossibly taken @gorkadabo1 claimed this 4 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
huggingface/diffusers#15146 · 1 comment · 1 assignee ·
Maintainers usually reply within 1 day
-
`encode_video` truncates a fractional `fps`, so the video runs longer than its audioPossibly taken @guptaishaan claimed this 12 days ago. Open
Difficulty 2/5 1-3 hours Newbie friendliness 83/100
huggingface/diffusers#15104 · 1 comment ·
Maintainers usually reply within 1 day
-
VaeImageProcessor.denormalize() raises AttributeError for NumPy inputsPossibly taken @tonycoder-hub claimed this 22 days ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
huggingface/diffusers#15011 · 1 comment ·
Maintainers usually reply within 1 day
-
`ModelMixin.from_pretrained` on a sharded checkpoint fails under `HF_HUB_OFFLINE=1` even when fully cached (`_get_checkpoint_shard_files` still calls `model_info`)Possibly taken @Subodh-17 claimed this 28 days ago. Openbug models
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
huggingface/diffusers#14952 · 1 comment ·
Maintainers usually reply within 1 day
All issues in huggingface/diffusers
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
521xueweihan/HelloGitHub#4237 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
jejjohnson/gaussx#721 ·
Maintainers usually reply within 1 day
-
mock-core-configs/etc/mock/rocky-10-riscv64.cfg contains the wrong architecture in config_opts['root']Possibly taken @jasonmontleon claimed this 4 days ago. Open
Difficulty 1/5 Under an hour Newbie friendliness 94/100
rpm-software-management/mock#1834 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 75/100
elastic/elastic-otel-python#683 ·
Maintainers usually reply within 1 day
-
ci-rerun: collect.py fails a whole pr-babysit cycle on one transient GitHub 5xx and never retriesOpenfollow-up
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Maintainers usually reply within 1 day