in blocksparse/nccl.py [0:0]
def group_allreduce(
grads, parms, search_strings=None, cast_map=None, cast_all=None, allreduce_op=allreduce, **allreduce_kwargs):
# if no grouping specified, create one group to reduce at the end (no overlap with compute)
if search_strings is None:
search_strings = ["group_allreduce_all"]
groups = [(names, list(), list()) for names in search_strings]
last_group_idx = len(groups) - 1
for i, (grad, param) in enumerate(zip(grads, parms)):
for j, (names, group16, group32) in enumerate(groups):
# each group can be a single string, or a list of strings
# TODO: support regex's
if isinstance(names, str):
names = (names,)
if j == last_group_idx or any(name in param.name for name in names):
if cast_all is not None:
grad = float_cast(grad, dtype=cast_all)
elif cast_map is not None and name in cast_map:
grad = float_cast(grad, dtype=cast_map[name])
if grad.dtype.base_dtype is tf.float16:
group16.append((i, grad, param))
else:
group32.append((i, grad, param))
break
for name, group16, group32 in groups:
count = 0
if isinstance(name, str):
str_name = name
else:
str_name = "_".join(name)
str_name = str_name.replace('/', '_')
for group in (group16, group32):
count += len(group)
if len(group) > 0:
if len(group) == 1:
concated = group[0][1]
else:
concated = tf.concat([tf.reshape(grad, [-1]) for _, grad, _ in group], 0, name="concat_"+str_name)
reduced = allreduce_op(concated, **allreduce_kwargs)
if len(group) == 1:
grads[group[0][0]] = reduced
else:
offset = 0
for i, grad, param in group:
size = param.shape.num_elements()
grads[i] = tf.reshape(reduced[offset: offset + size], param.shape)
offset += size
if count == 0:
print("Warning: no grads found for all_reduce group: ", name)
# grads modified in place, but return anyway
return grads