Skip to content

Commit 8a83605

Browse files
authored
[training] fix: Stop profiler on rerun exit (#5943)
Signed-off-by: Yu Yao <yaoyu.094@gmail.com>
1 parent 9319463 commit 8a83605

2 files changed

Lines changed: 125 additions & 0 deletions

File tree

‎src/megatron/bridge/training/train.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,18 @@ def train(
547547
)
548548
if should_exit:
549549
nvtx_range_pop(suffix=f"training_step_{nvtx_step}")
550+
if (
551+
prof_config is not None
552+
and global_state.train_state.step < prof_config.profile_step_end
553+
and (prof is not None or nsys_nvtx_context is not None)
554+
):
555+
handle_profiling_stop(
556+
prof_config,
557+
prof_config.profile_step_end,
558+
torch.distributed.get_rank(),
559+
prof,
560+
nsys_nvtx_context,
561+
)
550562
break
551563

552564
# Enable forward pre-hooks after first set of forward and backward passes.

‎tests/unit_tests/training/test_pg_collection_wiring.py‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
from types import SimpleNamespace
1818
from unittest.mock import Mock
1919

20+
import pytest
21+
2022

2123
def test_train_step_accepts_pg_collection_argument():
2224
# Import locally to avoid import-time side effects in unrelated modules
@@ -192,6 +194,117 @@ def test_train_stops_nsys_profiler_when_skipped_iteration_reaches_profile_end(mo
192194
stop_nsys_profiler.assert_called_once()
193195

194196

197+
def test_train_stops_nsys_profiler_when_rerun_requests_exit(monkeypatch):
198+
"""A rerun-requested exit must close an active Nsys capture."""
199+
from megatron.bridge.training import profiling as profiling_module
200+
from megatron.bridge.training import train as train_module
201+
202+
profiling = SimpleNamespace(
203+
use_pytorch_profiler=False,
204+
use_nsys_profiler=True,
205+
profile_step_start=0,
206+
profile_step_end=2,
207+
profile_ranks=[0],
208+
record_shapes=False,
209+
)
210+
config = SimpleNamespace(
211+
train=SimpleNamespace(
212+
manual_gc=False,
213+
check_weight_hash_across_dp_replicas_interval=None,
214+
train_iters=2,
215+
micro_batch_size=1,
216+
iterations_to_skip=set(),
217+
),
218+
validation=SimpleNamespace(eval_interval=0, start_eval_at_iter=None),
219+
profiling=profiling,
220+
straggler=None,
221+
ddp=SimpleNamespace(use_megatron_fsdp=False, overlap_param_gather=False),
222+
optimizer=SimpleNamespace(
223+
use_distributed_optimizer=False,
224+
optimizer_cuda_graph=False,
225+
),
226+
model=SimpleNamespace(
227+
virtual_pipeline_model_parallel_size=None,
228+
cuda_graph_warmup_steps=0,
229+
cuda_graph_use_single_mempool=False,
230+
moe_expert_rank_capacity_factor=None,
231+
),
232+
logger=SimpleNamespace(log_throughput_to_tensorboard=False),
233+
checkpoint=SimpleNamespace(save=None, save_interval=None),
234+
tensor_inspect=None,
235+
)
236+
state = SimpleNamespace(
237+
cfg=config,
238+
train_state=SimpleNamespace(
239+
step=0,
240+
consumed_train_samples=0,
241+
skipped_train_samples=0,
242+
floating_point_operations_so_far=0,
243+
),
244+
timers=Mock(),
245+
straggler_timer=Mock(),
246+
energy_monitor=None,
247+
nvrx_straggler_manager=None,
248+
tensorboard_logger=None,
249+
wandb_logger=None,
250+
_comet_logger=None,
251+
)
252+
model_config = SimpleNamespace(cuda_graph_impl=None)
253+
rerun_state_machine = SimpleNamespace(current_iteration=0)
254+
data_distribution_group = SimpleNamespace(size=lambda: 1)
255+
pg_collection = SimpleNamespace(
256+
dp=data_distribution_group,
257+
pp=SimpleNamespace(size=lambda: 1),
258+
)
259+
checkpoint_manager = Mock()
260+
nsys_context = Mock()
261+
start_nsys_profiler = Mock(return_value=nsys_context)
262+
stop_nsys_profiler = Mock()
263+
264+
monkeypatch.setattr(train_module, "get_model_config", lambda _model: model_config)
265+
monkeypatch.setattr(train_module, "get_rerun_state_machine", lambda: rerun_state_machine)
266+
monkeypatch.setattr(train_module, "get_num_microbatches", lambda: 1)
267+
monkeypatch.setattr(train_module, "update_num_microbatches", lambda *args, **kwargs: None)
268+
monkeypatch.setattr(train_module, "get_data_distribution_group", lambda *args, **kwargs: data_distribution_group)
269+
monkeypatch.setattr(train_module, "should_disable_forward_pre_hook", lambda *args: False)
270+
monkeypatch.setattr(train_module, "prepare_forward_step_func", lambda *args: Mock())
271+
monkeypatch.setattr(train_module, "get_forward_backward_func", lambda **kwargs: Mock())
272+
monkeypatch.setattr(train_module, "is_full_iteration_cuda_graph", lambda _config: False)
273+
monkeypatch.setattr(train_module, "P2PCommunicator", lambda **kwargs: Mock())
274+
monkeypatch.setattr(train_module, "train_step", lambda *args: ({}, True, False, True, 16, None, None, None))
275+
monkeypatch.setattr(train_module, "_delete_cuda_graphs", lambda _helper: None)
276+
monkeypatch.setattr(train_module, "safe_shutdown_nvrx_straggler_manager", lambda _manager: None)
277+
monkeypatch.setattr(train_module, "tensor_inspect_step_if_enabled", lambda _config: None)
278+
monkeypatch.setattr(train_module, "tensor_inspect_end_if_enabled", lambda _config: None)
279+
monkeypatch.setattr(train_module, "should_fire", lambda *args: False)
280+
monkeypatch.setattr(train_module, "nvtx_range_push", lambda **kwargs: None)
281+
monkeypatch.setattr(train_module, "nvtx_range_pop", lambda **kwargs: None)
282+
monkeypatch.setattr(train_module.torch.distributed, "get_rank", lambda: 0)
283+
monkeypatch.setattr(profiling_module, "start_nsys_profiler", start_nsys_profiler)
284+
monkeypatch.setattr(profiling_module, "stop_nsys_profiler", stop_nsys_profiler)
285+
monkeypatch.setattr(train_module.fault_tolerance, "on_checkpointing_start", lambda _state: None)
286+
monkeypatch.setattr(train_module.fault_tolerance, "on_checkpointing_end", lambda **kwargs: None)
287+
monkeypatch.setattr(train_module.fault_tolerance, "on_training_step_start", lambda _state: None)
288+
monkeypatch.setattr(train_module.fault_tolerance, "on_training_step_end", lambda _state: None)
289+
monkeypatch.setattr(train_module.fault_tolerance, "shutdown", lambda _state: None)
290+
291+
with pytest.raises(SystemExit, match="16"):
292+
train_module.train(
293+
forward_step_func=Mock(),
294+
model=[Mock()],
295+
optimizer=Mock(),
296+
scheduler=Mock(),
297+
train_data_iterator=None,
298+
valid_data_iterator=None,
299+
global_state=state,
300+
checkpoint_manager=checkpoint_manager,
301+
pg_collection=pg_collection,
302+
)
303+
304+
start_nsys_profiler.assert_called_once_with(profiling)
305+
stop_nsys_profiler.assert_called_once_with(nsys_context)
306+
307+
195308
def test_first_skipped_iteration_preserves_cuda_graph_hook_bootstrap(monkeypatch):
196309
"""A dummy first iteration must not strand parameter-gather hook initialization."""
197310
from megatron.bridge.training import train as train_module

0 commit comments

Comments
 (0)