Skip to content

Commit e4a90d7

Browse files
committed
Merge upstream main
Signed-off-by: Philip Petrakian <ppetrakian@nvidia.com>
2 parents 2110b61 + 47f079a commit e4a90d7

71 files changed

Lines changed: 46762 additions & 569 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/cicd-main.yml

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,22 @@ env:
3535
container-registry-gb200: 766267172432.dkr.ecr.us-east-2.amazonaws.com
3636

3737
jobs:
38+
ephemeral-runner-routing:
39+
uses: NVIDIA-NeMo/FW-CI-templates/.github/workflows/_ephemeral_runner_routing.yml@d0878a142525ff79366ca96fbc0b306cd8d64670 # v1.9.0
40+
with:
41+
lane: ${{ vars.NEMO_CI_EPHEMERAL_LANE }}
42+
legacy_label: nvidia-ci-aws-gpu-x8-ephemeral
43+
run_id: ${{ github.run_id }}
44+
run_attempt: ${{ github.run_attempt }}
45+
3846
is-not-external-contributor:
47+
needs: [ephemeral-runner-routing]
3948
runs-on: ubuntu-latest
4049
if: github.repository == 'NVIDIA/Megatron-LM'
4150
outputs:
4251
is_external_contributor: ${{ github.event.pull_request.user.type == 'User' }}
4352
is_maintainer: ${{ steps.check-membership.outputs.is_maintainer }}
44-
selected_runner: ${{ steps.check-membership.outputs.is_maintainer == 'true' && 'nvidia-ci-aws-gpu-x8' || 'nvidia-ci-aws-gpu-x8-ephemeral' }}
53+
selected_runner: ${{ steps.check-membership.outputs.is_maintainer == 'true' && 'nvidia-ci-aws-gpu-x8' || needs.ephemeral-runner-routing.outputs.runner_label }}
4554
selected_runner_gb200: ${{ steps.check-membership.outputs.is_maintainer == 'true' && 'nvidia-ci-aws-use2-gpu-x4' || 'ubuntu-latest' }}
4655
permissions:
4756
issues: write
@@ -168,7 +177,7 @@ jobs:
168177
pre-flight:
169178
needs: [is-not-external-contributor]
170179
if: github.repository == 'NVIDIA/Megatron-LM'
171-
uses: NVIDIA-NeMo/FW-CI-templates/.github/workflows/_cicd_preflight.yml@c1a0837f362a1a696e647238ab1cf916b2a7cf4a # v1.8.6
180+
uses: NVIDIA-NeMo/FW-CI-templates/.github/workflows/_cicd_preflight.yml@d0878a142525ff79366ca96fbc0b306cd8d64670 # v1.9.0
172181

173182
configure:
174183
runs-on: ubuntu-latest
@@ -1357,26 +1366,6 @@ jobs:
13571366
body: `🔄 Merge queue validation started!\n\nYou can track the progress here: ${runUrl}`
13581367
});
13591368
1360-
cleanup-taint-node:
1361-
runs-on: ${{ needs.is-not-external-contributor.outputs.selected_runner }}
1362-
needs:
1363-
- is-not-external-contributor
1364-
- cicd-container-build
1365-
- cicd-unit-tests-latest
1366-
- cicd-integration-tests-latest-h100
1367-
- cicd-integration-tests-latest-gb200
1368-
- Coverage
1369-
- Coverage_Fake
1370-
if: |
1371-
always()
1372-
&& !cancelled()
1373-
&& contains(needs.is-not-external-contributor.outputs.selected_runner, 'ephemeral')
1374-
&& !needs.pre-flight.outputs.is_deployment_workflow == 'true'
1375-
steps:
1376-
- name: Taint node for cleanup
1377-
shell: bash
1378-
run: taint-node.sh
1379-
13801369
DCO_merge_group:
13811370
name: DCO
13821371
if: github.event_name == 'merge_group'

examples/inference/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Inference can collect traces two ways.
111111

112112
| Path | Enable with | Captures | CUDA graphs |
113113
|------|-------------|----------|------------|
114-
| **Sink** | `--moe-enable-routing-replay` | top-K indices only | on |
114+
| **Sink** | `--moe-enable-routing-replay` + legacy scheduling | top-K indices only | on |
115115
| **Hook** | no replay + `--cuda-graph-impl none` | indices **+ hidden states + router weights** | must be off |
116116

117117
Only the hook path captures the hidden states and router weights that
@@ -134,10 +134,14 @@ Forward hooks do not fire during CUDA graph replay. MoE cudagraphs must be disab
134134

135135
**Inference — sink** (routing indices only, graphs on):
136136

137+
Routing replay requires legacy scheduling. Because async scheduling is enabled by
138+
default, explicitly select legacy mode when enabling the routing replay sink.
139+
137140
```bash
138141
--moe-routing-trace-path /path/to/trace_dir
139142
--moe-routing-trace-max-inference-steps 200
140143
--moe-enable-routing-replay
144+
--inference-dynamic-batching-async-sched-mode legacy
141145
```
142146

143147
**Inference — hook** (adds hidden states + weights for predictability):

examples/inference/advanced/gpt_dynamic_inference.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,7 @@ def escape_str(s):
506506
p_count = len(p_times)
507507
d_count = len(d_times)
508508

509-
p_mean = p_total / p_count
509+
p_mean = p_total / p_count if p_count != 0 else 0.0
510510
d_mean = d_total / d_count if d_count != 0 else 0.0
511511

512512
# Commented out for now as the step/add/output times are not calculated correctly.

examples/post_training/modelopt/README.md

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ knowledge distillation, pruning, speculative decoding, and more.
2020

2121
## Major Features
2222

23-
- Start from Hugging Face pretrained model checkpoint with on-the-fly conversion to Megatron-LM checkpoint format.
23+
- Optimize Megatron-Core distributed checkpoints.
2424
- Support all kinds of model parallelism (TP, EP, ETP, PP).
2525
- Export to TensorRT-LLM, vLLM, and SGLang ready unified checkpoint.
2626

@@ -50,13 +50,58 @@ Alternatively, you can install from [source](https://github.com/NVIDIA/Model-Opt
5050
to try our latest features.
5151

5252
> **❗ IMPORTANT:** The first positional argument (e.g. `meta-llama/Llama-3.2-1B-Instruct`) of each script
53-
> is the config name used to match the supported model config in `conf/`. The pretrained HF checkpoint should
54-
> be downloaded and provided through `${HF_MODEL_CKPT}`.
53+
> is the config name used to match the supported model config in `conf/`.
54+
55+
### Megatron-Core Checkpoint Prerequisite
56+
57+
All examples in this folder, including examples for post-training quantization (PTQ) and quantization-aware training (QAT) or distillation (QAD), require a Megatron-Core
58+
distributed checkpoint. Direct Hugging Face import in the ModelOpt scripts is deprecated; use the
59+
[Megatron-Bridge stable checkpoint conversion CLI](https://github.com/NVIDIA-NeMo/Megatron-Bridge/tree/main/examples/conversion#2-stable-checkpoint-conversion-cli)
60+
to import the model first. If you want to start directly from a Hugging Face checkpoint for
61+
quantization, use the [Megatron-Bridge quantization examples](https://github.com/NVIDIA-NeMo/Megatron-Bridge/tree/main/examples/quantization).
62+
63+
The [NVIDIA NGC NeMo container catalog](https://catalog.ngc.nvidia.com/orgs/nvidia/-/containers/nemo/-/tags)
64+
lists the current release. The example below uses `26.08`; the NeMo container provides
65+
Megatron-Bridge at `/opt/Megatron-Bridge`. It mounts a local Hugging Face model and a directory
66+
for the imported checkpoint.
67+
68+
```sh
69+
HF_MODEL_PATH=/path/to/hf/Llama-3.2-1B-Instruct
70+
MEGATRON_MODEL_PATH=/path/to/checkpoints/Llama-3.2-1B-Instruct
71+
HF_TOKEN=<your_hugging_face_access_token>
72+
73+
docker run --rm -it --shm-size=24g \
74+
-e HF_TOKEN \
75+
-v "${HF_MODEL_PATH}:/models/hf/Llama-3.2-1B-Instruct:ro" \
76+
-v "${MEGATRON_MODEL_PATH}:/models/megatron/Llama-3.2-1B-Instruct" \
77+
-w /opt/Megatron-Bridge \
78+
nvcr.io/nvidia/nemo:26.08 \
79+
./scripts/conversion/convert.sh import \
80+
--executor local --device cpu \
81+
--hf-model /models/hf/Llama-3.2-1B-Instruct \
82+
--megatron-path /models/megatron/Llama-3.2-1B-Instruct
83+
```
84+
85+
#### Choosing CPU or GPU for the import
86+
87+
Use `--device cpu` for a single-process import when the model and conversion working set fit in
88+
host memory. This is the simplest choice for the Llama 3.2 1B example above and does not require
89+
GPUs or model parallelism. Use `--device gpu` with `--gpus-per-node` (and, when needed, `--nodes`)
90+
when host memory is insufficient, when the target checkpoint needs tensor, pipeline, or expert
91+
parallelism, or when a distributed import is more practical for a large model. Model size alone
92+
does not require GPU import: a sufficiently high-memory CPU node can import even a large model;
93+
GPU import shards the work and memory across ranks. For GPU import, set `--tp`, `--pp`, and `--ep`
94+
to the intended checkpoint layout.
95+
96+
Set `HF_TOKEN` to a Hugging Face access token before starting the import; it is required for gated
97+
models and is passed into the container by `-e HF_TOKEN`. Set `--tp`, `--pp`, and `--ep` for the
98+
target parallelism. Consult the Megatron-Bridge conversion documentation for supported architectures
99+
and distributed examples.
55100

56101

57102
### ⭐ NVFP4 Quantization, Quantization-Aware Training, and Model Export
58103

59-
Provide the pretrained checkpoint path through variable `${HF_MODEL_CKPT}` and provide variable
104+
Provide the imported Megatron-Core checkpoint through `${MLM_MODEL_CKPT}` and provide variable
60105
`${MLM_MODEL_SAVE}` which stores a resumeable Megatron-LM distributed checkpoint. To export
61106
Hugging Face-Like quantized checkpoint for TensorRT-LLM, vLLM, or SGLang deployement,
62107
provide `${EXPORT_DIR}` to `export.sh`.
@@ -71,13 +116,12 @@ provide `${EXPORT_DIR}` to `export.sh`.
71116
```sh
72117
\
73118
TP=1 \
74-
HF_MODEL_CKPT=<pretrained_model_name_or_path> \
119+
MLM_MODEL_CKPT=<megatron_core_checkpoint> \
75120
MLM_MODEL_SAVE=/tmp/Llama-3.2-1B-Instruct_quant \
76121
./quantize.sh meta-llama/Llama-3.2-1B-Instruct NVFP4_DEFAULT_CFG
77122

78123
\
79124
PP=1 \
80-
HF_MODEL_CKPT=<pretrained_model_name_or_path> \
81125
MLM_MODEL_CKPT=/tmp/Llama-3.2-1B-Instruct_quant \
82126
EXPORT_DIR=/tmp/Llama-3.2-1B-Instruct_export \
83127
./export.sh meta-llama/Llama-3.2-1B-Instruct
@@ -89,7 +133,6 @@ export the model with flag `--export-vllm-fq`:
89133
\
90134
PP=1 \
91135
MLM_EXTRA_ARGS=--export-vllm-fq \
92-
HF_MODEL_CKPT=<pretrained_model_name_or_path> \
93136
MLM_MODEL_CKPT=/tmp/Llama-3.2-1B-Instruct_quant \
94137
EXPORT_DIR=/tmp/Llama-3.2-1B-Instruct_export \
95138
./export.sh meta-llama/Llama-3.2-1B-Instruct
@@ -115,14 +158,13 @@ via the auto-quantize arguments.
115158
```sh
116159
\
117160
TP=1 \
118-
HF_MODEL_CKPT=<pretrained_model_name_or_path> \
161+
MLM_MODEL_CKPT=<megatron_core_checkpoint> \
119162
MLM_MODEL_SAVE=/tmp/Llama-3.2-1B-Instruct_auto_quant \
120163
MLM_EXTRA_ARGS="--auto-quantize-bits 4.0" \
121164
./quantize.sh meta-llama/Llama-3.2-1B-Instruct auto
122165

123166
\
124167
PP=1 \
125-
HF_MODEL_CKPT=<pretrained_model_name_or_path> \
126168
MLM_MODEL_CKPT=/tmp/Llama-3.2-1B-Instruct_auto_quant \
127169
EXPORT_DIR=/tmp/Llama-3.2-1B-Instruct_auto_quant_export \
128170
./export.sh meta-llama/Llama-3.2-1B-Instruct

examples/post_training/modelopt/convert.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ if [ -z ${MLM_MODEL_CKPT} ]; then
2727
if [ -z ${HF_MODEL_CKPT} ]; then
2828
HF_MODEL_CKPT=${1}
2929
fi
30+
printf "${MLM_WARNING} Importing a Hugging Face checkpoint from convert.sh is deprecated.\n"
31+
printf "Use Megatron-Bridge to create a Megatron-Core checkpoint, then set ${PURPLE}MLM_MODEL_CKPT${WHITE}.\n"
32+
printf "For Hugging Face quantization workflows, see https://github.com/NVIDIA-NeMo/Megatron-Bridge/tree/main/examples/quantization\n"
3033
${LAUNCH_SCRIPT} ${SCRIPT_DIR}/convert_model.py \
3134
${MODEL_ARGS} \
3235
--tensor-model-parallel-size ${TP} \

examples/post_training/modelopt/convert_model.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,10 @@ def add_convert_args(parser):
3838
"""Add additional arguments for ModelOpt checkpoint convertion."""
3939
group = parser.add_argument_group(title='ModelOpt MCore checkpoint convertion')
4040
group.add_argument(
41-
"--pretrained-model-path", type=str, default=None, help="HuggingFace pretrained model"
41+
"--pretrained-model-path",
42+
type=str,
43+
default=None,
44+
help="Deprecated: Hugging Face pretrained model. Use Megatron-Bridge to import checkpoints.",
4245
)
4346
group.add_argument(
4447
"--extra-model-path", type=str, default=None, help="Extra module weights to load"
@@ -132,6 +135,14 @@ def check_arguments():
132135
unwrapped_model = unwrap_model(model)[0]
133136

134137
if args.pretrained_model_path is not None:
138+
warnings.warn(
139+
"Importing Hugging Face checkpoints with --pretrained-model-path is deprecated. "
140+
"Use Megatron-Bridge to create a Megatron-Core checkpoint, then load it with --load. "
141+
"For Hugging Face quantization workflows, see "
142+
"https://github.com/NVIDIA-NeMo/Megatron-Bridge/tree/main/examples/quantization.",
143+
FutureWarning,
144+
stacklevel=2,
145+
)
135146
import_dtype = torch.float16 if args.fp16 else torch.bfloat16
136147
unwrapped_model = unwrap_model(model)[0]
137148
workspace_dir = os.environ.get("MLM_WORK_DIR", "/tmp")

examples/rl/benchmark_refit.py

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,12 @@ def model_provider(pre_process=True, post_process=True, parallel_output=False,
7575
)
7676

7777

78-
def create_refit_service(method):
78+
def create_refit_service(method, execution_batch_bytes: int | None = None):
7979
"""Create and return a refit service instance."""
8080
if method == 'nvshmem':
8181
return NVSHMEMCopyService()
8282
elif method == 'nccl_m2n':
83-
return NCCLM2NCopyService()
83+
return NCCLM2NCopyService(max_group_bytes=execution_batch_bytes)
8484
elif method == 'nccl':
8585
return NCCLCopyService()
8686
elif method == 'gloo':
@@ -104,14 +104,26 @@ def print_config_summary(args, src_config, dst_config, world_size, mode):
104104
print_rank_0(f"{'='*80}\n")
105105

106106

107-
def run_benchmark(src_model, dst_model, refit_service, num_warmup, num_iterations):
107+
def run_benchmark(
108+
src_model,
109+
dst_model,
110+
refit_service,
111+
num_warmup,
112+
num_iterations,
113+
execution_batch_bytes: int | None = None,
114+
):
108115
"""Run warmup and benchmark iterations, return timings."""
109116
# Warmup (builds refit plan on first iteration)
110117
print_rank_0(f"Warmup: {num_warmup} iterations...")
111118
for i in range(num_warmup):
112119
torch.cuda.synchronize()
113120
torch.distributed.barrier()
114-
swap_model_weights(src_model, dst_model, refit_method=refit_service)
121+
swap_model_weights(
122+
src_model,
123+
dst_model,
124+
refit_method=refit_service,
125+
execution_batch_bytes=execution_batch_bytes,
126+
)
115127
torch.cuda.synchronize()
116128
torch.distributed.barrier()
117129

@@ -126,7 +138,12 @@ def run_benchmark(src_model, dst_model, refit_service, num_warmup, num_iteration
126138
torch.distributed.barrier()
127139

128140
start_time = time.perf_counter()
129-
swap_model_weights(src_model, dst_model, refit_method=refit_service)
141+
swap_model_weights(
142+
src_model,
143+
dst_model,
144+
refit_method=refit_service,
145+
execution_batch_bytes=execution_batch_bytes,
146+
)
130147
torch.cuda.synchronize()
131148
end_time = time.perf_counter()
132149

@@ -251,7 +268,9 @@ def benchmark_collocated():
251268

252269
# Create refit service
253270
print_rank_0(f"Creating {args.refit_method} service...")
254-
refit_service = create_refit_service(args.refit_method)
271+
refit_service = create_refit_service(
272+
args.refit_method, execution_batch_bytes=args.refit_execution_batch_bytes
273+
)
255274
print_rank_0("Service created.\n")
256275

257276
try:
@@ -261,6 +280,7 @@ def benchmark_collocated():
261280
refit_service,
262281
args.num_benchmark_warmup,
263282
args.num_benchmark_iterations,
283+
execution_batch_bytes=args.refit_execution_batch_bytes,
264284
)
265285
print_results(timings)
266286
finally:
@@ -361,7 +381,9 @@ def benchmark_non_collocated():
361381

362382
# Create refit service
363383
print_rank_0(f"Creating {args.refit_method} service...")
364-
refit_service = create_refit_service(args.refit_method)
384+
refit_service = create_refit_service(
385+
args.refit_method, execution_batch_bytes=args.refit_execution_batch_bytes
386+
)
365387
print_rank_0("Service created.\n")
366388

367389
try:
@@ -371,6 +393,7 @@ def benchmark_non_collocated():
371393
refit_service,
372394
args.num_benchmark_warmup,
373395
args.num_benchmark_iterations,
396+
execution_batch_bytes=args.refit_execution_batch_bytes,
374397
)
375398
print_results(timings)
376399
finally:

megatron/core/inference/config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -556,8 +556,9 @@ class InferenceConfig:
556556
enabled), then all DP ranks share the same sampling / generation seed.
557557
"""
558558

559-
async_sched_mode: AsyncScheduleMode = AsyncScheduleMode.LEGACY
560-
"""Mode used to schedule dynamic batching inference work."""
559+
async_sched_mode: AsyncScheduleMode = AsyncScheduleMode.ASYNC
560+
"""Mode used to schedule dynamic batching inference work. Defaults to async scheduling; use
561+
``AsyncScheduleMode.LEGACY`` to disable it."""
561562

562563
logprobs_mode: Literal['raw_logprobs', 'processed_logprobs'] = 'raw_logprobs'
563564
"""Whether returned log-probs are modified by the sampling parameters or not."""

0 commit comments

Comments
 (0)