in blocksparse/transformer.py [0:0]
def __init__(self, layout, block_size=64, heads=None, mask_callback=None, name=None):
if len(layout.shape) == 2:
assert heads is not None, "heads must be explicitly specified when using shared layouts per head"
# broadcast same layout over all heads
layout = np.expand_dims(layout, 0)
if heads is None:
heads = layout.shape[0]
assert block_size in (8,16,32,64), "Block sizes of 8, 16, 32 and 64 currently supported"
assert len(layout.shape) == 3, "bad layout shape: " + str(layout.shape)
#self.layout = layout > 0 # save boolean version for serialization purposes, TODO: save packbits or csr version
self.blk_size = block_size
self.name = name
self.heads = heads
self.lut_heads = layout.shape[0]
self.ctx_blks_q = layout.shape[1]
self.ctx_blks_k = layout.shape[2]
self.blk_shape = (block_size, block_size)
self.nn_max = 0
self.tn_max = 0
self.softmax_dtype = None
if layout.dtype != np.int32:
layout = layout.astype(np.int32)
self.nt_lut = list()
self.nn_lut = list()
self.tn_lut = list()
self.nt_list = list()
self.nn_list = list()
self.tn_list = list()
blocks = None
for head in range(layout.shape[0]):
# convert to csr for vastly more efficient python iteration on large sparse layouts
csr = sparse.csr_matrix(layout[head,:,:])
ys, xs, bs = sparse.find(csr) # xs is in sorted order by default
if blocks is None:
blocks = len(bs)
else:
assert len(bs) == blocks, "number of layout blocks must be equal across heads"
# make blocks contiguous along the rows (softmax code leverages this for increased performance)
nt_list = sorted( zip(ys, xs) )
ys = [b[0] for b in nt_list]
xs = [b[1] for b in nt_list]
nt_lut = np.array(nt_list, dtype=np.int32)
nn_lut, nn_list, nn_max = self.xn_lut(ys, xs, blocks, self.ctx_blks_q)
tn_lut, tn_list, tn_max = self.xn_lut(xs, ys, blocks, self.ctx_blks_k)
self.nt_lut.append(nt_lut)
self.nn_lut.append(nn_lut)
self.tn_lut.append(tn_lut)
self.nt_list.append(nt_list)
self.nn_list.append(nn_list)
self.tn_list.append(tn_list)
self.nn_max = max(self.nn_max, nn_max)
self.tn_max = max(self.tn_max, tn_max)
self.blocks = blocks
self.nt_lut = np.array(self.nt_lut, dtype=np.int32)
self.nn_lut = np.array(self.nn_lut, dtype=np.int32)
self.tn_lut = np.array(self.tn_lut, dtype=np.int32)
if mask_callback is not None:
self.init_softmax_mask(mask_callback)
else:
self.softmax_mask = None
self.softmax_mask_np = None