Skip to content

Commit 2d67a5e

Browse files
deepakn94claude
andauthored
Deduplicate GTP-replicated params with the optimizer's own GTP group (#7359)
Signed-off-by: Deepak Narayanan <dnarayanan@nvidia.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent bab851b commit 2d67a5e

7 files changed

Lines changed: 344 additions & 5 deletions

File tree

‎megatron/core/optimizer/__init__.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,11 @@ def init_state_fn(opt, config=None):
705705
# TODO(M4): plumb TP groups through optimizer constructors so these setattrs disappear.
706706
setattr(optimizer, 'tp_group', tp_group)
707707
setattr(optimizer, 'expert_tp_group', expert_tp_group)
708+
# The GTP axes this optimizer's params are sharded over. Taken from the collection rather
709+
# than MPU because a MIMO module owns its axes through its own grid and leaves the MPU
710+
# globals unset, where the duplicate filter would read rank 0 everywhere.
711+
setattr(optimizer, 'gtp_group', getattr(pg_collection, 'gtp_remat', None))
712+
setattr(optimizer, 'expert_gtp_group', getattr(pg_collection, 'expt_gtp_remat', None))
708713

709714
return optimizer
710715

@@ -930,6 +935,8 @@ def _get_megatron_emerging_optimizer(
930935
expert_tp_group = getattr(pg_collection, 'expt_tp', tp_group)
931936
setattr(optimizer, 'tp_group', tp_group)
932937
setattr(optimizer, 'expert_tp_group', expert_tp_group)
938+
setattr(optimizer, 'gtp_group', getattr(pg_collection, 'gtp_remat', None))
939+
setattr(optimizer, 'expert_gtp_group', getattr(pg_collection, 'expt_gtp_remat', None))
933940
results.append(optimizer)
934941
continue
935942
else:

‎megatron/core/optimizer/clip_grads.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ def count_zeros_fp32(
226226
use_decoupled_grad: bool = False,
227227
tp_group: Optional[torch.distributed.ProcessGroup] = None,
228228
expert_tp_group: Optional[torch.distributed.ProcessGroup] = None,
229+
gtp_group: Optional[torch.distributed.ProcessGroup] = None,
230+
expert_gtp_group: Optional[torch.distributed.ProcessGroup] = None,
229231
) -> float:
230232
"""Counts the number of zero values in the gradients of the given parameters.
231233
@@ -274,7 +276,9 @@ def count_zeros_fp32(
274276
is_not_tp_duplicate = param_is_not_tensor_parallel_duplicate(
275277
param, tp_group=tp_group, expert_tp_group=expert_tp_group
276278
)
277-
is_not_gtp_duplicate = param_is_not_gtp_duplicate(param)
279+
is_not_gtp_duplicate = param_is_not_gtp_duplicate(
280+
param, gtp_group=gtp_group, expert_gtp_group=expert_gtp_group
281+
)
278282
if grad_not_none and is_not_shared and is_not_tp_duplicate and is_not_gtp_duplicate:
279283
grad_obj = getattr(param, grad_attr)
280284
data_parallel_group = get_data_parallel_group_if_dtensor(grad_obj, data_parallel_group)

‎megatron/core/optimizer/layer_wise_optimizer.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,11 +668,17 @@ def __init__(
668668

669669
self.tp_group = self.pg_collection.tp
670670
self.expert_tp_group = getattr(self.pg_collection, 'expt_tp', self.tp_group)
671+
# The module's own GTP axes: a MIMO module's grid carries these, and MPU has no
672+
# globals to fall back on there (see param_is_not_gtp_duplicate).
673+
self.gtp_group = getattr(self.pg_collection, 'gtp_remat', None)
674+
self.expert_gtp_group = getattr(self.pg_collection, 'expt_gtp_remat', None)
671675
for optimizer in optimizers:
672676
# Child optimizers perform duplicate filtering and gradient-stat reductions.
673677
optimizer.grad_stats_parallel_group = self.grad_stats_parallel_group
674678
optimizer.tp_group = self.tp_group
675679
optimizer.expert_tp_group = self.expert_tp_group
680+
optimizer.gtp_group = self.gtp_group
681+
optimizer.expert_gtp_group = self.expert_gtp_group
676682

677683
super().__init__(optimizers)
678684

@@ -1118,6 +1124,8 @@ def count_zeros(self):
11181124
use_decoupled_grad=self.config.use_precision_aware_optimizer_no_fp8_or_ds_fp8,
11191125
tp_group=self.tp_group,
11201126
expert_tp_group=self.expert_tp_group,
1127+
gtp_group=self.gtp_group,
1128+
expert_gtp_group=self.expert_gtp_group,
11211129
)
11221130

11231131
def start_param_sync_for_bucket_group_subset(self) -> None:

‎megatron/core/optimizer/optimizer.py‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,11 @@ def _filter_grads_for_norm(
301301
tp_group=getattr(self, 'tp_group', None),
302302
expert_tp_group=getattr(self, 'expert_tp_group', None),
303303
)
304-
is_not_gtp_duplicate = tensor_parallel.param_is_not_gtp_duplicate(param)
304+
is_not_gtp_duplicate = tensor_parallel.param_is_not_gtp_duplicate(
305+
param,
306+
gtp_group=getattr(self, 'gtp_group', None),
307+
expert_gtp_group=getattr(self, 'expert_gtp_group', None),
308+
)
305309
if grad_not_none and is_not_shared and is_not_tp_duplicate and is_not_gtp_duplicate:
306310
grads_for_norm.append(grad)
307311
return grads_for_norm
@@ -464,6 +468,8 @@ def count_zeros(self) -> float:
464468
use_decoupled_grad=self._uses_decoupled_grad(params),
465469
tp_group=getattr(self, 'tp_group', None),
466470
expert_tp_group=getattr(self, 'expert_tp_group', None),
471+
gtp_group=getattr(self, 'gtp_group', None),
472+
expert_gtp_group=getattr(self, 'expert_gtp_group', None),
467473
)
468474

469475
@abstractmethod
@@ -1901,6 +1907,8 @@ def count_zeros(self):
19011907
),
19021908
tp_group=getattr(self.chained_optimizers[0], 'tp_group', None),
19031909
expert_tp_group=getattr(self.chained_optimizers[0], 'expert_tp_group', None),
1910+
gtp_group=getattr(self.chained_optimizers[0], 'gtp_group', None),
1911+
expert_gtp_group=getattr(self.chained_optimizers[0], 'expert_gtp_group', None),
19041912
)
19051913
else:
19061914
num_zeros_in_grad = 0

‎megatron/core/tensor_parallel/layers.py‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,26 @@ def copy_gtp_attributes(destination, source):
121121
setattr(destination, attr, getattr(source, attr))
122122

123123

124-
def param_is_not_gtp_duplicate(param):
124+
def param_is_not_gtp_duplicate(param, gtp_group=None, expert_gtp_group=None):
125125
"""True if the param's grad is counted once across the GTP_remat/EGTP_remat axis.
126126
127127
GTP_remat/EGTP_remat shards are unique per peer (kept); replicated params counted only on
128128
rank 0 of the gtp_remat/egtp_remat axis (else counted N times). When GTP_remat is off rank is 0,
129129
so every param is kept.
130+
131+
Pass the group that owns the param's GTP axis. The MPU fallback below is only correct for
132+
callers whose axis is the global one: a module carrying its own grid (MIMO builds every
133+
module's ``gtp_remat`` group in its HyperCommGrid and never initializes the MPU globals)
134+
reads rank 0 on every rank there, which keeps every replicated param on every peer.
130135
"""
131136
if getattr(param, "is_gtp_weight_remat", False):
132137
return True
133138
is_expert = not getattr(param, "allreduce", True)
139+
group = expert_gtp_group if is_expert else gtp_group
140+
# Prefer provided group when available (new explicit path).
141+
if group is not None:
142+
return group.rank() == 0
143+
# Fallback to legacy global state (back-compat).
134144
if is_expert:
135145
return get_expert_gtp_weight_remat_rank() == 0
136146
return get_gtp_weight_remat_rank() == 0

‎tests/unit_tests/determinism/kernels/manifest.py‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,10 @@ class KernelEntry:
251251
KernelEntry(
252252
name="tensor_parallel_layers",
253253
sources=("megatron/core/tensor_parallel/layers.py",),
254-
tests=(K + "test_tensor_parallel_kernels.py",),
254+
tests=(
255+
K + "test_tensor_parallel_kernels.py",
256+
"tests/unit_tests/optimizer/test_grad_norm_gtp_invariance.py",
257+
),
255258
kind="torch-op",
256259
notes="VocabParallelEmbedding (weight[idx] deterministic branch vs F.embedding) and local Column/RowParallelLinear "
257260
"incl. apex fused_weight_gradient_mlp_cuda gradient-accumulation fusion.",
@@ -468,7 +471,10 @@ class KernelEntry:
468471
"megatron/core/optimizer/optimizer.py",
469472
"megatron/training/utils/common_utils.py",
470473
),
471-
tests=(K + "test_optimizer_kernels.py",),
474+
tests=(
475+
K + "test_optimizer_kernels.py",
476+
"tests/unit_tests/optimizer/test_grad_norm_gtp_invariance.py",
477+
),
472478
kind="external-lib",
473479
notes="multi_tensor l2norm / scale (TE, apex or local fallback) and fused Adam; "
474480
"optimizer.py (gradient unscaling) and training/utils/common_utils.py (param / grad norm "

0 commit comments

Comments
 (0)