in blocksparse/matmul.py [0:0]
def __init__(self, layout, block_size=32, feature_axis=0, z_order=True, name=None):
if (feature_axis == 0 and block_size in (8,16,32)) or \
(feature_axis == 1 and block_size in (32,64)):
self.axis = feature_axis
self.bsize = block_size
else:
raise ValueError("Unsupported block size with this feature axis")
assert len(layout.shape) == 2
CB, KB = layout.shape
group_sizes = layout.sum(axis=0) # assume symetrical transpose
max_group = group_sizes.max()
min_group = group_sizes[np.nonzero(group_sizes)].min()
if max_group / min_group > 2.0:
segment_size = max(ceil_div(max_group,4), min_group*2)
else:
segment_size = SEG_MAX # not worth segmenting
#print(max_group, min_group, segment_size, KB)
#segment_size = SEG_MAX
# don't creat any segments smaller than this
seg_min = max(ceil_div(segment_size, 4), 4)
# segment_size = seg_min = 2
if layout.dtype != np.int32:
layout = layout.astype(np.int32)
# convert to csr for vastly more efficient python iteration on large matrices
csr = sparse.csr_matrix(layout)
cs, ks, vs = sparse.find(csr) # ks is in sorted order by default
blocks = len(vs)
idx = list(range(blocks))
idxT = sorted(idx, key=lambda i: cs[i]) # transpose view
# morton order (z-order) the blocks for efficient L2 cache utilization across all 3 ops
updat_list = list()
if z_order:
blk = 0
for _, i in sorted( [ (z_order_2d(cs[i], ks[i]), i) for i in range(blocks) ] ):
vs[i] = blk
updat_list.append((cs[i], ks[i]))
blk += 1
else:
# row contiguous
updat_list = list( zip(cs, ks) )
vs = list(range(blocks))
# cs = [b[0] for b in updat_list]
# ks = [b[1] for b in updat_list]
self.updat_list = updat_list
self.updat_lut = np.array(updat_list, dtype=np.int32)
fsetup = self.xprop_lut(KB, cs, ks, vs, idx, segment_size, seg_min)
bsetup = self.xprop_lut(CB, ks, cs, vs, idxT, segment_size, seg_min)
self.fprop_list, self.fprop_lut, self.l2_lut, self.fprop_shared, self.l2_shared, self.fprop_segments, self.fprop_locks = fsetup
self.bprop_list, self.bprop_lut, _, self.bprop_shared, _, self.bprop_segments, self.bprop_locks = bsetup
if name is None:
name = "BlocksparseMatMul"
self.z_order = z_order
self.name = name
self.flops = blocks * block_size * block_size * 2
self.blocks = blocks
self.w_shape = (blocks, block_size, block_size)
self.g_shape = (blocks,)
self.count = 0
self.CB = CB
self.KB = KB
self.C = CB * block_size
self.K = KB * block_size
self.sparsity = round(float(blocks) / float(CB * KB), 3)
# save boolean version for serialization purposes, TODO save csr version
self.layout = layout > 0