|
import torch |
|
|
|
|
|
def grab_first_if_tuple(x): |
|
if x.__class__.__name__ == "tuple": |
|
return x[0] |
|
else: |
|
return x |
|
|
|
|
|
def column_split(x, num_heads, head_size): |
|
"""Split a tensor with `num_heads` alongside the head dimension, instead of |
|
across heads. Fixed to three projections |
|
""" |
|
|
|
x_reshaped = x.reshape( |
|
x.shape[0], |
|
num_heads, |
|
3 * head_size, |
|
) |
|
|
|
x2, x1, v = ( |
|
x_reshaped[:, :, :head_size], |
|
x_reshaped[ |
|
:, |
|
:, |
|
head_size : 2 * head_size, |
|
], |
|
x_reshaped[:, :, 2 * head_size :], |
|
) |
|
x2, x1, v = ( |
|
x2.reshape(x2.shape[0], -1), |
|
x1.reshape(x1.shape[0], -1), |
|
v.reshape(v.shape[0], -1), |
|
) |
|
return x2, x1, v |
|
|
|
|
|
def get_init_from_string(init_str): |
|
if type(init_str) == str: |
|
if init_str == "torch.nn.init.zeros_": |
|
return torch.nn.init.zeros_ |
|
elif init_str == "torch.nn.init.xavier_uniform_": |
|
return torch.nn.init.xavier_uniform_ |
|
elif init_str == "torch.nn.init.xavier_normal_": |
|
return torch.nn.init.xavier_normal_ |
|
else: |
|
raise ValueError(f"Unrecognized init {init_str}") |
|
|
|
|
|
def print_rank_0(message, debug=False, end="\n"): |
|
"""Print from rank 0 only.""" |
|
if torch.distributed.is_initialized(): |
|
if torch.distributed.get_rank() == 0: |
|
print(message, flush=True, end=end) |
|
else: |
|
print(message, flush=True, end=end) |
|
|
|
|
|
class dotdict(dict): |
|
"""dot.notation access to dictionary attributes""" |
|
|
|
__getattr__ = dict.get |
|
__setattr__ = dict.__setitem__ |
|
__delattr__ = dict.__delitem__ |
|
|
|
|
|
def ensure_divisibility(numerator, denominator): |
|
"""Ensure that numerator is divisible by the denominator.""" |
|
assert numerator % denominator == 0, "{} is not divisible by {}".format(numerator, denominator) |
|
|
|
|
|
def divide(numerator, denominator): |
|
"""Ensure that numerator is divisible by the denominator and return |
|
the division value.""" |
|
ensure_divisibility(numerator, denominator) |
|
return numerator // denominator |
|
|
|
|
|
class VocabUtility: |
|
"""Split the vocabulary into `world_size` chunks amd return the |
|
first and last index of the vocabulary belonging to the `rank` |
|
partition: Note that indices in [first, last]""" |
|
|
|
@staticmethod |
|
def vocab_range_from_per_partition_vocab_size(per_partition_vocab_size, rank, world_size): |
|
index_f = rank * per_partition_vocab_size |
|
index_l = index_f + per_partition_vocab_size |
|
return index_f, index_l |
|
|
|
@staticmethod |
|
def vocab_range_from_global_vocab_size(global_vocab_size, rank, world_size): |
|
per_partition_vocab_size = divide(global_vocab_size, world_size) |
|
return VocabUtility.vocab_range_from_per_partition_vocab_size( |
|
per_partition_vocab_size, rank, world_size |
|
) |
|
|