Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
f83eb16
Run expert-parallel PTQ from hf_ptq.py
shengliangxu Oct 10, 2026
dd4c58b
Move the expert-parallel PTQ changelog entry into 0.49.0
shengliangxu Oct 11, 2026
83d15c3
Test hf_ptq.py's expert-parallel wiring
shengliangxu Oct 11, 2026
6aa837c
Refuse a plan whose dense sharding nothing would apply
shengliangxu Oct 11, 2026
da0d66d
Pin a model to one GPU only when torchrun runs several ranks
shengliangxu Oct 11, 2026
40cfc95
Document expert-parallel PTQ in the hf_ptq README
shengliangxu Oct 11, 2026
49c0180
Calibrate through the distributed loop only for expert-parallel runs
shengliangxu Oct 11, 2026
40899fe
Initialize NVML before probing it in launch_memory_monitor
shengliangxu Oct 11, 2026
d489b4b
Stub load_pretrained in the device-pinning test
shengliangxu Oct 13, 2026
446c152
Load hf_ptq's models through load_pretrained's routing
shengliangxu Oct 13, 2026
8fcda25
Stub load_pretrained in the FSDP2 MTP-refusal test
shengliangxu Oct 13, 2026
c249470
Answer the session's collectives in the hf_ptq wiring tests
shengliangxu Oct 13, 2026
987610c
Run hf_ptq without the session: own the process group, read rank and …
shengliangxu Oct 14, 2026
0edf648
Decide hf_ptq's distribution once and read the plan wherever it distr…
shengliangxu Oct 14, 2026
ec6e422
Take hf_ptq's DistributedState from distributed_run
shengliangxu Oct 14, 2026
e155b07
Let distributed_run own hf_ptq's one-rank FSDP2 group
shengliangxu Oct 14, 2026
b0c984e
Leave a single process's FSDP2 group to the load
shengliangxu Oct 14, 2026
14ddc44
Keep every rank decoding hf_ptq's preview of a sharded model
shengliangxu Oct 15, 2026
211ef0d
Test the preview lockstep for a one-rank FSDP2 plan and in the VL ima…
shengliangxu Oct 15, 2026
820ddb8
Write a replicated model's checkpoint from rank 0 only
shengliangxu Oct 15, 2026
4daa54e
Refuse dense FSDP2 within expert-data-parallel replicas before loading
shengliangxu Oct 15, 2026
4ef2a4c
Answer the checkpoint-read gather in hf_ptq's simulated torchrun laun…
shengliangxu Oct 16, 2026
29b87bf
Run hf_ptq expert-parallel for real on two GPUs
shengliangxu Oct 16, 2026
d06802c
Trim the hf_ptq expert-parallel tests: drop duplicates, merge tables
shengliangxu Oct 16, 2026
4fe6e55
Refuse the TensorRT-LLM checkpoint export in a multi-process run
shengliangxu Oct 17, 2026
879d45f
Calibrate image batches through the expert-parallel loop
shengliangxu Oct 17, 2026
0ddf290
Let the hf_ptq EP tests' checkpoint stub take the Hub options
shengliangxu Oct 20, 2026
fb475b2
Keep generate from switching a MoE's experts to batched_mm in hf_ptq'…
shengliangxu Oct 20, 2026
2f0cc06
Run hf_ptq's sharded previews for real, under expert parallelism and …
shengliangxu Oct 20, 2026
10ded45
Refuse an AutoQuantize recipe on the expert-parallel and replicated runs
shengliangxu Oct 24, 2026
16b758e
Keep each rank on its own GPU on every load path, and stop a sharded …
shengliangxu Oct 24, 2026
7238c98
Have a sharded model's ranks skip the image preview together
shengliangxu Oct 24, 2026
a04bf65
Refuse single-process load options in hf_ptq's multi-rank runs
shengliangxu Oct 25, 2026
53159ca
Refuse a sharded vLLM fake-quant export; re-plant a2a forwards after PTQ
shengliangxu Oct 25, 2026
532c902
Describe auto's EP degree below a spec's floor, and who re-plants a2a
shengliangxu Oct 25, 2026
c0f2ea9
Keep --use_fsdp2's best-effort preview; refuse a rank naming no GPU
shengliangxu Oct 25, 2026
7777e5e
Re-plant a text-calibrated VLM's a2a forwards over the whole model
shengliangxu Oct 25, 2026
b5d0f7e
Keep a preview's nested language model off batched_mm experts too
shengliangxu Oct 25, 2026
c724987
Note hf_ptq's --device refusal under a multi-rank torchrun in the cha…
shengliangxu Oct 25, 2026
5fbb9b1
Refuse a sharded model's speculative-decoding export on every rank
shengliangxu Oct 25, 2026
8245ee9
Name transformers 5.7 as the expert-parallel floor in the hf_ptq README
shengliangxu Oct 25, 2026
e277aa8
Skip hf_ptq's preview of a model that has no generate
shengliangxu Oct 25, 2026
a5e4fca
Drop hf_ptq's preview skip for a model without generate
shengliangxu Oct 25, 2026
886b5b8
Skip hf_ptq's DeepSeek-V3 expert-parallel routes below transformers 5.7
shengliangxu Oct 25, 2026
a7793b7
Keep hf_ptq's Whisper calibration loader whole on every rank
shengliangxu Oct 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Changelog
- Add a checkpoint-specific NVIDIA Nemotron 3.5 Super VL AutoQuantize recipe with a 4.9-effective-bit NVFP4-MSE/FP8/BF16 search and fixed NVFP4 MTP experts. Select it under ``models/nvidia/NVIDIA-Nemotron-3.5-Super-VL-120B-A12B-BF16/auto_quantize/``.
- Add ``examples/hf_ptq/convert_ggml_to_int8.py`` to expand a checkpoint exported with a GGML recipe (IQ formats, ``q8_0``) into an INT8 weight-only compressed-tensors checkpoint. Stock vLLM serves it with its integer kernels at about half the BF16 weight memory, reproducing the GGML weights up to rounding their scales to the model dtype.
- Add an opt-in no-gather HuggingFace export for FSDP2-sharded models: with ``MODELOPT_FSDP2_EXPORT=nogather``, ``export_hf_checkpoint`` sends each tensor to a single owner rank and every rank writes its own shards in parallel, instead of gathering the full state dict on one host. MoE experts stay sharded through the export, so each rank only materializes its own experts.
- Add expert-parallel PTQ for HuggingFace MoE models to ``examples/hf_ptq/hf_ptq.py``: under ``torchrun``, each rank holds only its share of the routed experts, tokens reach them by all-to-all, and every rank calibrates on its own slice of the data. ``MODELOPT_EP_DEGREE`` and ``MODELOPT_FSDP_SIZE`` override the automatic choice of expert-parallel degree and of FSDP2-sharding the dense layers, and the quantized checkpoint is written by every rank in parallel without gathering the model.

*Speculative Decoding*

Expand All @@ -38,6 +39,7 @@ Changelog

**Backward Breaking Changes**

- ``examples/hf_ptq/hf_ptq.py`` launched by ``torchrun`` on more than one rank now refuses a ``--device`` other than ``cuda``, which it used to ignore: each rank runs on its own GPU, ``cuda:<local_rank>``.
- ``examples/hf_ptq/hf_ptq.py --use_fsdp2`` on more than one GPU now refuses calibration that keeps its statistics on each rank: AWQ, SVDQuant, local Hessian and imatrix, also as an AutoQuantize candidate. Each rank calibrates on its own share of the data, so these calibrated the ranks' shards of a weight differently; run them without ``--use_fsdp2``.
- ``export_mcore_gpt_to_hf`` given a Hugging Face Hub model ID no longer writes the tokenizer, processor, generation config or remote-code files. Pass a local directory instead, e.g. from ``modelopt.torch.export.ensure_local_checkpoint``.
- ``modelopt.torch.utils.distributed.fsdp2_wrap`` moved to ``modelopt.torch.utils.plugins.model_load_utils``, with the other loaders. The old import path still works, but calling it now needs the ``hf`` extra.
Expand Down
26 changes: 26 additions & 0 deletions examples/hf_ptq/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,32 @@ See [Recipe-based Quantization](#recipe-based-quantization) for the recipe forma

> *Set `MODELOPT_FSDP2_EXPORT=nogather` to have every rank write its own shards of the checkpoint in parallel instead of gathering the full state dict on one host.*

## Expert-Parallel Post-Training Quantization for MoE Models

Under `torchrun`, `hf_ptq.py` shards an MoE model's routed experts across the ranks (expert parallelism) instead of loading the whole model on every GPU. Each rank holds `num_experts / ep_degree` experts and calibrates on its own shard of the calibration data. An all-to-all sends every token to the rank that owns its expert, so each expert's quantizers see the tokens routed to it from all ranks. The dense (non-expert) part is replicated on every rank, or FSDP2-sharded when it does not fit one GPU. Each rank then writes its share of the unified HF checkpoint, without gathering the model onto one GPU.

A model can be expert-parallel when its config declares a `base_model_ep_plan`. transformers ships one for several MoEs, and ModelOpt supplies the plan or an adapter for others (see the `ep_spec` entries in `modelopt/torch/models/*/specs.py`). Expert parallelism needs transformers 5.7 or newer, and some models a newer release; a run that cannot be expert-parallel is refused before loading.

```bash
torchrun --nproc_per_node=<num_gpus_per_node> \
hf_ptq.py \
--pyt_ckpt_path <path_to_moe_model> \
--recipe general/ptq/nvfp4_default-kv_fp8 \
--calib_size <num_calib_samples> \
--export_path <export_path>
```

To run across nodes, add the `--nnodes`, `--node_rank`, `--master_addr` and `--master_port` flags shown in [Manual (run on each node)](#manual-run-on-each-node). `--calib_size` is the total over all ranks.

Two environment variables override the automatic distribution plan:

| Variable | Default | Effect |
| :--- | :--- | :--- |
| `MODELOPT_EP_DEGREE` | `auto` | Expert-parallel degree. `auto` picks the largest degree that divides both the routed-expert count and the world size, or 1 for a model whose spec refuses expert parallelism or needs a newer transformers. Below the world size, each group of `MODELOPT_EP_DEGREE` ranks holds a full set of experts, and the groups calibrate on different data. |
| `MODELOPT_FSDP_SIZE` | `auto` | Whether to FSDP2-shard the dense part. `auto` shards it when it would take more than 60% of one GPU's memory; `world` always shards it; `1` replicates it. With `MODELOPT_EP_DEGREE` below the world size the export cannot write a sharded dense part yet, so such a run fails before loading. |

A run that cannot shard the model the way the plan asks fails before loading, rather than loading the whole model on every rank. `--use_fsdp2` skips expert parallelism and uses the [FSDP2 path](#multi-node-post-training-quantization-with-fsdp2) instead. Expert parallelism refuses GPT-OSS and Llama-4: their experts are stored transposed, which the expert-parallel export cannot write yet. `--use_fsdp2` refuses their released checkpoints too (GPT-OSS's carry an MXFP4 `quantization_config`, and Llama-4's are multimodal), so quantize those in a single process (without `torchrun`), which spreads the model over the node's GPUs.
Comment thread
shengliangxu marked this conversation as resolved.

## Evaluate Accuracy

### TensorRT-LLM Validation
Expand Down
Loading
Loading