Skip to content

基准测试:当前本机快照与复验协议

证据状态(2026-08-24):仓库没有保存 V100/A100/H100 表格对应的原始 JSON、 Nsight 报告或 Release 附件。因此第 2–5 节中的跨 GPU 数字是不可审计历史快照: 不得出现在 README 首页、Release、简历、面试数字卡或性能结论中,也不得用于横向比较。

第 1.5 节保留 RTX 3060 Laptop 的本机测量上下文,供重新执行 benchmark 时做 sanity check;它同样没有成套原始 JSON,不能冒充正式跨硬件报告。下一份可引用结果必须归档 硬件/软件/commit、Google Benchmark JSON、命令、原始日志和 nsys/ncu 产物。

本仓库是参考级 CUDA 实现,未接入 CUTLASS 或 cuDNN 优化管线;即使将来产出正式结果, 也不代表生产级性能上限。


1. 本机快照与未来复验协议

1.1 硬件平台

GPU 型号架构显存Compute Capability驱动版本
NVIDIA V100 SXM2Volta32 GB HBM2sm_70535.183
NVIDIA A100-40GB PCIeAmpere40 GB HBM2esm_80535.183
NVIDIA H100 SXM5Hopper80 GB HBM3sm_90535.183

1.2 软件栈

组件版本
CUDA Toolkit12.2
PyTorch (SDPA 对比基线)2.2.0+cu122
Google Benchmark1.8.3
GCC11.4
CMake3.27

1.3 测试配置

  • 数据类型: FP16(half / __half2
  • 注意力类型: Causal masking enabled(下三角掩码)
  • head_dim: 固定为 64(本实现支持 32、64、128)
  • Q/K/V 布局: [batch_size, num_heads, seq_len, head_dim]
  • 计时方式: Google Benchmark Benchmark::UseManualTime(),CUDA Event 统计 kernel-only 耗时
  • 预热迭代: 10 次
  • 正式采样: 30 次(取中位数)
  • 内存统计: cudaMemGetInfo 前后差值 + nvidia-smi dmon 交叉验证

1.4 编译参数

bash
cmake --preset release \
  -DCUFASH_ATTN_BENCHMARKS=ON \
  -DCUFASH_ATTN_ARCHS="70;80;90"
cmake --build --preset release --target cuflash_attn_bench

1.5 本机测量快照(RTX 3060 Laptop,2026-08-18,非正式结果包)

本节保留当前可执行的本机测量上下文,但原始 JSON 尚未随仓库归档;它只用于 sanity check,不可替代正式结果包。

环境

GPUNVIDIA GeForce RTX 3060 Laptop GPU(6144 MiB,sm_86
驱动591.44
CUDA Toolkit12.0(nvcc 12.0.140)
本仓库 commit6860cbc
编译cmake --preset release && cmake --build --preset release -j(默认 arch 80;86
配置batch=1, heads=8, kernel-only 耗时(CUDA Event),10 预热 + 30 采样中位数

复现命令

bash
cmake --preset release && cmake --build --preset release -j
./build/release/cuflash_attn_bench

前向(Forward,非 causal,FP16 / BF16,Tensor Core 路径),单位 ms:

seq_lenhead_dimFP16 (ms)BF16 (ms)FP32 (ms)
256640.1580.1620.841
512640.4960.5022.86
1,024641.761.7912.0
2,048646.336.4547.8
4,0966423.523.7177
4,09612884.182.6379

前向(Forward,Causal,FP32),单位 ms:

seq_lenhead_dimFP32 causal (ms)
1,024644.55
4,0966456.7
4,096128186

反向(Backward,dQ/dK/dV,非 causal),单位 ms:

seq_lenhead_dimFP16 (ms)BF16 (ms)FP32 (ms)
1,0246429.729.328.4
4,09664421415409
4,09612811601141994

说明:本次为 RTX 3060 Laptop(sm_86,约 220 GB/s 显存带宽)单机实测, 与第 2–5 节不可审计历史快照不可直接横向比较;A100/H100 数据必须在该机型上按 同一协议重跑并归档原始产物后,才可进入正式报告。


2. 不可审计历史快照:多维度 Benchmark 矩阵(禁止引用)

2.1 端到端前向传播(Forward, FP16, Causal)

单位: 毫秒(ms),数值越小越好。表格内为 kernel-only 时间。

seq_lenbatchheadsV100 (ms)A100 (ms)H100 (ms)
1,024180.420.190.11
1,0241160.810.360.20
1,024883.121.380.78
1,0248166.182.721.52
1,0241686.152.711.51
1,024161612.215.383.00
4,096185.822.181.15
4,09611611.484.302.26
4,0968844.8016.728.79
4,09681688.9233.1617.44
4,09616888.5033.0217.37
4,0961616TBD65.6034.50
8,1921822.507.803.85
8,19211644.5015.407.60
8,19288173.059.829.5
8,192816TBD118.058.2
8,192168TBD118.558.5
8,1921616TBDTBD115.0
16,3841888.028.513.2
16,384116172.055.825.8
16,38488TBDTBD100.0
16,384816TBDTBDTBD
32,76818TBD105.045.0
32,768116TBD205.088.0

: TBD 表示该配置因时间或硬件调度原因尚未实测。可通过下方 可复现脚本 补充。

2.2 反向传播(Backward, dQ/dK/dV, FP16, Causal)

反向传播通常约为前向的 2.0–2.5× 耗时(额外两次 GEMM-like 计算与重计算路径)。

seq_lenbatchheadsA100 前向 (ms)A100 反向 (ms)反向/前向 比值
1,024180.190.412.16×
4,096182.184.752.18×
8,192187.8017.202.21×
16,3841828.563.52.23×

3. 不可审计历史快照:与 PyTorch SDPA 的速度对比(禁止引用)

PyTorch 2.2 的 torch.nn.functional.scaled_dot_product_attention 默认优先调用 FlashAttention-2(通过 memory_efficient 后端)。此处以 A100-40GB、FP16、causal、head_dim=64 为基准,对比端到端前向耗时。

3.1 绝对耗时对比

seq_lenbatchheadsPyTorch SDPA (ms)CuFlash-Attn (ms)加速比 (SDPA/ ours)
1,024180.120.190.63×
1,0248161.822.720.67×
4,096181.052.180.48×
4,09681615.8033.160.48×
8,192183.507.800.45×
8,19281652.00118.00.44×
16,3841812.0028.50.42×

3.2 结果解读

指标观察结论
绝对性能CuFlash-Attn 约为 PyTorch SDPA 的 42%–67%。这是预期内结果——本库为从零手写 CUDA 的教学/参考实现,未接入 cuDNN 高度调优的管线,也未使用 CUTLASS 的 warp-specialization 与自动调度。
趋势一致性随着 seq_len 增大,两者的 scaling 曲线基本平行(均接近 O(N2) 计算量),说明本实现的核心 tiling 与 softmax 重缩放逻辑是正确的。
小序列开销seq_len=1K 时,本实现相对差距最大(0.63×),因为 kernel launch、causal mask 边界判断与 warp-level reduction 的固定开销占比更高。

面试要点: 当被问及"为什么比 PyTorch 慢"时,应区分算法正确性工程优化深度。本库验证了 O(1) HBM 内存的 FlashAttention 算法,而 PyTorch 后端调用的是 NVIDIA/cuDNN 经过数千小时调优的生产 kernel。


4. 不可审计历史快照:内存占用对比(禁止引用)

4.1 峰值显存(Forward + Backward 单步)

单位: MB。对比标准 Attention(O(N2) 中间激活)与 FlashAttention(O(N) 激活)。

seq_lenbatchheads标准 Attention (MB)CuFlash-Attn (MB)节省比例
1,0241832.516.250.2%
4,09618512.065.087.3%
8,192182,048.0130.093.7%
16,384188,192.0260.096.8%

4.2 内存 Scaling 公式验证

  • 标准 Attention(Materialized Softmax): Mstd=4×batch×heads×seq_len2×sizeof(FP16)

    • seq_len=8192, batch=1, heads=8 为例:4×1×8×81922×24096 MB=4 GB
    • 实际测量含 PyTorch 框架开销与临时 buffer,约为 2 GB forward + 2 GB backward = 4 GB 量级。
  • FlashAttention(Tiled Online Softmax): Mfa=2×batch×heads×seq_len×head_dim×sizeof(FP16)+workspace

    • 以同样配置为例:2×1×8×8192×64×216.8 MB 的 Q/K/V/O 张量本身
    • 加上 SRAM 大小的 softmax 统计量(m, l 向量)与 tile buffer,总计约 130 MB(含 CUDA context、cuBLAS workspace、pytorch allocator 碎片)。

核心结论: 当 seq_len ≥ 4K 时,FlashAttention 的内存优势呈指数级体现,使得在 40GB A100 上单卡可训练 seq_len=128K 的模型,而标准 Attention 在 seq_len=32K 时就会 OOM。


5. 不可审计历史快照:不同 GPU 架构的 Scaling 分析(禁止引用)

5.1 理论峰值对比

指标V100 (sm_70)A100 (sm_80)H100 (sm_90)A100/V100H100/A100
HBM 带宽900 GB/s2,039 GB/s3,350 GB/s2.27×1.64×
FP16 Tensor Core 算力 (dense)31.4 TFLOPS312 TFLOPS989 TFLOPS9.94×3.17×
FP16 Tensor Core 算力 (sparse)62.8 TFLOPS624 TFLOPS1,979 TFLOPS9.94×3.17×
带宽-算力比34.9 FLOP/Byte153 FLOP/Byte295 FLOP/Byte
典型 TDP300 W400 W700 W

5.2 实测 Scaling(固定配置: batch=1, heads=8, head_dim=64, causal FP16)

seq_lenV100 (TFLOPS)A100 (TFLOPS)H100 (TFLOPS)V100 带宽利用率A100 带宽利用率H100 带宽利用率
1,0242.14.58.252%48%46%
4,0962.87.514.269%80%80%
8,1923.08.517.374%91%97%
16,3843.19.320.176%>100%*>100%*

*: 利用率超过 100% 是因为 FlashAttention 的在线 softmax 重计算减少了 HBM 流量,使得有效带宽高于原始理论值;或受限于 timer 精度与异步 overlap 的测量误差。在严谨分析中,应使用 Roofline 模型将其归一化到计算强度实际 HBM 流量(见 Roofline 分析)。

5.3 理论 vs 实测加速比

seq_lenA100/V100 (理论)A100/V100 (实测)H100/A100 (理论)H100/A100 (实测)
1,0242.27× (带宽上限)0.45 / 0.19 ≈ 2.37×1.64× (带宽上限)0.19 / 0.11 ≈ 1.73×
4,0962.27× (带宽上限)5.82 / 2.18 ≈ 2.67×1.64× (带宽上限)2.18 / 1.15 ≈ 1.90×
8,1922.27× (带宽上限)22.5 / 7.8 ≈ 2.88×1.64× (带宽上限)7.8 / 3.85 ≈ 2.03×
16,3842.27× (带宽上限)88.0 / 28.5 ≈ 3.09×1.64× (带宽上限)28.5 / 13.2 ≈ 2.16×

分析

  1. V100 → A100: 实测加速比随 seq_len 增大而超过理论带宽比(2.27×)。这是因为:

    • A100 的 Tensor Core 支持更细粒度的 FP16 MMA(16×8×16),而 V100 为 8×8×4,tiling 效率在 A100 上更高。
    • Ampere 架构引入的异步拷贝(cp.async)未被本实现显式使用,但编译器自动生成的 LDGSTS 流水仍优于 Volta。
  2. A100 → H100: 实测加速比低于理论带宽比(1.64×)。这是因为:

    • 本实现尚未针对 Hopper 的 TMA (Tensor Memory Accelerator)WGMMA (Warp Group-level MMA) 进行重写。
    • Hopper 的 Thread Block Cluster 与分布式共享内存特性未启用,导致未能发挥 SM90 的理论峰值。
    • 预期: 若将 kernel 升级至 FlashAttention-3 风格(TMA + WGMMA),H100 上可望获得 2.5×–3.0× 于 A100 的性能。

6. 未来正式结果的复验命令

6.1 本地运行(需 CUDA GPU)

bash
# 1. 克隆仓库
git clone https://github.com/your-org/cuflash-attn.git
cd cuflash-attn

# 2. 使用 CMake Preset 构建 benchmark 目标
cmake --preset release -DCUFASH_ATTN_BENCHMARKS=ON
cmake --build --preset release --target cuflash_attn_bench

# 3. 运行全量 benchmark(约 20–30 分钟)
./build/release/bench/cuflash_attn_bench \
  --benchmark_time_unit=ms \
  --benchmark_repetitions=30 \
  --benchmark_report_aggregates_only=true \
  --benchmark_filter="BM_FlashAttention_Forward.*"

# 4. 导出 JSON 供后续分析
./build/release/bench/cuflash_attn_bench \
  --benchmark_out=results.json \
  --benchmark_out_format=json

6.2 Docker 环境(推荐,完全可复现)

dockerfile
# Dockerfile.benchmark
FROM nvidia/cuda:12.2.0-devel-ubuntu22.04

RUN apt-get update && apt-get install -y \
    cmake ninja-build git python3 python3-pip \
    libbenchmark-dev libgtest-dev \
    && rm -rf /var/lib/apt/lists/*

# 安装 Google Benchmark(若 apt 版本过旧)
RUN git clone https://github.com/google/benchmark.git /tmp/benchmark \
    && cmake -S /tmp/benchmark -B /tmp/benchmark/build \
       -DBENCHMARK_DOWNLOAD_GTEST=ON -DCMAKE_BUILD_TYPE=Release \
    && cmake --build /tmp/benchmark/build -j$(nproc) \
    && cmake --install /tmp/benchmark/build

WORKDIR /workspace
COPY . /workspace/cuflash-attn
RUN cmake --preset release -DCUFASH_ATTN_BENCHMARKS=ON \
    && cmake --build --preset release --target cuflash_attn_bench

CMD ["./build/release/bench/cuflash_attn_bench"]
bash
# 构建并运行
docker build -f Dockerfile.benchmark -t cuflash-bench .
docker run --gpus all -v $(pwd)/results:/results cuflash-bench \
  --benchmark_out=/results/bench_$(nvidia-smi --query-gpu=name --format=csv,noheader | tr ' ' '_').json

6.3 与 PyTorch SDPA 的对比脚本

python
# scripts/bench_vs_pytorch.py
import torch
import torch.nn.functional as F
import time

def benchmark_pytorch(batch, heads, seq_len, head_dim=64, causal=True, n_iters=100):
    device = torch.device("cuda")
    q = torch.randn(batch, heads, seq_len, head_dim, device=device, dtype=torch.float16)
    k = torch.randn(batch, heads, seq_len, head_dim, device=device, dtype=torch.float16)
    v = torch.randn(batch, heads, seq_len, head_dim, device=device, dtype=torch.float16)

    # 预热
    for _ in range(10):
        out = F.scaled_dot_product_attention(q, k, v, is_causal=causal)
    torch.cuda.synchronize()

    # 计时
    start = torch.cuda.Event(enable_timing=True)
    end = torch.cuda.Event(enable_timing=True)
    start.record()
    for _ in range(n_iters):
        out = F.scaled_dot_product_attention(q, k, v, is_causal=causal)
    end.record()
    torch.cuda.synchronize()
    return start.elapsed_time(end) / n_iters

if __name__ == "__main__":
    for seq_len in [1024, 4096, 8192, 16384]:
        t = benchmark_pytorch(batch=1, heads=8, seq_len=seq_len)
        print(f"seq_len={seq_len}: {t:.3f} ms/iter")

7. 正式结果发布门槛

在 L40S、A100 或其他云 GPU 上发布新的性能数字前,必须先通过数值正确性测试,并将以下 产物与结果页一并提交:

  • metadata.json:GPU、显存、驱动、CUDA、commit、编译参数和输入矩阵;
  • Google Benchmark 的原始 JSON 与完整 stdout.log
  • PyTorch SDPA 或官方 FlashAttention 对照的独立命令、版本与输入契约;
  • nsys timeline 与 ncu 指标(若云环境未开放权限,明确记录限制,不用推测替代);
  • 包含失败形状、OOM、数值误差和低于噪声优化的报告。

不同 GPU 的结果分目录和分表展示;禁止把不同架构、不同精度、不同实现版本的数据拼成 同一加速比。


8. 版本变更记录

版本日期变更说明
v0.5.12026-08-24跨 GPU 历史表格隔离为不可审计快照;首页撤下未经原始产物支持的数字,新增正式结果发布门槛
v0.5.0+2026-08-18新增 RTX 3060 Laptop 本机测量上下文(commit 6860cbc),补充 head_dim=128 数据
v0.4.02026-04-15初始 benchmark 文档;跨 GPU 数字未保留完整原始产物,现已禁止引用

稳定 v0.5.0 基线 · 精简 CUDA FlashAttention 参考实现