B, H, n = 2, 8, 8192
X = jax.random.normal(jax.random.key(0), (B, n, H, d_h), dtype=jnp.float16)
def naive_heads(X):
Xt = X.transpose(0, 2, 1, 3)
i = jnp.arange(X.shape[1])
scores = Xt @ Xt.swapaxes(-1, -2) / math.sqrt(X.shape[-1])
scores = jnp.where(i[None, :] > i[:, None],
jnp.finfo(scores.dtype).min, scores)
return (jax.nn.softmax(scores, axis=-1) @ Xt).transpose(0, 2, 1, 3)
def fused_heads(X):
return jax.nn.dot_product_attention(X, X, X, is_causal=True,
implementation='cudnn')
for name, f in [('naive', naive_heads), ('fused', fused_heads)]:
jitted = jax.jit(f)
temp = jitted.lower(X).compile().memory_analysis().temp_size_in_bytes
print(f'{name}: {wall_clock(jitted, X)*1e3:6.2f} ms, '
f'XLA temp {temp/2**20:7.1f} MiB')