- 人工智能
- 大模型
- AI 技能/插件
- 分布式训练
- 微调
- 深度学习
【免费下载链接】ml-engineering
Machine Learning Engineering Open Book
导读
本指南源自 ml-engineering 仓库 insights/when-to-upgrade-gpus/README.md,它解决一个所有训练团队都会遇到的现实问题:当新一代 GPU 上市时,是否值得为它付出更高的采购成本?文档以一个真实可复现的 DeepSpeed 训练基准为具体案例(meta-llama/Llama-3.1-8B,H200 上 FlashAttention-3 vs B200 上 FlashAttention-4)给出了一套通用的两段式决策框架:先问"新 GPU 是否具备旧 GPU 做不到的能力",再问"在性能上它是否值回票价"。读完本文你将掌握:如何用 MAMF(可实现峰值算力)而非理论 TFLOPS 校准期望、如何设计两个 GPU 之间公平的基准实验、如何解读"加速比随序列长度增长"的现象、以及如何在预算决策中同时考虑 $/token 与墙钟时间。
H200 与 B200 的关键规格差异
一切决策都从规格对比开始。下表汇总了 Hopper(H200)与 Blackwell(B200)两代硬件的关键差异(完整规格表见 compute/accelerator/README.md):
| 规格 | H200 SXM | B200 SXM | 比值(B200/H200) |
|---|---|---|---|
| 架构 | Hopper | Blackwell | — |
| Compute capability | sm90 | sm100 | — |
| 注意力内核(HF 自动选择) | FlashAttention-3 | FlashAttention-4 (beta) | — |
| 理论峰值 bf16 TFLOPS | 989 | 2250 | 2.28× |
| 理论峰值 fp8 TFLOPS | 1979 | 4500 | 2.27× |
| 可用 HBM 容量 HBM3e | ~141GiB | ~180GiB | 1.28× |
| HBM 带宽 | 4.8TBps | 8.0TBps | 1.67× |
| TDP | 700W | 1000W | 1.43× |
注意两点:
- 理论峰值是现实中无人能触及的天花板——正如 training/performance/README.md 所强调的,真正的可达吞吐要看下面的 MAMF。
- 该表是跨厂商(含 AMD)完整规格的一部分,实际采购决策时应结合 compute/accelerator/README.md 中所有厂商、所有 dtype 的规格与功耗、时钟参考。
MAMF:现实中的天花板,而不是营销数字
MAMF(Maximum Achievable Matmul FLOPS)是在真实硬件/软件上实测到的 matmul 最优吞吐(完美对齐的最大尺寸形状、无稀疏),与物理上不可达的理论峰值相对。用 MAMF 来校验你自己的训练 TFLOPS 是否还有优化空间,或者是否已经贴近天花板。可以用mamf-finder.py在自有 GPU 上测量,例如:
python mamf-finder.py --m_range 0 20480 256 --n 4096 --k 4096 --output_file=$(date +'%Y-%m-%d-%H:%M:%S').txtmamf-finder 会执行多次不同形状的 matmul 取平均值(每个形状 50 次 warmup + 100 次迭代),完整方法说明见 compute/accelerator/benchmarks/README.md。仓库实测的对比数据如下:
BF16:
| 加速器 | MAMF (TFLOPS) | 理论峰值 | 效率 |
|---|---|---|---|
| H100/H200 SXM | 794.5 | 989 | 80.3% |
| B200 SXM | 1745.0 | 2250 | 77.6% |
FP8:
| 加速器 | MAMF (TFLOPS) | 理论峰值 | 效率 |
|---|---|---|---|
| H200 SXM | 1453.4 | 1979 | 73.4% |
| B200 SXM | 3432.5 | 4500 | 76.3% |
完整的 MAMF 对比表见 compute/accelerator/README.md。
结论:bf16 的可实现比值(1745/794.5 =2.20×)与理论值 2.28× 相当接近,因为两代芯片效率相近(80.3% vs 77.6%);而 fp8 的可实现比值(3432.5/1453.4 =2.36×)反而高于理论值,因为 B200 的 fp8 路径相对更成熟(76.3% vs 73.4%)。无论哪种 dtype,2.2–2.4× 都是这次升级现实的 matmul-only 天花板——真实的训练吞吐一旦计入注意力扩展、稠密 GEMM 成熟度和通信开销,会落在这个数字之下(后面的实测案例精确展示了低多少、为什么)。
决策框架第一部分:你需要新的 dtype 吗?
从这里开始,因为这一个问题本身就能决定结论,根本无需跑基准。真正要问的第一个问题不是"它快多少",而是"新 GPU 能否做旧 GPU 做不到的事"。对一次硬件代际跃迁来说,最清晰的能力缺口就是**新的低精度 dtype**。
Blackwell 增加了FP4/NVFP4/FP6,Hopper 在硬件上根本无法执行——这对 FP4 推理或 microscaling 训练配方(recipe)至关重要。如果你的目标配方需要这些格式之一,旧 GPU 的得分是零,而不是"慢 2 倍"——没有基准可比,你只需要或者不需要这个能力。(注意:这也是最容易受软件成熟度风险影响的功能——硅片能做的往往早于框架/内核/数值配方能做的,见下文"软件支持"一节。)
在为某个功能升级之前,先确认你实际使用的软件栈支持它。一个你的技术栈无法调用的硬件能力,等于花钱买空气——规格表只说明硅片能做什么,不代表框架/内核/库今天允许你做什么。两个典型例子:
- NVLink-C2C(Grace 系统中 CPU↔GPU 相干互连)在纸面上很漂亮,但发布初期几乎未被大多数训练/推理软件利用——在软件追上之前,为它付费买到的实际收益很少。
- 完全可用的 FlashAttention-4 花了数月才出现。此前只能继续用 FlashAttention-2,它在 Blackwell 上非常慢,因为它无法利用新架构。
把"我的软件栈是否支持该功能"视为任何以功能为动机的升级的硬性门槛(并随时间复检,因为支持在改善)。
新 GPU 带来的其他一切——更多内存、更高带宽、更快互连、更多原始 FLOPS——都只是你已有的东西的更大数量,不是全新的能力,因此它们本身不能决定结论,一切落到测量上。这就是第二部分。
补充:为什么 4-bit 能真正可用?dtype 理论峰值从 H200 到 B200:bf16 989→2250,fp8 1979→4500,另外还有 Hopper 完全无法执行的格式——fp6→4500、fp4→9000、nvfp4→10000。FP4 大约是 fp8 吞吐的两倍,同时把量化张量的内存/带宽减半。而让 4-bit真正可用的关键是 Blackwell 的第二代 Transformer Engine(带 microscaling):FP4 只有约 16 个可表示值,每个张量一个缩放因子无法覆盖其动态范围(小值冲刷为零、大值饱和)。Microscaling(MX / NVFP4)改为对每个小块(如每 16–32 个值)单独用缩放因子,由 tensor core 在硬件中无吞吐代价地施加——于是在 FP4 约 2× 速度和一半内存下保持接近 fp8/bf16 的精度,这是朴素 per-tensor FP4 做不到的。(Hopper 第一代 TE 通过 per-tensor 缩放为 fp8 做这件事;Blackwell 第二代将其扩展到 block-scaled fp4/fp6。)
决策框架第二部分:性能上是否值回票价?
如果你不需要第一部分覆盖的新功能,那么升级就是一个量化的"速度与容量换钱"问题——而这必须测量。在相信任何厂商幻灯片或单一基准数字之前,按以下步骤走一遍:
- 两个 GPU 上匹配软件栈。新旧硬件上用相同的 torch/CUDA/库版本——新 GPU 往往也在更新的软件栈上验证过,而仅软件栈差异就能带来两位数的百分比差异(见下文"在同一软件栈上对比")。苹果对苹果地比较。
- 找出你工作负载的 attention-vs-dense 比例,以及它如何随真实配置伸缩。新 GPU 代际通常对 attention(FlashAttention 内核)的改进快于稠密 GEMM 的成熟度(cuBLAS/cuDNN 需要时间赶上新架构)。如果你的负载以 attention 为主(长上下文),你会看到比短上下文/稠密绑定负载更大的收益——而且这个比例并非固定,它随序列长度增长。测量它,不要假设它。(注:驱动这一长上下文优势的 O(s²) 全注意力占比正随新模型转向线性/混合注意力而缩小——Gated DeltaNet、Mamba 式 SSM、滑窗注意力,以及把少量全注意力层交错在大量线性注意力层之间的 MoE 混合体。线性注意力是 O(s),表现更像稠密路径而非全注意力——让新 GPU 在长上下文大放异彩的二次项在这些模型里占比更小。如果你的目标模型是混合/线性注意力架构,不要从 Llama-3 这类全注意力模型外推加速比;要针对该特定架构做基准。)
- 权衡新 GPU 针对你的负载的量化硬件优势——内存、带宽、互连。这些是提升而非新能力,其价值与负载相关,必须实测:
- 更多内存(如 180 vs 141GiB)是临界点。它可能让一个在旧 GPU 上 OOM 的配置装下,并帮你摆脱损害吞吐的拐杖(CPU offload、高 ZeRO 阶段、activation checkpointing)——因此一旦重新调优,有效加速甚至可能超过原始 FLOPS 比值。但"装不下"很少是硬墙:你几乎总能通过更多并行度(更多 GPU + ZeRO/TP/CP/SP/PP/EP)在旧 GPU 上装下,所以这通常是成本/效率权衡,只有当为装下而增加的 GPU/并行度比新硬件更贵或更慢时才倾向"直接升级"。(极端情况——你负担得起的任何并行度都装不下——内存才会变成硬性能力缺口,就像新 dtype。)
- 更高 HBM 带宽(8.0 vs 4.8TBps,约 1.67×)设定带宽绑定工作(norms、elementwise、optimizer、KV 流量)和解码绑定推理延迟的天花板;回报取决于你的负载实际有多带宽绑定。
- 更快互连(更新的 NVLink/NVSwitch/NVLink-C2C)抬高 ZeRO/TP/CP/SP/PP/EP 通信、各种主机内存 offload 策略和多节点扩展天花板;回报取决于你有多通信绑定。
- 计算 $/token(或 $/step),而不仅仅是 TFLOPS/step。2× 加速但价格 2× 等于成本打平,打破平局看 (a) 墙钟时间 (b) 内存余量。
- 注意真实世界的注意事项,它们会膨胀或压缩实验室数字——packed vs unpacked 序列、beta 质量内核、软件栈不匹配。具体例子见下文"Caveats"。
以下文档将带你端到端走完这些步骤(H200→B200 案例)。
实测案例:meta-llama/Llama-3.1-8B 训练 step,FA3 vs FA4
实验设置:meta-llama/Llama-3.1-8B 真实权重、bf16、8 GPU、DeepSpeed、mbs=1、fwd+bwd+step。注意力为 HF 原生attn_implementation,按 GPU 自动选择:H200 → FA3,B200 → FA4。
结果:加速比随序列长度增长
同一配置跑在两块 GPU 上(ZeRO-3 + activation checkpointing + CPU-offload + Liger-Kernel),稳态 TFLOPS/GPU:
| seqlen | full attn 占 step 比例 | H200 TFLOPS | H200 MFU | B200 TFLOPS | B200 MFU | speedup |
|---|---|---|---|---|---|---|
| 8K | ~13% | 141 | 14% | 167 | 7% | 1.19× |
| 32K | ~36% | 324 | 33% | 524 | 23% | 1.62× |
| 64K | ~53% | 391 | 40% | 719 | 32% | 1.84× |
| 128K | ~70% | 420 | 42% | 836 | 37% | 1.99× |
| 192K | ~77% | 422 | 43% | 852 | 38% | 2.02× |
| 256K | ~82% | 419 | 42% | 852 | 38% | 2.03× |
为什么加速比随 seqlen 增长(attention-vs-dense 比例的实战场面):因果注意力每 step 成本为6·s²·d·h·L(O(s²));稠密路径成本为6·N·tok(O(s))。序列越长,注意力占 step 的比例越高,而注意力恰恰是 FA4/Blackwell 优势最集中的地方——同时稠密路径(该尺寸下带宽绑定 + "年轻"的 sm_100 cuBLAS)只缩放约 1.7×,缩成舍入误差。恒等式speedup ≈ 2.28 × MFU_ratio全程成立——与 2.28× 的残余差距来自 FA4-beta 开销即使在纯注意力上也尚未达到完整硬件比值。
FLOP 计数约定:表格中的 TFLOPS/MFU 是模型FLOP(MFU),注意力按因果计数(6·s²·…,即 FlashAttention 实际计算的下三角——非因果12·s²会重复计数并在长上下文下夸大 MFU)。Activation-checkpoint 重计算被排除——计入它会是 HFU(约 1.3× 更高)。两种约定在 B200/H200 加速比中抵消,所以只有绝对 MFU/TFLOPS 依赖这个选择,头条加速比不受影响。这一计数的实现可对照 benchmark.py 中的estimate_tflos,其注意力系数为 6(因果)而非 12。
8k 注意事项:这个重型配置(ZeRO-3 + activation checkpointing + CPU-offload)的存在是为了跑到 256k,因此在 8k 时它是纯开销、没有计算可以藏——导致个位数 B200 MFU 和只有 1.19×。一个尺寸恰当的 8k 跑法(ZeRO-2、无 activation checkpointing/offload)能达到约 1.69× 且 MFU 高得多——见下文"稠密路径赤字从何而来"。教训:不要用一个长上下文配置在短上下文下跑基准,然后声称它有代表性。
更大的 GPU 能否解锁旧 GPU 跑不了的配置?
配置:ZeRO-3、Liger-Kernel、开启 activation checkpointing、CPU AdamW offload、mbs=1。有了 activation checkpointing + fused-CE,激活内存小而线性:峰值 ≈ 12.6GiB + 0.00043GiB/token(12.6GiB 底座是 ZeRO-3 的 param/grad 分片;AdamW 状态在 CPU 上)。
给定 seqlen 下峰值内存(max_memory_reserved,最差 rank)在H200 和 B200 上完全相同——它由模型 + ZeRO-3 分片 + 激活决定,而非 GPU 架构——所以一个能在一台装下的 seqlen 也能在另一台装下,直到各自的天花板:
| seqlen | H200 峰值 (GiB) | B200 峰值 (GiB) | H200 TFLOPS | B200 TFLOPS |
|---|---|---|---|---|
| 8K | 16.3 | 16.3 | 141 | 167 |
| 32K | 25.8 | 25.9 | 324 | 524 |
| 64K | 37.5 | 37.6 | 391 | 719 |
| 128K | 66.5 | 66.7 | 420 | 836 |
| 192K | 95.7 | 95.7 | 422 | 852 |
| 256K | 124.5 | 124.6 | 419 | 852 |
H200 约 130GiB 可用预算上的上限是256k token、约 125GiB,在两台机器上都得到确认(峰值相差约 0.2GiB)。B200 更大的 HBM(180 vs 141GiB)可以推到约 350k token 以上——这些序列H200 无论如何都装不下——而这恰恰是 B200 加速比最大的区间。这就是第二部分"更多内存"优势的极端形态:过了 256k,比较不再是"B200 更快",而是"H200 根本干不了这活"。
Caveats
1. unpacked vs packed 序列
上面每一次运行都喂入一条稠密序列→ 真正的全 O(s²) 注意力,这正是 256K 时注意力占到约 82% FLOP(speedup 表中的"full attn 占 step 比例"列)以及 ≥2× 加速比的原因。真实训练通常用 document maskpacking短样本,使注意力成本变成Σ lenᵢ²而非(Σ lenᵢ)²。例如把每条约 8k token 的样本 packing 成 256k 序列 → 注意力只在每个样本内部运行,其 FLOP 下降约 32×(总注意力工作量从256k²降到Σ lenᵢ² = 256k·8k,因子为256k ÷ 8k = 32;下降因子 = packed seqlen ÷平均样本长度,由每条样本多短决定,而非你 pack 了多少条)。这把注意力份额打回真正 8k 序列的约 13%(对应上面 8K 行),加速比因此回到我们直接测过的稠密绑定区间——约 1.7×(见"稠密路径赤字从何而来"),而非真正长上下文的约 2×。≥2× 的结果仅适用于真正很长的单篇文档——在假设头条数字可迁移之前,先确认你的负载处于哪个区间。
2. 在同一软件栈上对比
写这篇指南时作者最初没注意,把 H200(torch2.10.0/cu129)和 B200(torch2.13.0/cu130)对比,得到了非常不同的结果,B200 大幅受益。怀疑 CUDA 版本后,作者在 H200 上单独重跑了 torch 2.10.0–2.13.0 分别搭配 cu129 与 cu130 的扫描——结果 CUDA 几乎无关紧要。真正的驱动因素是PyTorch 本身:2.12.0 及更高显著快于 2.11.0 及更早,与 CUDA 版本无关。8k、同一 GPU/模型/配置、独立扫描 torch 和 CUDA:
| H200 @ 8k, TFLOPS/GPU | torch 2.10.0 | 2.11.0 | 2.12.0 | 2.13.0 |
|---|---|---|---|---|
| cu129 | 113.8 | – | – | 140.4 |
| cu130 | 117.8 | 120.5 | 140.1 | 140.2 |
H200 上从 torch 2.10.0 全范围到 2.13.0,固定 cu130 时**+19%(117.8 → 140.2 TFLOPS),而且几乎全部收益落在一个点——仅 torch 2.11.0 → 2.12.0 一跳就+16%(120.5 → 140.1)。CUDA 至多贡献约 3.5%(torch 2.10.0 时 113.8 → 117.8),到 torch 2.13.0 时基本为零(140.4 vs 140.2)。所以最初触发这次调查的 2.10.0/cu129 → 2.13.0/cu130 对比(113.8 → 140.4,+23.4%**)几乎完全是PyTorch 版本伪影,不是硬件,甚至不是 CUDA。本文所有结果均使用完全相同的软件栈(torch 2.13.0/cu130、deepspeed 0.19.2)。如果跳过这一步检查,你会系统性地高估恰好跑在更新 PyTorch 版本上的那块 GPU。
B200 值不值约 2× 的 H200 成本?
为简化起见,先假设成本差为 2×——新 GPU 家族刚发布时通常如此。Blackwell 自 2026 年年中面市,实际成本差已小于 2×。请用你自己的报价而非网上信息计算。
按 2× 价差做算术:
- 长 unpacked 上下文(128k–256k):约 2.0× 吞吐换约 2× 成本 → $/token 打平,然后凭两点净赚:(1)墙钟时间减半(2)更多内存解锁 H200 根本装不下的上下文(≥256k)——而这正是 B200 加速比峰值处,两者叠加。
- 短 / packed-short(稠密绑定):约 1.7× 换 2× 成本 → 当前在 $/token 上亏。此 batch size 下稠密路径是带宽绑定而非计算绑定(见"稠密路径赤字"),所以别指望 cuBLAS sm_100 成熟度单靠自己追上 2.28×——它收敛于约 1.67× 的 HBM 带宽天花板。要在稠密区更接近 2.28×,需要更大 batch/更大 GEMM 让稠密路径重新变成计算绑定。
超越 $/token——时间维度。仅看 cost-per-performance 可能用错指标,因为它把慢而便宜和快而贵视为等价——只要每 token 成本相同——却忽略了到达结果的墙钟时间。
- 训练上,多花 2× 时间可能意味着输掉先发制人的竞争,这是任何 $/token 节省都补偿不了的。
- 推理上,2× 更慢直接恶化用户体验——更高的 TTFT(time to first token)和 TPOT(time per output token)——无论每 token 算术多划算都可能让你流失用户。
- 原则上你可以在便宜 GPU 上砸约 2× 的数量买回速度,但那通常意味着更多跨 GPU(往往跨节点)通信,增加开销,可能侵蚀甚至超过你要找回的加速——尤其对通信绑定负载。所以把原始速度优势作为独立轴来衡量,而不只是 $/token 比率里的一个项。
本例结论:真正长上下文训练值得升级;短/packed 负载先别急,因为那里的稠密路径是带宽绑定而非计算绑定(见下文),在此 batch size 下到不了完整 2.28× 硬件比值。
稠密路径赤字从何而来(为什么到不了完整 2.28×?)
对 8k step 的深潜(ZeRO-2、无 activation checkpointing、为短上下文定尺寸)解释了为什么稠密路径把加速比压到硬件比值之下。下面三个桶共享同一时钟——实测的墙钟 step 时间,按各桶在计算流内核时间中的份额拆分(attention = FlashAttention 内核;NCCL 梯度通信与 backward 重叠、隐藏在墙钟内)——因此各桶与总时间天然对账。用bench_decompose.py复现。
8k step 分解(注意力约占 FLOP 13%、step 时间约 12%;其余为稠密路径):
| bucket | H200 TFLOPS | H200 MFU | B200 TFLOPS | B200 MFU | ratio |
|---|---|---|---|---|---|
| attention (FA) | 447 | 45% | 834 | 37% | 1.87× |
| everything else | 463 | 47% | 771 | 34% | 1.67× |
| total | 461 | 47% | 778 | 35% | 1.69× |
两点突出:
- 注意力(FA4 vs FA3)在 step 内实测缩放 1.87×,与隔离微基准一致(
bench_flash_attn.py,FA4 vs FA3,8B 注意力形状、因果:fwd+bwd8k 时 1.88× → 32k 时 1.95×)。注意力接近 2.28× 天花板,不是瓶颈。 - 天花板是 1.67× 的稠密"everything else"桶——几乎正好等于HBM 带宽比值(8 vs 4.8TBps = 1.67×)。mbs=1 × 8k 下每 GPU 的 GEMM 很小,稠密路径是带宽/开销绑定(norm/RoPE/SwiGLU/CE elementwise + NCCL 通信 + 细长 GEMM),Blackwell 的 2.28×计算优势大部分闲置,该桶改而跟随内存带宽。这把混合总加速拖低到1.69×。
Liger-Kernel(融合 RMSNorm/RoPE/SwiGLU/CE)在 8k 是内存收益而非速度收益:峰值内存降约 20%(99 → 80GiB,两卡相同),step 时间在噪声内(两机都 ≤1.5%),混合加速基本不变(约 1.66×)。融合带宽绑定的 elementwise 运算在这里不提升吞吐,因为稠密路径已被 GEMM 尺寸和通信限制,而非那些 op——与桶跟随 HBM 带宽一致。cuBLAS sm_100 比 Hopper 的 cuBLAS "年轻",且 FA4 采数时还是 beta(现已作为flash-attn-4包发布),所以这个稠密路径赤字应随时间缩小——定期重跑该基准,不要视今天的数字为永久。
实验环境
| B200 | H200 | |
|---|---|---|
| GPU | NVIDIA B200 | NVIDIA H200 |
| attention | flash-attn-4 4.0.0b22 (beta) | flash-attn-3 3.0.0 |
| PyTorch / CUDA | 2.13.0 / cu130 | 2.13.0 / cu130 |
| deepspeed | 0.19.2 | 0.19.2 |
| python / transformers / Liger-Kernel | 3.12.12 / 5.14.1 / 0.8.0 | (相同) |
软件支持:过早切换的代价
新硅片几乎总是领先于能完全利用它的软件栈。"GPU 可用"和"GPU 能以标称性能被你的负载使用"可能相隔数月——而且这种差距可能是按模型架构的,而非仅按 GPU。这个基准中直接可见两种具体形式:
- 优化内核本身可能仍是 beta。这里的 B200 注意力路径是
flash-attn-4 4.0.0b22——beta 而非 GA。Beta 内核可能有正确性 bug、缺失特性和 1.0 前的破坏性 API 变更;钉住精确版本、每次升级重测、查项目 issue tracker,而不是默认"它在 PyPI 上"就等于生产可用。 - 即使头条内核没问题,栈的其他部分也可能滞后。隔离的注意力(FA4 vs FA3)这里已达约 1.9×,接近 2.28× 硬件比值——但稠密路径只到约 1.7×(它跟随 HBM 带宽比值,此尺寸下带宽/开销绑定,且新
sm_100架构上的 Blackwell cuBLAS 比历经多年成熟的 Hopper cuBLAS "年轻")。净效应:你可能运行着最好的注意力内核,却仍只看到理论加速的一小部分,因为栈里一个不起眼的部分——没人放在幻灯片上的那部分——还没赶上。
在为新架构承诺预算前的实用检查清单:
- 在内核库的 issue tracker 里按你 GPU 的确切 compute capability(如
sm_100)和你的模型注意力/MoE 机制名称搜索——README 说"supported"不代表 GA 质量,甚至不代表预编译 wheel 存在。 - 确认你的训练框架(DeepSpeed、Megatron-LM、TorchTitan 等)有已发布且对新 compute capability 做过验证的版本——"应该能用,只是 CUDA 而已"不等于测试过。
- 如果你的模型用了非标准 op(线性注意力、MoE 路由、稀疏注意力、融合自定义 CUDA 扩展),确认确实有人在新架构上构建并基准测试过它。不要因为 GPU 更快就假设它继承 GPU 的加速比。
- 定期重新测量,而不是相信一次性结论。Beta 内核和年轻 GEMM 库都进步很快;cuBLAS 成熟度缺口正是那种可能在几个发布周期内把"尚不值得"翻转为"值得"的移动目标——若出现回归,也可能反向。
租用目标新硬件
虽然你或许可以依赖别人替你完成分析工作(比如本指南),但工作负载通常各不相同,最好对你确切的工作负载做基准。
因此,建议先租用至少一个节点的目标 GPU 并就地跑基准。
如果工作负载涉及多节点,先尝试把工作负载缩减到单节点做性能对比。例如缩小模型层数让它小得多——ML 模型架构通常是相同重复层的堆叠,所以把 48 层模型砍到 1-2 层几乎不占 GPU 内存,轻松装进单节点,同时保持逐层计算/内存行为具有代表性。
如果工作负载涉及多节点,你最终当然需要跑完整最小副本配置,但可以等单节点对比给出有利于升级的结果后再做。如果单节点结果不利,你就省下了租额外节点的钱和时间。
把你的升级决策套用这套框架
换上你自己的模型、GPU 和价格,然后按两段式框架走——先 第一部分(dtype 能力检查),若功能未定论再走 第二部分(性能):
- 在两块 GPU 上钉住完全相同的软件栈(见 Caveats 中的"在同一软件栈上对比")——否则你测的是软件栈而非硬件。
- 扫描会移动你 attention/dense(或其他加速/非加速)比例的轴——LLM 训练是序列长度;其他工作负载可能是 batch size、分辨率或完全其他的东西。
- 在旧 GPU 上扫描内存受限配置直到 OOM,看看新 GPU 还能额外装下什么。
- 取新旧两边的实际 $/GPU-hour,在扫描的每个点计算 $/token 或 $/step,而不是只在扫描顶端算。
- 检查会使比较失效的坑:beta 内核、packed vs unpacked 数据、热降频、同节点跨 GPU 的硅片彩票差异(见 compute/accelerator/README.md 的"并非所有加速器生而平等")。
如果扩展用 FSDP——它与 DeepSpeed ZeRO 性能大致相当——你可能需要微调配置以匹配自己的设置,但理想情况下还是基准你自己的确切软件。
同代升级:B200 → B300(Blackwell Ultra)
以上比较的都是跨代(Hopper → Blackwell)。同代 refresh——如 B200 →B300——是不同且通常更小的决策。同一两段式框架适用,但答案以可预测的方式偏移。
| 规格 | B200 SXM | B300 SXM | 比值 |
|---|---|---|---|
| bf16 / fp8 TFLOPS(理论) | 2250 / 4500 | 2250 / 4500 | 1.0× |
| fp4 / nvfp4 TFLOPS(理论) | 9000 / 10000 | 12600 / 15000 | ~1.4–1.5× |
| bf16 MAMF(可实现) | 1745 | 1769 | ~1.01× |
| HBM(可用) | ~180GiB | ~288GiB | 1.6× |
| HBM 带宽 | 8.0TBps | 8.0TBps | 1.0× |
| TDP | 1000W | 1300W | 1.3× |
这对 should-you-upgrade 框架意味着:
- [第一部分(需要新 dtype 吗?)很少触发。B300 没有引入 B200 缺少的 dtype。唯一能像第一部分缺口一样起作用的是内存:288 vs 180GiB(1.6×)是个大跳跃,所以即使加并行也无法装进 B200 节点的模型/配置,可能直接装进 B300 节点。
- [第二部分(性能值吗?):唯一的实际计算提升是 fp4(约 1.4–1.5×)——bf16/fp8 不变,所以 B300 主要对低精度推理/训练和额外内存有回报。
- 软件成熟度风险低。同一架构家族(
sm_100)、同一 FA4/内核栈——跨代案例中"过早切换"的成本在这里不存在。
复现这套基准
本指南的每一个数字都来自本目录的脚本,没有手填数据。下面精确列出哪个脚本产出哪张表/图,以便重新生成(或在自有 GPU/模型上重跑)。所有脚本自动检测 GPU(Hopper→FA3,Blackwell→FA4),并在输出头部回显解析出的后端与完整环境,因此相同的命令可跑在两台机器上。
文件速览
| 文件 | 用途 | 产出 |
|---|---|---|
install.sh | 一次性安装:钉住匹配的 torch/CUDA/依赖,安装 FA3(Hopper)或 FA4(Blackwell),把模型暂存到本地磁盘 | 相同软件栈环境("在同一软件栈上对比"这一 caveat) |
benchmark.py | 训练循环(fwd+bwd+step)、真实权重、逐 step 打印 JSON(tflops、peak_mem_gib);顶部配置块、可用环境变量覆盖(SEQ_LEN、STEPS、WARMUP_STEPS、ZERO_STAGE、OFFLOAD_OPTIMIZER、GRAD_CHECKPOINT、USE_LIGER、MEM_DEBUG) | speedup 表和内存表的一行 |
run_sweep.sh | 在多个序列长度列表上驱动benchmark.py,日志写入results_<gpu>_<ts>.log | speedup-vs-seqlen和max-seqlen/内存表 |
bench_flash_attn.py | 隔离的 FA3/FA4 注意力内核微基准(多个 seqlen 上的 fwd / fwd+bwd TFLOPS) | "稠密路径赤字"中的隔离注意力数字 |
bench_decompose.py | 一个被 profile 的训练 step,把实测墙钟时间按注意力(FlashAttention 内核)vs everything-else 桶拆分在单一时钟上(env 可覆盖:SEQ_LEN、ZERO_STAGE、GRAD_CHECKPOINT、OFFLOAD_OPTIMIZER、USE_LIGER) | "稠密路径赤字"中的step 分解表 |
plot_results.py | 用扫描数字绘制的 matplotlib 图(数据硬编码在脚本顶部) | results_plot.png |
第 1 步——在每块 GPU 上搭建相同软件栈(每节点一次)
在 H200 机和 B200 机上运行同一安装脚本。它钉住完全相同的 torch/CUDA/依赖,使唯一预期差异是注意力后端,然后在 Hopper 自动安装 FA3 / Blackwell 自动安装 FA4,并把模型暂存到本地磁盘:
./install.sh # H200 -> FA3, B200 -> FA4(自动检测);--force fa3|fa4 可强制覆盖HF_HOME默认~/.cache/huggingface;模型(meta-llama/Llama-3.1-8B)须先存在那里(如hf download meta-llama/Llama-3.1-8B)。安装器最后一步验证软件栈并做一次微型 FA 调用以捕获 ABI 不匹配。
第 2 步——在每块 GPU 上运行序列长度扫描(speedup + 内存表)
SEQLENS="8192 32768 65536 131072 196608 262144" GPUS=8 ./run_sweep.sh # -> results_<gpu>_<ts>.log两台机器都跑。每 step 打印一行 JSON,如{"step": 5, "warmup": false, "exec_time_ms": ..., "tflops": ..., "peak_mem_gib": ...};取稳态(非 warmup)tflops用于吞吐/speedup 表,peak_mem_gib用于内存表。B200/H200 speedup 就是两个机器每个 seqlen 上tflops的比值。(省略环境变量的默认值:单 seqlen 196608、8 GPU、10 steps + 2 warmup。)定义运行的所有配置——ZeRO-3、activation checkpointing、CPU AdamW offload、Liger-Kernel、mbs=1——都在benchmark.py的配置块中,并在每次运行的头部回显。
第 3 步——隔离注意力微基准(稠密路径深潜)
python bench_flash_attn.py # 打印每个 seqlen 的 FA3 或 FA4 的 fwd / fwd+bwd TFLOPS两台机器都跑;每个 seqlen 的fwd_bwd_tflops的 FA4/FA3 比值就是"隔离注意力"结果,显示注意力本身缩放约 1.9×——即限制端到端加速比的是稠密路径而非 FA。
第 4 步——step 分解(attention vs everything-else 桶)
for L in 0 1; do USE_LIGER=$L deepspeed --num_gpus=8 bench_decompose.py; done # L=0 基础,L=1 Liger两台机器都跑。它先测墙钟 step 时间(profiler 关),再 profile 一个窗口,把测得的时间按其在计算流内核时间中的份额拆成 attention 桶(FlashAttention 内核)和 everything-else 桶(NCCL 通信与 backward 重叠、作为隐藏排除)。因为两个桶都从同一个实测 step 中切出,它们与总时间天然对账——这就是step 分解表。每个桶的 B200/H200 比值就是分桶加速比(attention 约 1.87×,稠密路径约 1.67×)。
第 5 步——内存用量调查(可选)
MEM_DEBUG=1 SEQ_LEN=32768 deepspeed --num_gpus=8 benchmark.pyMEM_DEBUG=1在 fwd/bwd/step 前后加入分阶段 alloc/reserved 探针,并在 rank 0 上 dump 一份torch.cuda.memory._record_memory_history快照——对诊断 GPU 内存用量很有用。
第 6 步——重新生成图表
python plot_results.py # -> results_plot.png注意:plot_results.py的扫描数字硬编码在脚本顶部(它不解析.log文件)。如果重跑扫描得到不同数字,请更新plot_results.py中的数组以及上文的表,再重新生成。
进一步阅读
- Accelerators —— 完整规格表(全厂商、全 dtype)、MAMF 方法论、内存/功耗/时钟参考、硅片彩票与散热笔记。
- 人工智能
- 大模型
- AI 技能/插件
- 分布式训练
- 微调
- 深度学习
【免费下载链接】ml-engineering
Machine Learning Engineering Open Book
相关推荐
FlashMLA性能基准测试:H800 vs B200 GPU对比分析
FlashMLA性能基准测试:H800 vs B200 GPU对比分析 FlashMLA作为DeepSeek团队开发的高效多头部潜在注意力(MLA)解码内核,在
算子库大模型Redpanda Connect AWS 基准测试框架:基于 Terraform 的生产级 Bench 与 Soak 压测体系
Redpanda Connect AWS 基准测试框架:基于 Terraform 的生产级 Bench 与 Soak 压测体系 导读 benchmarking/
数据集成流处理ETL变更数据捕获消息路由Dear PyGui 是什么、为什么值得用:一个基于 GPU 渲染的 Python GUI 框架深度解析
Dear PyGui 是什么、为什么值得用:一个基于 GPU 渲染的 Python GUI 框架深度解析 Dear PyGui(下文简称 DPG)是一个简单、无
桌面应用UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考