def bst_deconv_layout()

in blocksparse/utils.py [0:0]


def bst_deconv_layout(output_h=1, output_w=1, filter_h=1, filter_w=1, stride=1, blk_size=32, autoregressive=True):

    H = output_h
    W = output_w
    R = filter_h
    S = filter_w

    assert H % stride == 0 or H == 1
    assert W % stride == 0

    P = H // stride or 1
    Q = W // stride

    if H == 1:
        R = 1
        pad_r = 0
    else:
        pad_r = -1
        for r in range(R):
            if P == out_dim(R, H, r, stride):
                pad_r = backward_pad(R,r)
                break
    assert pad_r >= 0, "Even size filters only work with stride 2."

    pad_s = -1
    for s in range(S):
        if Q == out_dim(S, W, s, stride):
            pad_s = backward_pad(S,s)
            break
    assert pad_s >= 0, "Even size filters only work with stride 2."

    print(f"P:{P} Q:{Q} H:{H} W:{W} R:{R} S:{S} std:{stride} pad_r:{pad_r} pad_s:{pad_s}")

    assert P*Q % blk_size == 0, f"P:{P} Q:{Q}"
    assert H*W % blk_size == 0, f"H:{H} W:{W}"

    mask_set = set()
    layout = np.zeros((H*W//blk_size, P*Q//blk_size), dtype=np.bool)

    # just compute the output pixels within the tile
    for h, w in np.ndindex(H, W):
        for     p in deconv_slice(h, P, R, pad_r, stride):
            for q in deconv_slice(w, Q, S, pad_s, stride):
                y = h*W + w
                x = p*Q + q
                if not autoregressive or y >= p*stride*Q*stride + q*stride:
                    layout[y//blk_size, x//blk_size] = 1
                    mask_set.add((y, x))

    def cb(blk_shape, head_idx, qry_idx, key_idx, blk_idx):
        mask = np.zeros(blk_shape, dtype=np.bool)

        q0 = qry_idx*blk_shape[0]
        k0 = key_idx*blk_shape[1]
        for q, k in np.ndindex(blk_shape):
            if (q0 + q, k0 + k) in mask_set:
                mask[q, k] = 1
        return mask

    return layout, cb