1. 项目概述与背景
在深度学习领域,Transformer架构已成为自然语言处理任务的主流选择。然而,传统注意力机制的计算和内存复杂度随序列长度呈二次方增长,这严重限制了模型处理长序列的能力。FlashAttention-2作为第二代内存高效注意力算法,通过分块计算和在线softmax技术,将显存复杂度从O(N²)降低到O(N),同时保持数值等价性。
本实验源自斯坦福大学CS336课程(2025春季)的第二个作业,要求学生从零实现FlashAttention-2算法。作业分为多个部分,包括基准测试、PyTorch编译优化以及核心算法实现。通过这个项目,学生能够深入理解现代注意力机制的底层优化原理,并掌握高性能计算的关键技术。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基准测试与问题分析
2.1 传统注意力实现的性能瓶颈
我们首先对标准PyTorch注意力实现进行基准测试,评估不同配置下的性能表现。测试脚本固定batch size为8,禁用多头注意力,遍历不同嵌入维度(16/32/64/128)和序列长度(256/1024/4096/8192/16384)组合。
测试结果显示,当序列长度达到8192时,所有配置均出现显存不足(OOM)错误。以最小OOM配置(d_model=16, seq_len=8192)为例分析:
- 注意力矩阵L=QK^T的形状为[8,8192,8192],元素数量约5.37亿
- 以FP32格式存储时,单个矩阵占用约2.0GB显存
- 前向传播需保留softmax输出,反向传播需要中间梯度,总显存需求呈O(B·S²)增长
2.2 编译优化的性能提升
使用PyTorch 2.0的torch.compile对注意力模块进行优化后,观察到显著性能改进:
- 小序列长度(S=256):1.5-2倍加速
- 中等序列(S=1024-4096):2-3倍加速
- 长序列(S=8192):编译版本可运行而原生版本OOM
值得注意的是,编译优化主要来自算子融合和调度改进,并未改变显存复杂度。端到端Transformer模型的测试显示类似趋势,编译后前向和反向传播均有稳定加速。
3. FlashAttention-2核心实现
3.1 PyTorch基础实现
我们首先实现纯PyTorch版本的FlashAttention-2前向传播,作为后续Triton实现的调试基准。关键算法步骤如下:
- 分块处理:将Q、K、V划分为大小为Bq和Bk的tile
- 在线softmax:维护运行统计量(m,l,o_acc)
- 增量更新:
- m_new = max(m, S_max)
- l_new = exp(m-m_new)*l + sum(exp(S-m_new))
- o_acc = exp(m-m_new)*o_acc + P@V
python复制class FlashAttention2Pytorch(torch.autograd.Function):
@staticmethod
def forward(ctx, q, k, v, is_causal=False):
B, Q, D = q.shape
K = k.shape[1]
scale = 1.0 / math.sqrt(D)
# 初始化输出和logsumexp
o = torch.empty_like(q)
L = torch.empty(B, Q, device=q.device, dtype=torch.float32)
