B, H, n = 2, 8, 8192
X = torch.randn(B, H, n, d_h, device=d2l.try_gpu(), dtype=torch.float16)
def naive_heads(X):
i = torch.arange(X.shape[-2], device=X.device)
scores = X @ X.transpose(-1, -2) / math.sqrt(X.shape[-1])
scores.masked_fill_(i[None, :] > i[:, None], torch.finfo(X.dtype).min)
return torch.softmax(scores, dim=-1) @ X
def fused_heads(X):
with sdpa_kernel(SDPBackend.FLASH_ATTENTION):
return F.scaled_dot_product_attention(X, X, X, is_causal=True)
for name, f in [('naive', naive_heads), ('fused', fused_heads)]:
t, mem = wall_clock(f, X), peak_memory(f, X)
print(f'{name}: {t*1e3:6.2f} ms, peak memory {mem/2**20:7.1f} MiB')