
ChatGPT
从零训练 ChatGPT 式模型:三种训练方案实测对比与踩坑指南
从零训练一个 ChatGPT 式的小模型,真正决定训练速度的往往不是 GPU 算力,而是注意力实现、精度方案与多机同步。本文整理三种训练路径的对比方法、完整操作流程与常见坑,帮助你在投入长时间训练前先做小规模试跑。
很多人以为从零训练一个 ChatGPT 式模型,拼的是 GPU 算力。实际跑起来会发现,算力往往不是瓶颈:注意力实现选错、精度方案选错、多机同步没对齐,都会让一块标称性能很高的芯片长期只发挥出四分之一的实力。本文整理一套可复用的训练流程,讲清楚三种训练数学路径(Transformer Engine 的 FP8、更新的四位 NVFP4、以及训练框架自带的 FP8 实现)该怎么对比、怎么试跑、怎么读监控指标,适合已经会本地跑推理、想进一步尝试从零训练小模型的人。如果你只是想先熟悉对话模型本身的能力边界,可以先看看站内的 ChatGPT 工具页,再决定要不要自己动手训练。
准备工作
在开始之前,需要把下面这些东西准备好。这里列的是完成一次完整训练所需的最小集合,具体版本与可用性请以各项目官网当前信息为准。
硬件
- 至少一台具备统一内存的 AI 小型机或工作站。本文讨论的场景是单机与双机两种配置。
- 如果要做双机训练,两台机器的型号、内存容量、驱动版本应尽量一致。两台机器性能不一致时,整体速度会被较慢的那台拖住。
- 注意供电。部分小型机的供电适配器内置 USB-C 供电协商控制器,该控制器异常时会把 GPU 频率压到很低的水平,而且不会报出常规的降频标志。
软件与依赖
- 训练框架:本文以 nanochat 这类从零实现的小型训练框架为例。它默认针对多卡 H100 环境调优,迁移到其他硬件时需要重新检查注意力路径。
- 注意力实现:优先确认 FlashAttention 3 是否可用。不可用时框架会回退到 PyTorch 的 SDPA,而 SDPA 无法处理滑动窗口注意力模式。
- 精度库:Nvidia Transformer Engine,用于 FP8 与 NVFP4 路径。
- 实验记录:Weights & Biases 或同类工具,用于记录损失、吞吐、功耗与显存。
- 性能分析器:用于抓取 GPU 频率、显存占用与算子耗时。
账号与数据
- 实验跟踪平台的账号与 API Key。
- 训练语料与分词器。本文示例使用约 52 亿到 88 亿 token 量级的语料。
- 一份明确的训练配置:层数、参数量、批大小、序列长度、总步数。这些数字决定了后面所有对比是否有意义。
先想清楚要对比什么
三种路径的差别主要在数值精度与算子实现上:
| 路径 | 精度 | 特点 |
|---|---|---|
| Transformer Engine FP8 | 8 位浮点 | 较新的官方路径,工具链更新快 |
| Transformer Engine NVFP4 | 4 位浮点 | 位数更少,理论上更省显存 |
| 框架自带 FP8 | 8 位浮点 | 框架内实现,未必是最新,但可能更贴合模型结构 |
直觉上「位数更少、工具更新」应该更快,但实测未必如此,所以必须做小规模试跑,而不是直接押注。
操作步骤
第一步:确认注意力路径
这是最容易被跳过、代价也最大的一步。启动训练后,先看日志开头的警告信息。如果出现类似「FlashAttention 3 不可用,已回退到 SDPA」以及「你的 GPU 利用率会很糟糕」的提示,说明注意力路径没有走对。
回退到 SDPA 的后果是:滑动窗口注意力模式无法被正确加速,GPU 会长时间处于「有 kernel 在跑、但芯片大部分空闲」的状态。日志里给出的警告不是危言耸听,它直接决定了整轮训练能发挥出多少算力。
处理原则很简单:在按下开始之前把注意力路径修好。一轮长训练跑到中途才发现问题,重启的代价通常高于修复带来的收益。可以按下面的经验判断:假设修复能带来约 20% 的加速,那么对于一轮长达数天的训练,只有在最初一天左右重启才是划算的。
第二步:做几十步的试跑对比
不要直接开一周的长训练。先用同一对机器、同一份配置,跑 20 到 50 步,记录每一步的耗时与峰值显存。
试跑时至少记录这几个量:
- 每步耗时(秒 / update)
- 每台机器的峰值显存占用
- GPU 频率
- 整机功耗
- 模型 FLOPs 利用率(MFU)
一个典型的双机试跑结果如下(同一对机器、同一时间窗口、第 5 到第 20 步):
| FP8 方案 | 每步耗时(秒) | 单机峰值显存 |
|---|---|---|
| Transformer Engine FP8 | 3.967 | 73.3 GiB |
| 框架自带 FP8 | 3.149 | 51.9 GiB |
也就是说,框架自带的 FP8 实现每步少用约 20.6% 的时间,显存占用也低得多。在另一对健康机器上重复同样的测试,差距几乎一致,约 20.5%。
四位 NVFP4 的结果同样反直觉:它比 FP8 少用约 7% 的显存,但每步慢约 7%。位数更少并没有换来速度。
所以试跑阶段的结论是:更新的方案不等于更快的方案。如果只跑了 20 步就下结论,至少能避免把一整周押在较慢的路径上;但也要清楚,20 步的样本无法推算整轮训练能省下多少小时。
第三步:配置双机同步
把训练拆到两台机器上,会引入单机没有的一项开销:每次参数更新之后,两台机器必须交换状态,才能继续下一步。
假设每次更新覆盖 65536 个 token,一轮训练跑了 133633 次更新,那么这种同步就发生了 133633 次。任何一台没算完,另一台都不能往下走。
可以用两个人抬沙发上楼来理解:能走多快取决于慢的那个人;一个人停下来喘气,另一个人只能站在原地扛着。
当两台机器性能接近时,同步本身的成本很低。当两台机器性能不匹配时,快的那台会把大量时间花在等待上。实测中曾出现这样的情况:一台 GPU 频率约 600 MHz,另一台接近 2190 MHz,在每次约 7.2 秒的更新里,快的那台有约 3.3 秒纯粹在等对方。
第四步:检查每台机器的频率与供电
双机训练出问题时,先怀疑较慢的那台。排查顺序建议如下:
- 用性能分析器抓取两台机器在负载下的 GPU 频率,确认是否一致。
- 如果某台被压在 600 MHz 附近,且没有常规的降频标志,优先怀疑供电适配器内的 USB-C 供电协商控制器卡死。
- 普通重启可能无法清除该状态。可以尝试把适配器从墙上完全断电,让两台机器冷放电后再上电。
- 恢复后重新跑同一段测试,观察每步耗时是否下降。
实测中,冷放电之后那台机器在负载下回到约 2190 MHz,同一段测试的每步耗时从 7.2 秒降到 3.9 秒,等待时间几乎消失。
需要说明的是,这种频率异常不一定会影响已经跑完的长训练。有一轮为期约 151 小时、共 133633 次更新的训练,平均每步约 4.07 秒,与试跑阶段的数字一致,说明频率问题是在那之后才出现的。
第五步:读对监控指标
这一步决定了你能不能及时发现上面那些问题。几个容易误读的指标:
- GPU 利用率:它衡量的是「有 kernel 在跑的时间比例」,不是「芯片有多少部分被用上了」。一块 GPU 可以整周显示 96% 利用率,同时只发挥出额定算力的很小一部分。
- 功耗:这是更诚实的信号。如果一块芯片整周大部分时间只拉 50 到 60 W、峰值 90 W,那它并不是在满负荷工作。作为对照,一次纯矩阵乘法测试可以拉到 81 到 85 W,并跑出接近规格的吞吐。
- 模型 FLOPs 利用率(MFU):比利用率图更有参考价值。但要注意,如果框架没有目标硬件的峰值算力数据,这个数字可能整轮都打印成 0.00,并不代表硬件空闲。
- 显存带宽相关图表:某些芯片根本不暴露带宽计数器,跟踪平台上的「GPU 访问内存耗时」可能整周显示 0%。这不代表没有内存瓶颈,只代表测不到。
把功耗、MFU 和每步耗时放在一起看,比只看利用率曲线可靠得多。
第六步:确认显存容量不是瓶颈
在排查内存问题时,先排除容量因素。实测中,单机整轮训练期间始终有至少 26 GB 空闲;双机整轮训练期间,两台机器都没有低于 32 GiB 空闲。也就是说,显存容量并不是限制因素。
真正可疑的是带宽。训练框架原本是在八卡 H100 上调优的,每张 H100 的内存带宽约 3.35 TB/s,而小型机的统一内存带宽约 273 GB/s,相差约 12 倍。由于芯片不暴露带宽计数器,无法直接证明是带宽不足,但可以确定的是:原调优环境的带宽余量要大得多。
一个完整示例
下面把上面的步骤串成一次完整流程。示例分两段:先用单机跑一轮小模型,再用双机跑一轮稍大的模型。
单机阶段
配置:20 层模型,8.965 亿参数,训练语料 52 亿 token。
# 1. 启动训练前,先检查日志开头的注意力警告
# 若出现 FlashAttention 3 不可用、回退到 SDPA 的提示,先修好再继续
# 2. 启动训练,并把指标记录到实验跟踪平台
# 记录项:loss、每步耗时、GPU 频率、功耗、显存占用
# 3. 训练过程中定期抽查功耗
# 若长期停留在 50-60 W、峰值 90 W,说明芯片没有真正跑满
# 4. 训练结束后做一次推理抽查
# 输入:"If 5x + 3 = 13, then x is"
# 早期输出:"5 x 5 x 5 x."
# 训练完成后输出:5
这一轮实际耗时 6 天 21 小时。GPU 利用率全程显示 96%,但功耗大部分时间只有 50 到 60 W,峰值 90 W,时钟稳定在约 2460 MHz。整轮估算约 15 百亿亿次浮点运算,折算下来持续吞吐约 25 TFLOPS。
作为对照,该芯片的公开标称值可换算为约 125 TFLOPS 的稠密 BF16;一次纯矩阵乘法测试跑出 98.6 TFLOPS,功耗 81 到 85 W。也就是说,芯片在只做数学运算时能接近规格,而实际训练只拿到约四分之一。
原因在日志第 0 步就写明了:FlashAttention 3 不可用,回退到 SDPA,无法处理滑动窗口模式。等发现问题时,训练已经跑得太远,重启的代价高于收益,只能让它跑完。
另外两个监控盲区也值得一提:框架自身的效率读数整轮打印 bf16_mfu: 0.00,因为它没有该芯片的峰值算力数据可除;跟踪平台的「GPU 访问内存耗时」整周显示 0%,因为芯片不上报该指标。这两个数字都不代表硬件空闲,但很容易被误读。
双机阶段
配置:两台机器,24 层模型,13.8 亿参数,使用 FlashAttention 2(回退问题消失),精度走 Transformer Engine 的 FP8。
# 1. 两台机器分别确认驱动版本、时钟、供电状态一致
# 2. 先跑 20-50 步试跑,对比三种精度路径
# - Transformer Engine FP8
# - Transformer Engine NVFP4
# - 框架自带 FP8
# 记录每步耗时与峰值显存
# 3. 根据试跑结果选定路径,再启动长训练
# 4. 长训练期间监控两台机器的频率是否一致
# 若一台明显偏低且无降频标志,检查供电适配器
# 5. 训练结束后用性能分析器复查同步等待时间
这一轮跑了约 151 小时,完成 133633 次更新,消耗 87.6 亿 token。每次更新覆盖 65536 个 token,每次更新后两台机器都要同步一次。
试跑阶段的对比结果已经说明问题:框架自带 FP8 每步 3.149 秒、峰值显存 51.9 GiB,优于 Transformer Engine FP8 的 3.967 秒、73.3 GiB;NVFP4 比 FP8 省约 7% 显存但慢约 7%。
长训练结束后复查时发现,其中一台机器的 GPU 频率被压在约 600 MHz,另一台接近 2190 MHz,快的那台每次更新有约 3.3 秒在等待。冷放电两台机器后,该机器在负载下恢复到约 2190 MHz,同一段测试从 7.2 秒降到 3.9 秒。
注意事项
- 先修注意力路径再开跑。 回退到 SDPA 会让 GPU 利用率长期虚高而实际算力利用率很低。假设修复能带来约 20% 加速,那么对一轮数天的训练,只有在最初一天左右重启才划算。
- 不要用 GPU 利用率判断芯片是否跑满。 它只反映 kernel 运行的时间比例。功耗和模型 FLOPs 利用率更可信。
- MFU 显示 0.00 不一定是硬件空闲。 如果框架没有目标硬件的峰值算力数据,这个数字会一直是 0。
- 带宽图表显示 0% 也不一定是没有瓶颈。 部分芯片不暴露带宽计数器,跟踪平台拿不到数据。
- 更新的精度方案不一定更快。 四位 NVFP4 在该场景下比 FP8 省约 7% 显存,但每步慢约 7%。框架自带的 FP8 实现反而比更新的 Transformer Engine FP8 每步快约 20%。
- 试跑样本量要清楚其局限。 20 步的测试能告诉你哪条路径更快,但无法推算整轮训练能省多少小时。
- 双机训练的速度取决于较慢的那台。 两台机器性能接近时同步成本很低;一台异常时,另一台可能有一半时间在等待。
- 频率被压在 600 MHz 附近且无降频标志时,优先怀疑供电适配器。 普通重启可能无效,需要把适配器从墙上完全断电、冷放电后再上电。
- 显存容量通常不是瓶颈。 实测中单机整轮至少空闲 26 GB,双机整轮两台都不低于 32 GiB 空闲。真正可疑的是内存带宽,原调优环境的带宽约为小型机的 12 倍。
- 小模型的对话能力有限。 这类从零训练的小模型大致处于 GPT-2 级别的智能水平,在数学题上可能从早期的胡言乱语逐步收敛到正确答案,在有明确结构的任务(如写俳句)上表现更好。没有联网搜索能力时,它的知识只限于训练语料,对近两年的信息一无所知。
- 价格、配额、硬件规格与软件版本请以各项目官网当前信息为准。 本文涉及的数字均为特定配置下的实测记录,不代表其他环境的表现。