1000 美元能买到什么级别的语言模型?Hugo Vergnes 用一份可复现的答案更新了这个问题的基准线:3.8B 参数的自研模型 little-lm,在 8 张租来的 B200 上训练 43 小时,花费 998 美元,CORE 评测得分 0.384。这个分数比 OpenAI 2019 年动用整个实验室资源训练的 GPT-2 1.5B(0.2565)高出超过四成,也超过了 Karpathy nanochat d32 在约 1000 美元预算下拿到的 0.310。
训练框架 little-lm 与完整实验报告均已公开,报告写于 2026 年 9 月 4 日,逐项记录了哪些改动有效、哪些被放弃、以及一个评测环节里藏了几个月的测量陷阱。对想理解「小预算训练 LLM 到底难在哪」的开发者来说,这是一份少见的、每个数字都能对上账的实验记录。

先看账本:同样的 1000 美元,买到什么
把三个模型放在同一张表里,预算接近,结果差距可以直接从表里读出来:
| 模型 | 参数量 | 训练 token | 硬件 | 耗时 | 成本 | CORE |
|---|---|---|---|---|---|---|
| GPT-2(OpenAI,2019) | 1.5B | — | — | — | — | 0.2565 |
| nanochat d32 | 约 1B | — | 8× H100 | 约 33h | 约 $1000 | 0.310 |
| little-lm(1024 ctx) | 3.85B | 57.3B | 8× B200 | 35.9h | $820 | 0.338 |
| little-lm(2048 ctx) | 3.85B | 65.3B | 8× B200 | 43h | $998 | 0.384 |
CORE 是 DCLM 使用的评测基准,22 个任务聚合成一个 0 到 1 的准确率分数,随机基线大约在 0.25 上下。little-lm 的 0.384 意味着 22 个任务上的平均正确率已经明显脱离随机区间,其中 boolq 到了 0.7095、bigbench_language_id 0.2585(该任务对当前规模仍接近随机水平)。
架构上这是一只标准的 Llama 系:RMSNorm、RoPE、GQA(24 个查询头对 8 个 KV 头)、relu² 非门控 MLP、QK-norm、logit softcap,外加每层可学习的残差缩放系数和 ResFormer 风格的价值嵌入(value embeddings)。参数分布里有个容易被忽略的细节:28 层解码器占 28.19 亿参数,而 14 张价值嵌入表占 7.21 亿,约 19% 的参数预算花在了「查询表」上。
从失败跑开始:858M 的六天换来的教训
little-lm 的第一轮正式实验并不成功。作者先训了一个 858M 的 Llama 架构模型,用 FineWeb-Edu 数据、AdamW 优化器、cosine 学习率衰减,单张 A100 跑了 5.8 天,只得到 PIQA 60.45% 的成绩——比参数量只有它七分之一的 GPT-2 124M(约 63%)还低。
复盘找出了四个问题,每一个都值得单独记下来:
cosine 衰减把最后 30% 的算力浪费掉了。 学习率在训练后段被压得过低,loss 曲线在 70% 进度后就基本走平,剩余预算没有产生实质学习。改用梯形调度(trapezoidal):5% warmup,中段保持峰值,最后 50% 线性冷却到峰值的 5%。效果直接体现在 3.8B 的正式跑上——eval loss 到最后一步仍在下降。
峰值学习率太保守。 2.5e-4 对 858M 的模型来说偏低,这个尺度的模型可以承受更激进的设置。
优化器选择。 后续正式跑改用复合优化器:矩阵参数用 Muon,其余(嵌入、LM head、价值嵌入、标量)用 AdamW。Muon 的 Newton-Schulz 正交化每步额外开销约 25%,但因为每 7 个 micro-step 才做一次优化器更新,摊到总时长只剩约 4%,换来的是明显更快的收敛。
数据从 FineWeb-Edu 换成 ClimbMix。 作者称这一项带来了「收敛速度的巨大跳跃」,与 Karpathy 在 nanochat 中的观察一致。
吞吐量优化:单卡 5090 上的省钱工程
在租 B200 之前,作者先在自己的 RTX 5090 上把 858M 基线的吞吐从 26,144 tok/s 提到 37,621 tok/s(+44%)。这套优化组合直接决定了正式跑的成本:
- FP8 训练(+25%):前向和两次反向共三个 GEMM 全部走
torch._scaled_mm的动态 tensorwise 缩放,需要 SM90 以上硬件。 - 词表 padding(与上一项合计 +33%):把词表从 50,257 补到 50,304(64 的倍数),只浪费 47 行嵌入,换来 tensor core 的对齐快速路径。
- 融合线性交叉熵:用 Liger 的 FusedLinearCrossEntropyLoss 把 lm_head 矩阵乘融进损失计算、分块处理,避免显式分配 (B×T, vocab) 的 logits 张量。单独对比它其实慢 6%,但省下约 8GB 显存,允许把 micro-batch 从 6 开到 10,净吞吐反而更高。作者提到 Claude 一开始因为那 6% 否决了这个方案。
- 去掉门控 MLP:SwiGLU 换成 relu²,三个矩阵乘变两个,5090 上吞吐从 183,035 提到 214,173 tok/s,还省 6GB 显存。代价是一个迁移陷阱:SwiGLU 常用的 2.75 倍中间层比例不能直接搬给 relu²,模型会明显学得更差,非门控结构要用 4 倍。
- bf16 主权重:优化器主权重从 fp32 降到 bf16,1.5B 配置上吞吐从 640K 提到 1.4M tok/s(2.2 倍),显存省 27%。质量代价真实但很小:4,000 步时 CORE 0.22 对 0.23。
正式跑的硬件效率数据:480,000 tok/s 稳态吞吐,单张 B200 持续约 1,047 TFLOP/s,对 Blackwell 密集 FP8 峰值约 25% MFU(对 bf16 峰值约 50%——作者认为后者更有参考意义,因为并非所有线性层都跑在 FP8 上)。92% 的 SM 活动率说明没有数据加载或网络等待造成的空转,40% 的 SM 占用率则是大 GEMM 背靠背执行的正常形态。
分布式策略没有用任何花活:单节点 8 卡裸 DDP。3.8B 的梯度通信量远未构成瓶颈,分片优化器在这个规模属于多余机器。
价值嵌入消融:19% 的参数换 5% 的训练量
价值嵌入占了 3.85B 总参数的 19%,是全模型最贵的单一组件。作者用已经付过钱的原始 run 做对照,关掉价值嵌入重训到 12,500 步(29B token):
| 配置 | 参数量 | 12.5K 步 loss | 12.5K 步 CORE | 吞吐 |
|---|---|---|---|---|
| 价值嵌入开 | 3.848B | 2.1075 | 0.3147 | 479,445 tok/s |
| 价值嵌入关 | 3.128B | 2.1171 | 0.3047 | 477,908 tok/s |
结论有三层。其一,loss 只差 0.46%,CORE 却差 3.2%——CORE 对模型能力差异的放大倍数约为 loss 的七倍,因为它是对齐随机基线的准确率指标,决策边界附近的题目会随微小 logit 变化翻转。其二,按训练进度折算,价值嵌入的收益相当于白送约 1,200 步(总步数的 5%)。其三,嵌入查表几乎不消耗 FLOPs,吞吐完全不受影响,成本只体现在显存和优化器状态上。
作者同时诚实列出了这个消融没回答的问题:对照组是「有对没有」,真正该问的是「这 7.21 亿参数花在价值嵌入上,和花在别处,哪个更值」。
被放弃的方案:失败清单的价值不亚于成功清单
报告里「什么没用」一节的密度不输有效改动:
- 文档边界掩码(flex attention):为了阻止打包序列中 token 跨文档互相注意,作者实现了基于 per-token 文档 ID 的注意力掩码——然后整段删掉。BOS 对齐的打包下,跨文档泄漏并没有明显伤害,10 行的 best-fit packing 加无条件因果注意力就够了。Karpathy 得到过同样结论。
- Liger RMSNorm 和 RoPE:微基准里 RoPE 快 2.2 倍,端到端吞吐毫无变化——它们不在关键路径上;Liger RMSNorm(0.41ms)甚至比 PyTorch 2.9 内置实现(0.25ms)更慢。两个都回退。
- nanochat 式初始化:理论上更优雅的初始化方案,loss 曲线起点略低,约 1,500 步后与 GPT-2 式初始化完全重叠。保留了,但理由是审美而非证据。
- 流式数据集:本地 shard 比流式加载多 2-3% 吞吐,且网络抖动一次的代价远超这个数。超过几小时的训练,数据一次性下载到本地是正确做法。
一个值得所有跑评测的人记住的测量事故
1024 上下文版本得 0.338 分,2048 版本得 0.384 分,差 0.046。看起来是上下文长度带来的模型能力提升,但拆开任务明细后,故事完全变了。
1024 跑中,22 个 CORE 任务里有 3 个的 prompt 绝大多数塞不进上下文:SQuAD 被截断 100%,boolq 99.8%,bigbench_language_id 99.7%。SQuAD 最戏剧化——得分不是停滞,是从 0.1478 单调跌到 0.0000。模型越训,这道题越差。
原因在评测管线而非模型。SQuAD 在 DCLM 里是 10-shot 任务,每条 prompt 含十个示范样例再加真实题目,中位长度 1,998 token,在 1024 上下文里没有一条能完整放下。截断逻辑保留最后 1,024 个 token,测试段落和问题位于末尾所以幸存(测试样例本身只有约 169 token),被截掉的是开头那十个教学示范。模型一直在读段落和问题,却几乎从没见过教它输出格式的示范。而 SQuAD 按精确 token 匹配打分,流畅但格式不对的答案得零分。
分数单调下降也有了合理诨释:早期高熵模型偶尔碰巧吐出能匹配的短答案,随着模型变强、输出变得更规范,这些「蒙对」的机会反而消失——语言能力变好,让瞎猜变得更不准。
扩到 2048 后,SQuAD 截断率降到 47%,得分 0.3114;boolq 3.2%,得分 0.7095。两个任务的改善合计贡献了总提升的 83%,剩下 19 个任务加起来只动了 0.008。换句话说,0.046 的提升里绝大部分是测量修正,不是能力增长。作者由此给出的结论很克制:2048 上下文首先是一个测量决策,其次才是质量决策;如果只关心训练吞吐,1024 的性价比依然成立。
这段事故对任何自己搭评测管线的人都有直接参考价值:截断策略会系统性重置特定任务的分数,而一个单调下降的任务分数不一定是模型退化,可能只是它在越来越擅长「不蒙对」。
成本结构之外:这件事改变的是什么
把报告里的事实并排放齐:一个工程师, evenings 时间写代码,在 5090 上调试、租 B200 完成正式跑,998 美元,43 小时,3.85B 参数,65.3B token,CORE 0.384。GPT-2 1.5B 在 2019 年需要一支资金充足的实验室团队,七年后同样的分数门槛成了个人项目能反超的下限。
作者自己在报告结尾的说法是:前沿移动的时候,所有东西都跟着移动,过去需要一个实验室的工作,现在一个工程师在晚上就能完成。报告没有回答、也回答不了的问题是可持续性——0.384 距离实用仍有整个数量级的距离,价值嵌入相对其他参数用途的优劣、1024 与 2048 在同等墙钟时间下的对比、Muon 在单卡上的冗余正交化怎么用优化器分片消掉,都被作者列进了未完成清单。
对于关注「个人还能不能训练出有意义的语言模型」的人来说,这份报告给出的不只是动机,而是一整套可以照抄的配置:从梯形学习率、Muon+AdamW 复合优化器、ClimbMix 数据,到 FP8、词表对齐、融合损失的吞吐三板斧,再到「先本地化数据、再谈流式」的工程判断。1000 美元买不到前沿模型,但 2026 年的 1000 美元,已经能买到一次对训练全流程的完整理解——以及一个在 22 项评测里稳定脱离随机水平的 3.8B 模型。
来源: