Skip to content

Commit 1e9c87d

Browse files
Merge branch 'main' into fridah/calib-registry
2 parents 0e43a87 + e4b054b commit 1e9c87d

16 files changed

Lines changed: 363 additions & 264 deletions

File tree

.github/codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ coverage:
99
project:
1010
default:
1111
target: auto
12-
threshold: 2% # Allow atmost 2% coverage drop from main branch.
12+
threshold: 1% # Allow atmost 1% coverage drop from main branch.
1313
patch: false

CHANGELOG.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Changelog
2222

2323
**Bug Fixes**
2424

25+
- Fix Megatron utility functions for generation (with pipeline parallelism) and ~10x speedup in MMLU score evaluation (by batching prefill passes).
2526
- Fix Minitron pruning (``mcore_minitron``) for MoE models. Importance estimation hooks were incorrectly registered for MoE modules and NAS step was hanging before this.
2627
- Fix TRT support for remote autotuning in ONNX Autotune from 10.16+ to 10.15+ and fix TRT versioning check to the ``trtexec`` version instead of the TRT Python API when using ``trtexec`` backend.
2728

@@ -32,7 +33,7 @@ Changelog
3233
- [Experimental] Add support for transformers>=5.0, including generic PTQ and unified HF checkpoint export for fused MoE expert modules (Mixtral, Qwen2-MoE, Qwen3-MoE, Qwen3.5-MoE, DeepSeek-V3, Jamba, OLMoE, etc.).
3334
- Improve ``megatron_preprocess_data``: add ``--reasoning_content`` support for Nemotron v3 datasets, eliminate intermediate JSONL for HuggingFace datasets, return output file prefixes from the Python API, add gzip input support (``.jsonl.gz``), add ``--strip_newlines`` flag for plain-text pretraining data, add ``--hf_streaming`` for very large datasets (only consumed rows downloaded), and auto-shuffle when ``--hf_max_samples_per_split`` is set to avoid biased sampling.
3435

35-
0.43 (2026-04-09)
36+
0.43 (2026-04-16)
3637
^^^^^^^^^^^^^^^^^
3738

3839
**Bug Fixes**

examples/megatron_bridge/prune_minitron.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
while skipping pruning of num_attention_heads using following defaults:
1919
1024 samples from nemotron-post-training-dataset-v2 for calibration,
2020
at-most 20% depth (num_layers) and 40% width is pruned per prunable hparam (hidden_size, ffn_hidden_size, ...),
21-
top-10 candidates are evaluated for MMLU score (5% sampled data) to select the best model.
21+
top-10 candidates are evaluated for MMLU score (10% sampled data) to select the best model.
2222
2323
torchrun --nproc_per_node 2 prune_minitron.py \
2424
--hf_model_name_or_path Qwen/Qwen3-8B \
@@ -140,11 +140,11 @@ def get_args() -> argparse.Namespace:
140140
parser.add_argument(
141141
"--prune_score_func",
142142
type=str,
143-
default="mmlu_5pct",
143+
default="mmlu_10pct",
144144
help=(
145145
"Score function to use for NAS-based pruning (--prune_target_params). Only supports MMLU at the moment. "
146146
"Format: mmlu_<N>pct where <N> is the percentage of MMLU data to sample per subject "
147-
"(e.g. mmlu_5pct for 5%, mmlu_100pct for full eval)."
147+
"(e.g. mmlu_10pct for 10%, mmlu_100pct for full eval)."
148148
),
149149
)
150150
parser.add_argument(
@@ -299,16 +299,14 @@ def main(args: argparse.Namespace):
299299
match = re.fullmatch(r"mmlu_(\d+)pct", args.prune_score_func)
300300
if not match:
301301
raise ValueError(
302-
f"Invalid score function: {args.prune_score_func}. "
303-
"Expected format: mmlu_<N>pct (e.g. mmlu_5pct)"
302+
f"Invalid score function: {args.prune_score_func}. Expected format: mmlu_<N>pct (e.g. mmlu_10pct)"
304303
)
305-
mmlu_pct = int(match.group(1))
306-
if not 0 < mmlu_pct <= 100:
307-
raise ValueError("--prune_score_func percentage must be in the range [1, 100].")
308-
_mmlu_pct = mmlu_pct / 100.0
304+
mmlu_frac = float(match.group(1)) / 100.0
309305

310306
def score_func(m):
311-
return megatron_mmlu(m, tokenizer, percentage=_mmlu_pct)
307+
return megatron_mmlu(
308+
m, tokenizer, few_shots=0, fraction=mmlu_frac, batch_size=args.calib_mbs
309+
)
312310

313311
pruning_config["score_func"] = score_func
314312
pruning_config["max_width_pruning"] = args.max_width_pruning

examples/pruning/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ This mode can be useful when you don't know the exact dimensions you want to pru
124124
from modelopt.torch.utils.plugins.megatron_mmlu import megatron_mmlu
125125

126126
def score_func(m):
127-
return megatron_mmlu(m, tokenizer, percentage=0.05) # 5% sampled data for faster eval
127+
return megatron_mmlu(m, tokenizer, fraction=0.1, batch_size=4) # 10% sampled data for faster eval
128128

129129
# Specify target parameter count and configure the auto pruning algorithm
130130
# Save minitron scores at checkpoint so we can resume pruning without running the forward loop again
@@ -147,7 +147,7 @@ mtp.prune(...)
147147

148148
1. **Importance Scoring**: Same as manual pruning - computes activation magnitudes for all parameters (takes ~5 minutes for an 8B model)
149149
2. **Search Space Construction**: Generates a search space of possible architectures based search space config and other configs (`max_width_pruning`, `max_depth_pruning`, `hparams_to_skip`)
150-
3. **Architecture Search**: Find candidate architectures that meet the parameter constraint and evaluate `top_k` (based on number of parameters) of them using `score_func` e.g. MMLU, negative validation loss, etc. (takes ~10 mins per candidate for an 8B model pruning)
150+
3. **Architecture Search**: Find candidate architectures that meet the parameter constraint and evaluate `top_k` (based on number of parameters) of them using `score_func` e.g. MMLU, negative validation loss, etc. (takes ~5 min per candidate for an 8B model MMLU score with 10% sampled data)
151151
4. **Best Architecture Selection**: Returns the architecture (best `export_config`) with the highest actual score from the top-K evaluated architectures
152152
5. **Weight Slicing**: Slices the model weights according to the best pruned architecture found
153153

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
datasets>=2.14.5
2-
torch==2.9.0
3-
transformers==4.57.3
2+
torch
3+
transformers<5.0.0

modelopt/deploy/llm/generate.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,12 +109,13 @@ def _find_max_position_embeddings(cfg: dict) -> int | None:
109109
if tp < 1:
110110
tp = torch.cuda.device_count()
111111

112-
# Check if any key in config contains both "num" and "experts"
112+
# Force ep=1 to avoid TRT-LLM DeepEP kernel failures on unsupported GPUs
113+
# (e.g. Blackwell SM 12.0). Expert parallelism can be enabled explicitly
114+
# by the caller when the environment is known to support it.
113115
ep = 1
114116
enable_attention_dp = False
115117
for k in config:
116118
if "num" in k and "experts" in k:
117-
ep = torch.cuda.device_count()
118119
enable_attention_dp = True
119120
break
120121

modelopt/torch/export/plugins/megatron_importer.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,17 @@ def _import_state_dict(self):
747747
if hasattr(model, "output_layer") and not model.share_embeddings_and_output_weights:
748748
self.rules["output_layer"](model.output_layer)
749749

750+
# For PP with shared embedding/output weights, re-sync the output layer on the last
751+
# pipeline stage from stage 0's (now HF-loaded) embedding. At model init,
752+
# setup_embeddings_and_output_layer() zeros out the last stage's weight and all-reduces
753+
# from stage 0. After importing HF weights into stage 0's embedding, that sync is stale,
754+
# so we re-run it here.
755+
if (
756+
model.share_embeddings_and_output_weights
757+
and model.config.pipeline_model_parallel_size > 1
758+
):
759+
model.setup_embeddings_and_output_layer()
760+
750761
# MTP
751762
if hasattr(model, "mtp"):
752763
layer_pbar.set_description("Importing MTP")

modelopt/torch/prune/plugins/mcore_minitron.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ class CandidateSubnet:
171171
score: float | None
172172

173173

174+
torch.serialization.add_safe_globals([CandidateSubnet])
175+
176+
174177
class MCoreMinitronSearcher(BaseSearcher):
175178
"""Searcher for Minitron pruning algorithm.
176179

modelopt/torch/utils/logging.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,9 @@ def no_stdout():
105105

106106
def print_rank_0(*args, **kwargs):
107107
"""Prints only on the master process."""
108+
kwargs.setdefault("flush", True)
108109
if dist.is_master():
109-
print(*args, **kwargs, flush=True)
110+
print(*args, **kwargs)
110111

111112

112113
def warn_rank_0(message, *args, **kwargs):

0 commit comments

Comments
 (0)