Victarry commited on
Commit
0a0d256
·
1 Parent(s): 592da35

Add support to set custom stage time.

Browse files
Files changed (1) hide show
  1. app.py +130 -3
app.py CHANGED
@@ -292,6 +292,35 @@ timing_params_card = dbc.Card([
292
  ])
293
  ], style=card_style)
294
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  # Updated app layout with improved structure
296
  app.layout = html.Div([
297
  header,
@@ -346,6 +375,7 @@ app.layout = html.Div([
346
  basic_params_card,
347
  scheduling_params_card,
348
  timing_params_card,
 
349
 
350
  # Generate button with better styling
351
  dbc.Button([
@@ -521,6 +551,75 @@ def toggle_advanced_options(n_clicks, is_open):
521
  return not is_open
522
  return is_open
523
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  # --- Client-side Callback for Strategy Card Selection ---
525
  app.clientside_callback(
526
  """
@@ -576,12 +675,14 @@ app.clientside_callback(
576
  State('op_time_overlapped_fwd_bwd', 'value'),
577
  State('microbatch_group_size_per_vp_stage', 'value'),
578
  State('selected-strategies-store', 'data'),
 
 
579
  prevent_initial_call=True
580
  )
581
  def update_graph(n_clicks, num_devices, num_stages, num_batches, p2p_latency,
582
  op_time_forward, op_time_backward, op_time_backward_d, op_time_backward_w,
583
  op_time_overlapped_fwd_bwd, microbatch_group_size_per_vp_stage,
584
- selected_strategies):
585
 
586
  strategy_display_order = ["1f1b", "1f1b_interleave", "1f1b_overlap", "1f1b_interleave_overlap", "dualpipe", "zb1p"]
587
 
@@ -669,14 +770,40 @@ def update_graph(n_clicks, num_devices, num_stages, num_batches, p2p_latency,
669
  if adjustment_msg not in automatic_adjustments:
670
  automatic_adjustments.append(adjustment_msg)
671
 
672
- op_times = { "forward": float(op_time_forward) * time_scale_factor }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
 
 
674
  if split_backward:
675
  op_times["backward_D"] = float(op_time_backward_d) * time_scale_factor
676
  op_times["backward_W"] = float(op_time_backward_w) * time_scale_factor
677
  op_times["backward"] = (float(op_time_backward_d) + float(op_time_backward_w)) * time_scale_factor
678
  else:
679
- op_times["backward"] = float(op_time_backward) * time_scale_factor
 
 
 
 
 
 
 
 
 
 
680
 
681
  if op_time_overlapped_fwd_bwd is not None:
682
  try:
 
292
  ])
293
  ], style=card_style)
294
 
295
+ # Per-stage timing configuration card
296
+ per_stage_timing_card = dbc.Card([
297
+ dbc.CardBody([
298
+ html.H5([
299
+ html.I(className="bi bi-list-ol section-icon"),
300
+ "Per-Stage Timing Configuration"
301
+ ], className="section-title"),
302
+
303
+ dbc.Button([
304
+ html.I(className="bi bi-sliders2 me-2"),
305
+ "Customize Per-Stage Timing"
306
+ ],
307
+ id="per-stage-timing-toggle",
308
+ color="light",
309
+ className="mb-3 w-100",
310
+ size="sm"
311
+ ),
312
+
313
+ dbc.Collapse([
314
+ dbc.Alert([
315
+ html.I(className="bi bi-info-circle-fill me-2"),
316
+ "Override global timing values for individual stages. Leave empty to use global values."
317
+ ], color="info", className="mb-3"),
318
+
319
+ html.Div(id='per-stage-inputs-container', children=[])
320
+ ], id="per-stage-timing-collapse", is_open=False)
321
+ ])
322
+ ], style=card_style)
323
+
324
  # Updated app layout with improved structure
325
  app.layout = html.Div([
326
  header,
 
375
  basic_params_card,
376
  scheduling_params_card,
377
  timing_params_card,
378
+ per_stage_timing_card,
379
 
380
  # Generate button with better styling
381
  dbc.Button([
 
551
  return not is_open
552
  return is_open
553
 
554
+ # --- Callback to toggle Per-Stage Timing Collapse ---
555
+ @app.callback(
556
+ Output("per-stage-timing-collapse", "is_open"),
557
+ Input("per-stage-timing-toggle", "n_clicks"),
558
+ State("per-stage-timing-collapse", "is_open"),
559
+ prevent_initial_call=True,
560
+ )
561
+ def toggle_per_stage_timing(n_clicks, is_open):
562
+ if n_clicks:
563
+ return not is_open
564
+ return is_open
565
+
566
+ # --- Callback to dynamically generate per-stage timing inputs ---
567
+ @app.callback(
568
+ Output("per-stage-inputs-container", "children"),
569
+ Input("num_stages", "value"),
570
+ )
571
+ def generate_per_stage_inputs(num_stages):
572
+ if num_stages is None or num_stages < 1:
573
+ return []
574
+
575
+ # Limit to reasonable number of stages for UI
576
+ num_stages = min(int(num_stages), 32)
577
+
578
+ stage_inputs = []
579
+ for stage_id in range(num_stages):
580
+ stage_inputs.append(
581
+ dbc.Row([
582
+ dbc.Col([
583
+ html.Strong(f"Stage {stage_id}", className="text-muted")
584
+ ], width=2, className="d-flex align-items-center"),
585
+ dbc.Col([
586
+ dbc.InputGroup([
587
+ dbc.InputGroupText("F", style={"minWidth": "30px"}),
588
+ dbc.Input(
589
+ id={"type": "stage-forward", "index": stage_id},
590
+ type="number",
591
+ placeholder="1.0",
592
+ min=0.01,
593
+ step=0.01,
594
+ size="sm"
595
+ ),
596
+ ], size="sm")
597
+ ], width=5),
598
+ dbc.Col([
599
+ dbc.InputGroup([
600
+ dbc.InputGroupText("B", style={"minWidth": "30px"}),
601
+ dbc.Input(
602
+ id={"type": "stage-backward", "index": stage_id},
603
+ type="number",
604
+ placeholder="1.0",
605
+ min=0.01,
606
+ step=0.01,
607
+ size="sm"
608
+ ),
609
+ ], size="sm")
610
+ ], width=5),
611
+ ], className="mb-2 g-2")
612
+ )
613
+
614
+ # Add header row
615
+ header = dbc.Row([
616
+ dbc.Col([html.Small("Stage", className="text-muted fw-bold")], width=2),
617
+ dbc.Col([html.Small("Forward Time", className="text-muted fw-bold")], width=5),
618
+ dbc.Col([html.Small("Backward Time", className="text-muted fw-bold")], width=5),
619
+ ], className="mb-2")
620
+
621
+ return [header] + stage_inputs
622
+
623
  # --- Client-side Callback for Strategy Card Selection ---
624
  app.clientside_callback(
625
  """
 
675
  State('op_time_overlapped_fwd_bwd', 'value'),
676
  State('microbatch_group_size_per_vp_stage', 'value'),
677
  State('selected-strategies-store', 'data'),
678
+ State({'type': 'stage-forward', 'index': ALL}, 'value'),
679
+ State({'type': 'stage-backward', 'index': ALL}, 'value'),
680
  prevent_initial_call=True
681
  )
682
  def update_graph(n_clicks, num_devices, num_stages, num_batches, p2p_latency,
683
  op_time_forward, op_time_backward, op_time_backward_d, op_time_backward_w,
684
  op_time_overlapped_fwd_bwd, microbatch_group_size_per_vp_stage,
685
+ selected_strategies, stage_forward_values, stage_backward_values):
686
 
687
  strategy_display_order = ["1f1b", "1f1b_interleave", "1f1b_overlap", "1f1b_interleave_overlap", "dualpipe", "zb1p"]
688
 
 
770
  if adjustment_msg not in automatic_adjustments:
771
  automatic_adjustments.append(adjustment_msg)
772
 
773
+ # Check if per-stage timing values are provided
774
+ has_per_stage_forward = stage_forward_values and any(v is not None for v in stage_forward_values)
775
+ has_per_stage_backward = stage_backward_values and any(v is not None for v in stage_backward_values)
776
+
777
+ # Build forward timing - either per-stage dict or global value
778
+ if has_per_stage_forward:
779
+ forward_times = {}
780
+ for stage_id in range(current_num_stages):
781
+ if stage_id < len(stage_forward_values) and stage_forward_values[stage_id] is not None:
782
+ forward_times[stage_id] = float(stage_forward_values[stage_id]) * time_scale_factor
783
+ else:
784
+ # Use global value as fallback (default 1.0 if not specified)
785
+ forward_times[stage_id] = float(op_time_forward if op_time_forward else 1.0) * time_scale_factor
786
+ op_times = {"forward": forward_times}
787
+ else:
788
+ op_times = {"forward": float(op_time_forward) * time_scale_factor}
789
 
790
+ # Build backward timing
791
  if split_backward:
792
  op_times["backward_D"] = float(op_time_backward_d) * time_scale_factor
793
  op_times["backward_W"] = float(op_time_backward_w) * time_scale_factor
794
  op_times["backward"] = (float(op_time_backward_d) + float(op_time_backward_w)) * time_scale_factor
795
  else:
796
+ if has_per_stage_backward:
797
+ backward_times = {}
798
+ for stage_id in range(current_num_stages):
799
+ if stage_id < len(stage_backward_values) and stage_backward_values[stage_id] is not None:
800
+ backward_times[stage_id] = float(stage_backward_values[stage_id]) * time_scale_factor
801
+ else:
802
+ # Use global value as fallback (default 1.0 if not specified)
803
+ backward_times[stage_id] = float(op_time_backward if op_time_backward else 1.0) * time_scale_factor
804
+ op_times["backward"] = backward_times
805
+ else:
806
+ op_times["backward"] = float(op_time_backward) * time_scale_factor
807
 
808
  if op_time_overlapped_fwd_bwd is not None:
809
  try: