Flash Attention解决了什么问题?

标准注意力计算需要将整个N×N的注意力矩阵存储在GPU高带宽内存(HBM)中。对于长序列,这个矩阵非常大——128K序列长度的注意力矩阵需要约64GB HBM。GPU核心(SM)与HBM之间的数据搬运成为瓶颈。

Flash Attention的核心创新:不在HBM中实例化完整注意力矩阵,而是在SRAM中分块计算。

GPU内存层次

理解Flash Attention需要先理解GPU的内存层次:

  SRAM (片上共享内存)
  ├── 延迟: ~20 cycles
  ├── 带宽: ~19 TB/s (A100)
  └── 容量: ~192KB per SM

  HBM (高带宽内存)
  ├── 延迟: ~200+ cycles  
  ├── 带宽: ~2 TB/s (A100)
  └── 容量: 80GB (A100)

标准注意力的问题:在HBM中读写O(n²)大小的矩阵,受限于2TB/s的HBM带宽。

Flash Attention的解决思路:将计算分块,每块在SRAM中完成,减少HBM访问次数。

算法原理

标准注意力计算

S = Q @ K^T / √d        # [N, N] 注意力分数
P = softmax(S)          # [N, N] 归一化
O = P @ V               # [N, d] 输出

问题:S和P是N×N矩阵,需要完整存储在HBM中。

Flash Attention的分块算法

将Q、K、V分成块,逐块计算:

输入: Q [N,d], K [N,d], V [N,d]
参数: block_size = B

初始化: O = 0, l = 0 (行和累积)

for j in range(0, N, B):  # 遍历K, V的块
    K_j = K[j:j+B]  # 加载到SRAM
    V_j = V[j:j+B]
    
    for i in range(0, N, B):  # 遍历Q的块
        Q_i = Q[i:i+B]  # 加载到SRAM
        
        # 在SRAM中计算
        S_ij = Q_i @ K_j^T / √d  # [B, B]
        P_ij = softmax(S_ij)
        
        # 在线更新softmax(关键创新)
        O_i += P_ij @ V_j  # 累加到输出

在线Softmax(核心难点)

标准softmax需要看到整行才能归一化。但Flash Attention逐块计算,不能看到整行。

解决方法——在线Softmax(Online Softmax):

# 维护两个状态: m (最大值), l (求和)

# 处理新块时:
m_new = max(m_old, max(S_ij))      # 更新最大值
l_new = l_old * exp(m_old - m_new) + sum(exp(S_ij - m_new))  # 更新归一化因子
O_new = O_old * (l_old * exp(m_old - m_new) / l_new) + P_ij @ V_j / l_new  # 更新输出

这个数学技巧让我们可以逐块计算softmax而无需存储完整矩阵。

反向传播

标准注意力在反向传播时需要中间矩阵P。Flash Attention不存储P,如何反向传播?

方案:在前向传播中存储O和softmax归一化统计量(m和l),在反向传播中重计算P:

# 前向:存储O, m, l(O(N*d)而非O(N²))
# 反向:用Q, K重计算P,再计算梯度

# 额外计算开销约2倍前向,但减少了O(N²)的存储

性能分析

时间复杂度

  • 标准注意力: O(N²) HBM读写 + O(N²) 计算
  • Flash Attention: O(N²/B) HBM读写 + O(N²) 计算

HBM读写减少B倍,计算量不变。

空间复杂度

  • 标准注意力: O(N²) HBM存储
  • Flash Attention: O(N*d) HBM存储(只存O和统计量)

实测性能

以A100 GPU为例,Llama-7B模型:

序列长度标准注意力Flash Attention加速比
2K5ms2ms2.5x
8K45ms8ms5.6x
32KOOM120ms
128KOOM950ms

关键发现:序列越长,Flash Attention优势越大。长上下文场景下,标准注意力直接OOM,而Flash Attention可以运行。

Flash Attention 2/3的改进

Flash Attention 2

减少非矩阵乘法运算:

  • 优化了online softmax的计算顺序
  • 减少GPU线程同步开销
  • 优化了并行度(沿序列维度并行)

效果:比Flash Attention 1快约2倍。

Flash Attention 3 (Flash Attention 3)

针对Hopper架构(H100)的优化:

  • 异步化:使用TMA(Tensor Memory Accelerator)异步加载数据
  • 低精度:支持FP8 Tensor Core
  • 流水线:前一个块计算与下一个块加载重叠

效果:在H100上比Flash Attention 2快1.5-2倍。

实现要点

分块大小选择

block_size选择需要考虑:
- SRAM容量: 块太大溢出SRAM
- 计算效率: 块太小GPU利用率低
- 经验值: 128-256 tokens per block

多GPU并行

Flash Attention可以沿Q维度并行:

  • 每个GPU处理不同的Q块
  • 不需要GPU间通信(K和V共享)
  • 适合Tensor Parallel

使用建议

# PyTorch 2.0+ 内置Flash Attention
import torch
attn_output = torch.nn.functional.scaled_dot_product_attention(
    Q, K, V, 
    is_causal=True  # causal mask
)
# 自动使用Flash Attention内核

# vLLM等推理框架默认使用Flash Attention
# 无需手动配置

总结

Flash Attention是近年来大模型领域最具影响力的算法创新之一。它不是改变注意力的数学含义,而是改变计算方式——通过减少内存搬运而非减少计算量来加速。这个"IO优化"思路解决了长上下文的核心瓶颈,使得128K甚至1M的上下文窗口成为可能。所有主流推理框架都已集成Flash Attention,它是长上下文推理的"隐形基础设施"。