Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c810c32
initial commit of sub-quadratic attention source from https://github.…
Birch-san Dec 26, 2022
c9b3b9f
invoke efficient_dot_product_attention(). not currently giving correc…
Birch-san Dec 26, 2022
70dc50d
provide a way to skip checkpointing
Birch-san Dec 26, 2022
c794f0b
MPS fixes; now working
Birch-san Dec 26, 2022
04a5cbe
eliminate all einsums. assume 3D tensor [batch * num_heads, tokens, c…
Birch-san Dec 26, 2022
b44fa12
remove the bits that I broke in the pursuit of speed (mask, bias, wei…
Birch-san Dec 26, 2022
8694703
clarify comment; verified that upcast_attention is indeed still helpf…
Birch-san Dec 26, 2022
5bfe96d
add TODO about softmax
Birch-san Dec 26, 2022
da8901b
typings
Birch-san Dec 26, 2022
0c4d82f
simplify protocols
Birch-san Dec 26, 2022
c5e8e31
remove unused
Birch-san Dec 26, 2022
b16edc9
simplify protocol
Birch-san Dec 26, 2022
b7fc3a8
fix tensor shape destructuring
Birch-san Dec 26, 2022
8f003c2
simplify dynamic_slice
Birch-san Dec 26, 2022
1334670
simplify chunk scanning
Birch-san Dec 26, 2022
0676c13
inline sole use of map_pt function
Birch-san Dec 26, 2022
264dfb7
simplify
Birch-san Dec 26, 2022
205f55b
no longer using original utilities from memory-efficient-attention re…
Birch-san Dec 26, 2022
1880c0e
fix query slicing
Birch-san Dec 26, 2022
8603c30
fix kv chunking
Birch-san Dec 26, 2022
96e0d8c
simplify dynamic slicing
Birch-san Dec 26, 2022
63ca66d
removed bias, mask, weights, calc_fn, and the conditions controlling …
Birch-san Dec 26, 2022
f4c0bf4
device arg fix no longer included
Birch-san Dec 26, 2022
624123f
simplify
Birch-san Dec 26, 2022
5b92dab
clarify attributions now that algorithm has been substantially rewritten
Birch-san Dec 26, 2022
60f0a5e
add chunk_threshold_bytes to let you specify your safe memory limit, …
Birch-san Dec 28, 2022
48db711
fast path for when we're just attention-slicing (i.e. chunking query …
Birch-san Dec 28, 2022
ef20fb9
default kv_chunk_size was meant to be sqrt() of global key size, not …
Birch-san Dec 28, 2022
69a8d2e
remove debug notes
Birch-san Dec 28, 2022
db25934
explain kv fast-path
Birch-san Dec 28, 2022
7aa8bac
add fast-path for "1 query chunk"
Birch-san Dec 28, 2022
59002c3
move kv_chunk_size_min concern to callsite, since if caller knows fin…
Birch-san Dec 28, 2022
a3152d8
Revert "move kv_chunk_size_min concern to callsite (1c4f10748e31d1851…
Birch-san Dec 28, 2022
0eafb95
de-duplicate fast-path for "matmul < quota". we can just ask for ever…
Birch-san Dec 28, 2022
9dc6822
pre-transpose key, rather than transposing it then undoing the transp…
Birch-san Dec 30, 2022
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
eliminate all einsums. assume 3D tensor [batch * num_heads, tokens, c…
…hannels_per_head] in order to make use of batched matmuls. fuse multiply into matmul. breaks bias, mask in exchange for massive speedup.
  • Loading branch information
Birch-san committed Dec 30, 2022
commit 04a5cbe2865e83bfc93d5bdff2f8a756d1c98239
8 changes: 4 additions & 4 deletions src/diffusers/models/cross_attention.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,9 @@ def __call__(
key = attn.to_k(encoder_hidden_states)
value = attn.to_v(encoder_hidden_states)

query = query.unflatten(-1, (attn.heads, -1))
key = key.unflatten(-1, (attn.heads, -1))
value = value.unflatten(-1, (attn.heads, -1))
query = query.unflatten(-1, (attn.heads, -1)).transpose(1,2).flatten(end_dim=1)
key = key.unflatten(-1, (attn.heads, -1)).transpose(1,2).flatten(end_dim=1)
value = value.unflatten(-1, (attn.heads, -1)).transpose(1,2).flatten(end_dim=1)

dtype = query.dtype
# TODO: do we still need this given how we delay the division?
Expand All @@ -303,7 +303,7 @@ def __call__(
)
hidden_states = hidden_states.to(dtype)

hidden_states = hidden_states.flatten(2)
hidden_states = hidden_states.unflatten(0, (-1, attn.heads)).transpose(1,2).flatten(start_dim=2)

out_proj, dropout = attn.to_out
hidden_states = out_proj(hidden_states)
Expand Down
36 changes: 24 additions & 12 deletions src/diffusers/models/sub_quadratic_attention.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
# sparse broadcasting for bias, mask, weights
# flattened conditions for clarity
# Hyungon Ryu (device arg fix)
# Alex Birch (MPS support)
# Alex Birch
# option to forego checkpointing (not needed during inference)
# MPS support
# optimizations (batched matmul, fused multiply) (at the expense of support for mask + bias)
# implementation of:
# Self-attention Does Not Need O(n2) Memory":
# https://arxiv.org/abs/2112.05682v2
Expand All @@ -34,31 +37,40 @@ def _query_chunk_attention(query_idx, query, key, value,
v_features = value.shape[-1]
num_q = query.shape[-3]
key_chunk_size = min(key_chunk_size or int(math.sqrt(num_kv)), num_kv)
query = query / math.sqrt(k_features)
scale = k_features ** -0.5

def summarize_chunk(key_idx, query, key, value, mask, bias):
attn_weights = torch.einsum('...qhd,...khd->...qhk', query, key)
attn_weights = torch.baddbmm(
torch.empty(1, 1, 1, device=query.device, dtype=query.dtype),
query,
key.transpose(1,2),
alpha=scale,
beta=0,
)
if bias_calc_fn is not None:
raise "bias_calc_fn no longer supported" # lost support as a result of migrating to 3D tensors; needs to be reimplemented
bias = bias_calc_fn(query_idx, key_idx, bias, attn_weights, calc_fn_data)
if bias is not None:
raise "bias no longer supported" # lost support as a result of migrating to 3D tensors; needs to be reimplemented
bias = torch.einsum('...hqk->...qhk', bias)
attn_weights = attn_weights + bias
if mask_calc_fn is not None:
raise "mask_calc_fn no longer supported" # lost support as a result of migrating to 3D tensors; needs to be reimplemented
mask = mask_calc_fn(query_idx, key_idx, mask, attn_weights, calc_fn_data)
if mask is not None:
raise "mask no longer supported" # lost support as a result of migrating to 3D tensors; needs to be reimplemented
big_neg = torch.finfo(attn_weights.dtype).min
big_neg = torch.tensor(big_neg, device=mask.device, dtype=torch.float32)
mask = torch.einsum('...hqk->...qhk', mask)
attn_weights = torch.where(mask, attn_weights, big_neg)
if weights_calc_fn is not None:
raise "weights_calc_fn no longer supported" # lost support as a result of migrating to 3D tensors; needs to be reimplemented
attn_weights = weights_calc_fn(query_idx, key_idx, attn_weights, calc_fn_data)
attn_weights = attn_weights.contiguous() if attn_weights.device.type == 'mps' else attn_weights
max_score, _ = torch.max(attn_weights, -1, keepdim=True)
max_score = max_score.detach()
exp_weights = torch.exp(attn_weights - max_score)
exp_values = torch.einsum('...vhf,...qhv->...qhf', value, exp_weights)
max_score = torch.einsum('...qhk->...qh', max_score)
exp_values = exp_values.contiguous() if exp_values.device.type == 'mps' else exp_values
exp_values = torch.bmm(exp_weights, value)
max_score = max_score.squeeze(-1)
return exp_values, exp_weights.sum(dim=-1), max_score
summarizer = partial(checkpoint, summarize_chunk) if use_checkpoint else summarize_chunk

Expand Down Expand Up @@ -115,14 +127,13 @@ def efficient_dot_product_attention(query, key, value,
"""Computes efficient dot-product attention given query, key, and value.
This is efficient version of attention presented in
https://arxiv.org/abs/2112.05682v2 which comes with O(sqrt(n)) memory requirements.
Note: query, key, value needn't have any batch dimensions.
Args:
query: queries for calculating attention with shape of
`[batch..., q_length, num_heads, qk_depth_per_head]`.
`[batch * num_heads, tokens, channels_per_head]`.
key: keys for calculating attention with shape of
`[batch..., kv_length, num_heads, qk_depth_per_head]`.
`[batch * num_heads, tokens, channels_per_head]`.
value: values to be used in attention with shape of
`[batch..., kv_length, num_heads, v_depth_per_head]`.
`[batch * num_heads, tokens, channels_per_head]`.
bias: bias for the attention weights. This should be broadcastable to the
shape `[batch..., num_heads, q_length, kv_length]`.
This can be used for incorporating padding masks, proximity bias, etc.
Expand Down Expand Up @@ -150,8 +161,9 @@ def efficient_dot_product_attention(query, key, value,
calc_fn_data: optional pure data to pass to each per-chunk call of
bias_calc_fn, mask_calc_fn, and weights_calc_fn.
weights_calc_data: pure_data to pass with each call to weights_calc_fn
use_checkpoint: bool: whether to use checkpointing (recommended True for training, False for inference)
Returns:
Output of shape `[batch..., q_length, num_heads, v_depth_per_head]`.
Output of shape `[batch * num_heads, query_tokens, channels_per_head]`.
"""
num_q, num_heads, q_features = query.shape[-3:]
num_kv = key.shape[-3]
Expand Down