|
17 | 17 | from types import SimpleNamespace |
18 | 18 | from unittest.mock import Mock |
19 | 19 |
|
| 20 | +import pytest |
| 21 | + |
20 | 22 |
|
21 | 23 | def test_train_step_accepts_pg_collection_argument(): |
22 | 24 | # 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 |
192 | 194 | stop_nsys_profiler.assert_called_once() |
193 | 195 |
|
194 | 196 |
|
| 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 | + |
195 | 308 | def test_first_skipped_iteration_preserves_cuda_graph_hook_bootstrap(monkeypatch): |
196 | 309 | """A dummy first iteration must not strand parameter-gather hook initialization.""" |
197 | 310 | from megatron.bridge.training import train as train_module |
|
0 commit comments