1818
1919Prerequisites:
2020First, you must run the quantization process to create a quantized checkpoint:
21- torchrun --nproc_per_node 2 examples/quantization/quantize.py --megatron-save-path ./quantized_megatron_checkpoint --tp 2
21+ torchrun --nproc_per_node 2 examples/quantization/quantize.py \
22+ --hf-model-id meta-llama/Llama-3.2-1B --megatron-save-path ./quantized_megatron_checkpoint --tp 2
2223
2324The process is as follows:
24251. An AutoBridge is initialized from a pretrained Hugging Face model
27283. The model is exported to HuggingFace format using ModelOpt export utilities.
2829
2930Usage:
30- torchrun --nproc_per_node 2 examples/quantization/export.py --megatron-load-path ./quantized_megatron_checkpoint --export-dir ./hf_export --tp 2
31+ torchrun --nproc_per_node 2 examples/quantization/export.py --hf-model-id meta-llama/Llama-3.2-1B \
32+ --megatron-load-path ./quantized_megatron_checkpoint --export-dir ./hf_export --tp 2
3133"""
3234
3335import argparse
34- import os
35- import sys
3636import warnings
3737
3838import modelopt .torch .export as mtex
39+ import modelopt .torch .utils .distributed as dist
3940import torch
4041from megatron .core .utils import unwrap_model
41- from rich .console import Console
42+ from quantize_utils import (
43+ add_common_model_args ,
44+ build_bridge_and_provider ,
45+ console ,
46+ load_quantized_megatron_model ,
47+ print_parallelism_summary ,
48+ require_checkpoint ,
49+ require_torchrun ,
50+ )
4251
43- from megatron .bridge import AutoBridge
4452from megatron .bridge .models .decorators import torchrun_main
4553from megatron .bridge .models .hf_pretrained .utils import is_safe_repo
4654
4755
4856warnings .filterwarnings ("ignore" )
4957
50- HF_MODEL_ID = "meta-llama/Llama-3.2-1B"
51- console = Console ()
52-
5358
5459@torchrun_main
5560def main (
56- hf_model_id : str = HF_MODEL_ID ,
61+ hf_model_id : str ,
5762 tp : int = 1 ,
5863 pp : int = 1 ,
5964 ep : int = 1 ,
@@ -65,88 +70,50 @@ def main(
6570 trust_remote_code : bool | None = None ,
6671) -> None :
6772 """Export a quantized Megatron-LM checkpoint to HuggingFace format on multiple GPUs."""
68- if os .environ .get ("WORLD_SIZE" ) is None :
69- console .print ("This script must be launched with torchrun. Please run:" )
70- console .print (f"torchrun --nproc_per_node <gpus> { sys .argv [0 ]} " )
71- sys .exit (1 )
72-
73- # Check if the checkpoint path exists
74- if not os .path .exists (megatron_load_path ):
75- console .print (f"[red]Error: Quantized checkpoint path { megatron_load_path } does not exist![/red]" )
76- console .print ("[yellow]Please run the quantization process first:[/yellow]" )
77- console .print (
78- f"[yellow]torchrun --nproc_per_node { tp } examples/quantization/quantize.py --megatron-save-path { megatron_load_path } --tp { tp } [/yellow]"
79- )
80- sys .exit (1 )
81-
82- # Initialize bridge from HF model to get tokenizer and model structure
83- bridge = AutoBridge .from_hf_pretrained (
84- hf_model_id ,
85- trust_remote_code = is_safe_repo (
86- trust_remote_code = trust_remote_code ,
87- hf_path = hf_model_id ,
73+ require_torchrun ()
74+ require_checkpoint (
75+ megatron_load_path ,
76+ quantize_command = (
77+ f"torchrun --nproc_per_node { tp } examples/quantization/quantize.py "
78+ f"--hf-model-id { hf_model_id } --megatron-save-path { megatron_load_path } --tp { tp } "
8879 ),
8980 )
9081
91- # Get model provider and configure for multi-GPU execution
92- model_provider = bridge .to_megatron_provider (load_weights = False )
93- model_provider .tensor_model_parallel_size = tp
94- model_provider .pipeline_model_parallel_size = pp
95- model_provider .expert_model_parallel_size = ep
96- model_provider .expert_tensor_parallel_size = etp
97-
9882 # Convert dtype string to torch dtype
9983 dtype_map = {
10084 "bfloat16" : torch .bfloat16 ,
10185 "float16" : torch .float16 ,
10286 "float32" : torch .float32 ,
10387 }
10488 torch_dtype = dtype_map .get (dtype , torch .bfloat16 )
105- model_provider .pipeline_dtype = torch_dtype
10689
107- # Once all overrides are set, finalize the model provider to ensure the post initialization logic is run
108- model_provider .finalize ()
109- model_provider .initialize_model_parallel (seed = 0 )
110-
111- # Load the quantized model
112- megatron_model = bridge .load_megatron_model (
113- megatron_load_path ,
114- mp_overrides = {
115- "tensor_model_parallel_size" : tp ,
116- "pipeline_model_parallel_size" : pp ,
117- "expert_model_parallel_size" : ep ,
118- "expert_tensor_parallel_size" : etp ,
119- },
120- wrap_with_ddp = False ,
90+ # Initialize bridge from HF model to get tokenizer and model structure
91+ bridge , model_provider = build_bridge_and_provider (
92+ hf_model_id ,
93+ tp = tp ,
94+ pp = pp ,
95+ ep = ep ,
96+ etp = etp ,
97+ load_weights = False ,
98+ pipeline_dtype = torch_dtype ,
99+ trust_remote_code = trust_remote_code ,
121100 )
101+ megatron_model = load_quantized_megatron_model (bridge , megatron_load_path , tp = tp , pp = pp , ep = ep , etp = etp )
122102
123103 # Now we can check for rank
124- is_rank_0 = torch . distributed . get_rank () == 0
104+ is_rank_0 = dist . is_master ()
125105
106+ print_parallelism_summary (model_provider )
126107 if is_rank_0 :
127- console .print (f"[green]Tensor parallel size: { model_provider .tensor_model_parallel_size } [/green]" )
128- console .print (f"[green]Pipeline parallel size: { model_provider .pipeline_model_parallel_size } [/green]" )
129- console .print (f"[green]Expert parallel size: { model_provider .expert_model_parallel_size } [/green]" )
130- console .print (f"[green]Expert tensor parallel size: { model_provider .expert_tensor_parallel_size } [/green]" )
131108 console .print (f"[green]Loaded quantized model from: { megatron_load_path } [/green]" )
132109
133110 # Get the unwrapped model for export
134111 unwrapped_model = unwrap_model (megatron_model )[0 ]
135112
136- # Decide whether we are exporting only the extra_modules (e.g. EAGLE, Medusa).
137- # Only the last pp stage may have extra_modules, hence broadcast from the last rank.
113+ # Only the last pp stage may have extra_modules (e.g. EAGLE, Medusa), hence broadcast from the last rank.
138114 has_extra_modules = hasattr (unwrapped_model , "eagle_module" ) or hasattr (unwrapped_model , "medusa_heads" )
139-
140- # Broadcast from the last rank in case this is pipeline parallel
141- if torch .distributed .is_initialized ():
142- extra_modules_list = [has_extra_modules ]
143- torch .distributed .broadcast_object_list (
144- extra_modules_list ,
145- src = torch .distributed .get_world_size () - 1 ,
146- )
147- export_extra_modules_flag = extra_modules_list [0 ] if export_extra_modules else False
148- else :
149- export_extra_modules_flag = has_extra_modules if export_extra_modules else False
115+ has_extra_modules = dist .broadcast (has_extra_modules , src = dist .size () - 1 )
116+ export_extra_modules_flag = has_extra_modules if export_extra_modules else False
150117
151118 if is_rank_0 :
152119 console .print ("[green]Exporting to HuggingFace format...[/green]" )
@@ -173,14 +140,8 @@ def main(
173140 parser = argparse .ArgumentParser (
174141 description = "Export a quantized Megatron-LM checkpoint to HuggingFace format on multiple GPUs"
175142 )
176- parser .add_argument (
177- "--hf-model-id" , type = str , default = HF_MODEL_ID , help = "HuggingFace model ID for tokenizer and model structure"
178- )
143+ add_common_model_args (parser )
179144
180- parser .add_argument ("--tp" , type = int , default = 1 , help = "Tensor parallelism size" )
181- parser .add_argument ("--pp" , type = int , default = 1 , help = "Pipeline parallelism size" )
182- parser .add_argument ("--ep" , type = int , default = 1 , help = "Expert parallelism size" )
183- parser .add_argument ("--etp" , type = int , default = 1 , help = "Expert tensor parallelism size" )
184145 parser .add_argument (
185146 "--megatron-load-path" ,
186147 type = str ,
@@ -205,11 +166,6 @@ def main(
205166 choices = ["bfloat16" , "float16" , "float32" ],
206167 help = "Data type for export" ,
207168 )
208- parser .add_argument (
209- "--trust-remote-code" ,
210- action = "store_true" ,
211- help = "if trust_remote_code" ,
212- )
213169
214170 args = parser .parse_args ()
215171 main (
@@ -225,5 +181,4 @@ def main(
225181 args .trust_remote_code ,
226182 )
227183
228- if torch .distributed .is_initialized ():
229- torch .distributed .destroy_process_group ()
184+ dist .cleanup ()
0 commit comments