Skip to content

Commit 87833e1

Browse files
committed
calculate grad norm wrt sub partitions
1 parent 17f36f1 commit 87833e1

2 files changed

Lines changed: 48 additions & 8 deletions

File tree

deepspeed/runtime/utils.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def check_using_norm(self, norm_group, reduce_overflow=True):
6767

6868
return bool(overflow)
6969

70-
def check(self, param_groups=None):
70+
def check(self, param_groups=None, raw_grads=False):
7171
params = []
7272
if param_groups is None:
7373
params = self.params
@@ -79,17 +79,18 @@ def check(self, param_groups=None):
7979
for param in group:
8080
params.append(param)
8181

82-
return self.has_overflow(params)
82+
return self.has_overflow(params, raw_grads)
8383

8484
# `params` is a list / generator of torch.Variable
85-
def has_overflow_serial(self, params):
85+
def has_overflow_serial(self, params, raw_grads=False):
8686
for i, p in enumerate(params):
87-
if p.grad is not None and self._has_inf_or_nan(p.grad.data, i):
87+
grad = p if raw_grads else p.grad
88+
if grad is not None and self._has_inf_or_nan(grad.data, i):
8889
return True
8990
return False
9091

91-
def has_overflow(self, params):
92-
overflow = self.has_overflow_serial(params)
92+
def has_overflow(self, params, raw_grads=False):
93+
overflow = self.has_overflow_serial(params, raw_grads)
9394
# Since each model parallel GPU carries only part of the model,
9495
# make sure overflow flag is synced across all the model parallel GPUs
9596
overflow_gpu = torch.cuda.ByteTensor([overflow])

deepspeed/runtime/zero/stage1.py

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from deepspeed.runtime.zero.utils import _initialize_parameter_parallel_groups
88
from deepspeed.runtime.fp16.loss_scaler import LossScaler, DynamicLossScaler
9-
from deepspeed.runtime.utils import get_grad_norm, CheckOverflow
9+
from deepspeed.runtime.utils import get_grad_norm, CheckOverflow, is_model_parallel_parameter
1010
from deepspeed.runtime.zero.config import ZERO_OPTIMIZATION_OPTIMIZER_STATES
1111
from deepspeed.utils import logger, log_dist
1212

@@ -642,7 +642,7 @@ def step(self, closure=None):
642642
partition_id = dist.get_rank(group=self.dp_process_group)
643643
for i, group in enumerate(self.fp16_groups):
644644
#TODO RS: update get grad norm to support sub partitions
645-
norm_groups.append(get_grad_norm(group, mpu=self.mpu))
645+
# norm_groups.append(get_grad_norm(group, mpu=self.mpu))
646646

647647
#RS: update free grads w.r.t. sub partitions
648648
#free gradients for all the parameters that are not updated by this process
@@ -667,6 +667,11 @@ def step(self, closure=None):
667667
self.free_grad_in_param_list(
668668
self.params_in_rank_sub_partitions[i][partition_id])
669669

670+
# calculate grad norm w.r.t. local sub partitions
671+
norm_groups.append(
672+
self.get_grad_norm_sub_partitions(local_grad_sub_partitions,
673+
mpu=self.mpu))
674+
670675
local_sub_partitions_grad_groups.append(local_grad_sub_partitions)
671676

672677
#RS: update unscale/clip with sub partitions
@@ -706,6 +711,40 @@ def step(self, closure=None):
706711

707712
return self.overflow
708713

714+
def get_grad_norm_sub_partitions(self, sub_partitions, mpu):
715+
norm_type = 2.0
716+
total_norm = 0.
717+
for partition in sub_partitions:
718+
if mpu is not None:
719+
# if (mpu.get_model_parallel_rank() == 0
720+
# ) or is_model_parallel_parameter(p):
721+
# param_norm = p.grad.data.float().norm(norm_type)
722+
# total_norm += param_norm.item()**norm_type
723+
raise NotImplementedError(
724+
"support grad norm of model parallel parameters")
725+
else:
726+
param_norm = partition.data.float().norm(norm_type)
727+
total_norm += param_norm.item()**norm_type
728+
729+
# Sum across all DP ranks who each have different grad sub-partitions
730+
total_norm_cuda = torch.cuda.FloatTensor([float(total_norm)])
731+
torch.distributed.all_reduce(total_norm_cuda,
732+
op=torch.distributed.ReduceOp.SUM,
733+
group=self.dp_process_group)
734+
735+
if mpu is not None:
736+
# Sum across all model parallel GPUs.
737+
torch.distributed.all_reduce(total_norm_cuda,
738+
op=torch.distributed.ReduceOp.SUM,
739+
group=mpu.get_model_parallel_group())
740+
741+
total_norm = total_norm_cuda[0].item()**(1. / norm_type)
742+
if total_norm == float(
743+
'inf') or total_norm == -float('inf') or total_norm != total_norm:
744+
total_norm = -1
745+
746+
return total_norm
747+
709748
def unscale_and_clip_grads(self, grad_groups_flat, norm_groups):
710749
total_norm = 0.0
711750
for norm in norm_groups:

0 commit comments

Comments
 (0)