Writing / KERNELIZED

FlashAttention · Transformers · Attention · Compute

FlashAttention Kernel: Backward Pass (MATH)

Deriving attention gradients from tensor differentiation to a computable backward pass.

Preliminary

  • A∈Rs2s1A \in \mathbb{R}^{s_2 s_1} where s2s_2 and s1s_1 are the index set, for example in a 5D tensor A∈RijklmA \in \mathbb{R}^{ijklm} a possible index set could be s2={i,j}s_2 = \{ i, j \} and s1={k,l,m}s_1 = \{k, l, m \}.

  • Bs2s1=flashs1(Qs2s1,Ks3s1,Vs3s1)B_{s_2 s_1} = flash_{s_1}(Q_{s_2 s_1}, K_{s_3 s_1}, V_{s_3 s_1}) is a flash attention operation over s1 index set of tensor set <Q,K,V><Q, K, V>, and the resulting index set is the index set of QQ s.t. B∈Rs2s1B \in \mathbb{R}^{s_2 s_1}

Attention Operation

For this exercise we will simplify the target index sets to match the most common setup, i.e. Qs2s1∈R[M×d]Q_{s_2 s_1} \in \mathbb{R}^{[M \times d]}, Ks3s1∈R[N×d]K_{s_3 s_1} \in \mathbb{R}^{[N \times d]}, Vs3s1∈R[N×d]V_{s_3 s_1} \in \mathbb{R}^{[N \times d]}

Note: In this doc, whenever we have to denote the exact dimensions instead of index set it will be denoted as .[...×...×… ].^{[... \times ... \times \dots]} where ×\times symbol separates across different index sets.

Thus our operation becomes:

Bs2s1=attentions1(Qs2s1,Ks3s1,Vs3s1)B[M×d]=attentiond(Q[M×d],K[N×d],V[N×d])\begin{aligned}B_{s_2 s_1} = attention_{s_1}(Q_{s_2 s_1}, K_{s_3 s_1}, V_{s_3 s_1}) \\ B^{[M \times d]} = attention_{d}(Q^{[M \times d]}, K^{[N \times d]}, V^{[N \times d]}) \end{aligned}
S[M×N]=Q@KT=Q∗(M×d,N×d,M×N)K∈R[M×N]SrmaxM=max⁡NS[M×N]∈RMSrm[m,n]=S[m,n]−Srmaxm∀[m,n]∈[M×N]P[M×N]=softmaxN(Srm[M×N])O[M×d]=P@V=P∗(M×N,N×d,M×d)V∈R[M×d]\begin{aligned}S^{[M \times N]} = Q @ K^T = Q *_{(M \times d, N \times d, M \times N)} K \in \mathbb{R}^{[M \times N]} \\ S_{rmax}^{M} = \max_{N} S^{[M \times N]} \in \mathbb{R}^{M} \\ S_{rm}^{[m, n]} = S^{[m, n]} - S_{rmax}^{m} \forall [m, n] \in [M \times N] \\ P^{[M \times N]} = softmax_{N}(S_{rm}^{[M \times N]}) \\ O^{[M \times d]} = P @ V = P *_{(M \times N, N \times d, M \times d)} V \in \mathbb{R}^{[M \times d]} \end{aligned}

Note: Notation abuse -> O  ⟺  BO \iff B

For detailed Forward pass derivation please refer to my previous blog: FlashAttention Kernel: Forward Pass (MATH)

Backward (mode autodiff) Pass:

Bs2s1  ⟺  B[M×d]=attentiond(Q[M×d],K[N×d],V[N×d])\begin{aligned}B_{s_2 s_1} \iff B^{[M \times d]} = attention_{d}(Q^{[M \times d]}, K^{[N \times d]}, V^{[N \times d]}) \end{aligned}

For a given loss value Os3=ϕO_{s_3 = \phi} and known dBϕs2s1=dBs2s1dOs3=ϕdB_{\phi s_2 s_1} = \frac{dB_{s_2 s_1}}{dO_{s_3 = \phi}} We need to find out dQϕs2s1dQ_{\phi s_2 s_1}, dKϕs3s1dK_{\phi s_3 s_1}, and dVϕs3s1dV_{\phi s_3 s_1}.

Here we will directly differentiate the core attention operation without adjusting for numerical stability of exponent (we did so in forward pass to just make computation stable). Here we will first derive the core backward operations and then change it to computation, followed by mitigating any source of numerical instability.

dVϕs3s1dV_{\phi s_3 s_1}:

Consider following op: Bs2s1=∑s3Ps2s3⋅Vs3s1=P[M×N]@V[N×d]∈Rs2s1[M×d]B_{s_2 s_1} = \sum_{s_3} P_{s_2 s_3} \cdot V_{s_3 s_1} = P^{[M \times N]} @ V^{[N \times d]} \in \mathbb{R}^{[M \times d]}_{s_2 s_1}

dVϕs3′s1′=∂Oϕ∂Vs3′s1′=∑s2s1∂Oϕ∂Bs2s1∂Bs2s1∂Vs3′s1′=∑s2s1dBs2s1∂Bs2s1∂Vs3′s1′∂Bs2s1∂Vs3′s1′=∑s3Ps2s31(s3s1)=(s3′s1′)=Ps2s3′1s1=s1′∑s2s1dBs2s1∂Bs2s1∂Vs3′s1′=∑s2s1dBs2s1Ps2s3′1s1=s1′=∑s2dBs2s1′Ps2s3′dVϕs3′s1′=∑s2s1dBs2s1∂Bs2s1∂Vs3′s1′=∑s2dBs2s1′Ps2s3′=dBT⋅P\begin{aligned}dV_{\phi s'_3 s'_1} = \frac{\partial O_{\phi}}{\partial V_{s'_3 s'_1}} = \sum_{s_2 s_1} \frac{\partial O_{\phi}}{\partial B_{s_2 s_1}} \frac{\partial B_{s_2 s_1}}{\partial V_{s'_3 s'_1}} = \sum_{s_2 s_1} dB_{s_2 s_1} \frac{\partial B_{s_2 s_1}}{\partial V_{s'_3 s'_1}} \\ \frac{\partial B_{s_2 s_1}}{\partial V_{s'_3 s'_1}} = \sum_{s_3} P_{s_2 s_3} \mathbb{1}_{(s_3 s_1) = (s'_3 s'_1)} = P_{s_2 s'_3} \mathbb{1}_{s_1 = s'_1} \\ \sum_{s_2 s_1} dB_{s_2 s_1} \frac{\partial B_{s_2 s_1}}{\partial V_{s'_3 s'_1}} = \sum_{s_2 s_1} dB_{s_2 s_1} P_{s_2 s'_3} \mathbb{1}_{s_1 = s'_1} = \sum_{s_2} dB_{s_2 s'_1} P_{s_2 s'_3} \\ dV_{\phi s'_3 s'_1} = \sum_{s_2 s_1} dB_{s_2 s_1} \frac{\partial B_{s_2 s_1}}{\partial V_{s'_3 s'_1}} = \sum_{s_2} dB_{s_2 s'_1} P_{s_2 s'_3} = dB^T \cdot P \end{aligned}

Note: This also provides a crucial propetry of tensor differentiation i.e. for tensor product operation Cs2s3=∑s1As2s1Bs1s3=A⋅BC_{s_2 s_3} = \sum_{s_1} A_{s_2 s_1} B_{s_1 s_3} = A \cdot B then for a given dCsos2s3dC_{s_o s_2 s_3} the derivative dAsos2′s1′=∑s3dCsos2′s3Bs1′s3dA_{s_o s'_2 s'_1} = \sum_{s_3} dC_{s_o s'_2 s_3} B_{s'_1 s_3} for a simple matmul i.e. so=ϕ,s3∈R,s2∈R,s1∈Rs_o = \phi, s_3 \in \mathbb{R}, s_2 \in \mathbb{R}, s_1 \in \mathbb{R} this operation shrinks to simply dA=dC⋅BTdA = dC \cdot B^T. Similarly for dBsos1′s3′=∑s2dCsos2s3′As2s1′dB_{s_o s'_1 s'_3} = \sum_{s_2} dC_{s_o s_2 s'_3} A_{s_2 s'_1} for a simple matrix multiplication this would reduce to dB=dCT⋅AdB = dC^T \cdot A

dPϕs2s3dP_{\phi s_2 s_3}:

From the formula derived previously dPϕs2′s3′=∑s1dBs2′s1Vs3′s1=dB⋅VTdP_{\phi s'_2 s'_3} = \sum_{s_1} dB_{s'_2 s_1} V_{s'_3 s_1} = dB \cdot V^T

dQKϕs2s3TdQK^T_{\phi s_2 s_3}

Here we have encountered softmax operation as Ps2s3=softmaxs3(Ss2s3=QKs2s3T)P_{s_2 s_3} = softmax_{s_3}(S_{s_2 s_3} = QK^T_{s_2 s_3}) from the softmax blog we can

Direct Operation:

Bs2s1=softmaxs1(As2s1)\begin{aligned}B_{s_2 s_1} = softmax_{s_1}(A_{s_2 s_1}) \end{aligned}

Here Os3O_{s_3} is the final loss value for which we need to extract the derivatives.

∂Os3∂As2′s1′=Bs2′s1′[dBs3s2′s1′−∑s1dBs3s2′s1Bs2′s1]\begin{aligned}\frac{\partial O_{s_3}}{\partial A_{s'_2 s'_1}} = B_{s'_2 s'_1} \left[dB_{s_3 s'_2 s'_1} - \sum_{s_1} dB_{s_3 s'_2 s_1} B_{s'_2 s_1}\right] \end{aligned}

From the formula, we can say:

∂Oϕ∂QKs2′s3′T=Ps2′s3′[dPϕs2′s3′−∑s3dPϕs2′s3Ps2′s3]\begin{aligned}\frac{\partial O_{\phi}}{\partial QK^T_{s'_2 s'_3}} = P_{s'_2 s'_3} \left[dP_{\phi s'_2 s'_3} - \sum_{s_3} dP_{\phi s'_2 s_3} P_{s'_2 s_3}\right] \end{aligned}

for a simple matmul:

∂Oϕ∂Si′j′=Pi′j′[dPi′j′−dPi′:T∘Pi′:]=P×[dP−BMM(dPi′1j,Pi′j1)]\begin{aligned}\frac{\partial O_{\phi}}{\partial S_{i'j'}} = P_{i'j'} \left[dP_{i'j'} - dP_{i':}^T \circ P_{i':} \right] = P \times \left[dP - BMM(dP_{i'1j, P_{i'j1}}) \right] \end{aligned}

dQϕs2s1dQ_{\phi s_2 s_1} & dKϕs2s1dK_{\phi s_2 s_1}:

S=QKTS = QK^T and we know dSdS thus we can directly write the derivatives of both QQ and KK.

dQ=dS⋅KdK=dST⋅Q\begin{aligned}dQ = dS \cdot K \\ dK = dS^T \cdot Q \end{aligned}

Final Backward Pass Equations:

dB∈R[M×D],{Q,dQ}∈R[M×D],{K,dK}∈R[N×D],{V,dV}∈R[N×D]\begin{aligned}dB \in \mathbb{R}^{[M \times D]}, \{Q, dQ\} \in \mathbb{R}^{[M \times D]}, \\ \{K, dK\} \in \mathbb{R}^{[N \times D]}, \{V, dV\} \in \mathbb{R}^{[N \times D]}\\ \end{aligned}
dV=dBT⋅PdP=dB⋅VTdSi′j′=Pi′j′[dPi′j′−dPi′:T∘Pi′:]dQ=dS⋅KdK=dST⋅Q\begin{aligned}dV = dB^T \cdot P \\ dP = dB \cdot V^T \\ dS_{i'j'} = P_{i'j'} \left[dP_{i'j'} - dP_{i':}^T \circ P_{i':} \right] \\ dQ = dS \cdot K \\ dK = dS^T \cdot Q \end{aligned}

Expansion in dimensions:

Sij=∑dqidkjddVjd=dBT⋅P=∑idBidPij=∑idBidexp⁡(Sij)LidPij=dB⋅VT=∑ddBidVjddSij=Pij[dPij−∑jdPijPij]dQid=dS⋅K=∑jdSijKjddKjd=dST⋅Q=∑idSijQid\begin{aligned}S_{ij} = \sum_d q_{i d} k_{j d} \\ dV_{j d} = dB^T \cdot P = \sum_i dB_{i d} P_{i j} = \sum_i dB_{i d} \frac{\exp(S_{i j})}{L_i} \\ dP_{i j} = dB \cdot V^T = \sum_d dB_{i d} V_{j d} \\ dS_{i j} = P_{i j} \left[dP_{i j} - \sum_j dP_{i j} P_{i j} \right] \\ dQ_{i d} = dS \cdot K = \sum_{j} dS_{i j} K_{j d}\\ dK_{j d} = dS^T \cdot Q = \sum_{i} dS_{i j} Q_{i d} \end{aligned}

Abstract away D dimension:

In a future blog we will see that this is natural to do computation along D (embedding) dimension as all of the computations are independent of each other in this dimension.

Sij=qi∘kjdVj=∑idBidexp⁡(qi∘kj)LidPij=dBi∘VjdSij=Pij[dPij−∑jdPijPij]dQi=dSi∘KjdKj=dSjT∘Qi\begin{aligned}S_{ij} = q_i \circ k_j \\ dV_j = \sum_i dB_{i d} \frac{\exp(q_i \circ k_j)}{L_i} \\ dP_{i j} = dB_i \circ V_j \\ dS_{i j} = P_{i j} \left[dP_{i j} - \sum_j dP_{i j} P_{i j} \right] \\ dQ_i = dS_i \circ K_j \\ dK_j = dS^T_j \circ Q_i \\ \end{aligned}
∑jdPijPij=∑j(∑ddBidVjd)Pij=∑j∑ddBidVjdPij=∑d∑jdBidVjdPij=∑ddBid∑jVjdPij=∑ddBidBid\begin{aligned}\sum_j dP_{i j} P_{i j} = \sum_j \big(\sum_d dB_{i d} V_{j d}\big) P_{i j} = \sum_j \sum_d dB_{i d} V_{j d} P_{i j} \\ = \sum_d \sum_j dB_{i d} V_{j d} P_{i j} = \sum_d dB_{i d} \sum_j V_{j d} P_{i j} = \sum_d dB_{i d} B_{i d} \end{aligned} Sij=qi∘kjdVj=∑idBidexp⁡(qi∘kj)LidPij=dBi∘VjdSij=Pij[dPij−dBi∘Bi]dQi=dSi∘KjdKj=dSjT∘Qi\begin{aligned}S_{ij} = q_i \circ k_j \\ dV_j = \sum_i dB_{i d} \frac{\exp(q_i \circ k_j)}{L_i} \\ dP_{i j} = dB_i \circ V_j \\ dS_{i j} = P_{i j} \left[dP_{i j} - dB_i \circ B_i \right] \\ dQ_i = dS_i \circ K_j \\ dK_j = dS^T_j \circ Q_i \\ \end{aligned}