- Why Guide: remove duplicated 20-case/rubric/test-definition tables, link to authoritative Roadmap/Worksheet instead; 10-min action points to entries - Concept Map / What-Is: cross-link narrative vs quick-reference roles - Worksheet: annotate sections with authoritative sources - 04-Reference 01-04 <-> archive/01: bidirectional resource links - archive/00-Material-List: shrink guidebook listing, now reachable from READMEs - guidebook: compress 06-Yearly-Dives 2025 section (-> 08-2025-Edition §3), add old/new version nav banners to 01-05, reverse links in 08 - README/Start-Here: link Learning Board (was orphaned)
28 KiB
type, tags, status, created, source
| type | tags | status | created | source | |||
|---|---|---|---|---|---|---|---|
| reference |
|
active | 2026-08-21 | https://github.com/huggingface/evaluation-guidebook |
Troubleshooting(排错)
本页提炼自 HuggingFace LLM Evaluation Guidebook 的 Troubleshooting 章节(共三小节:推理排错、LaTeX 数学解析、可复现性排错)。这是整本指南中最实操的部分——当评测跑不起来、跑得慢、分数对不上时,先查这里。文内 ⭐ 标记为作者特别推荐的资源。
⚠️ 旧版内容(2024 GitHub 仓库)。新版仅保留「可复现性排错」章节(与旧版基本一致,见 08-2025-Edition §7 的复现提示与 §5.6 Normalization / Math-Verify);推理排错与 LaTeX 解析独立页已从新版删除,本节作为旧版独有实操细节保留。
本节速览(TL;DR)
| 症状 / 诉求 | 第一反应 | 详见 |
|---|---|---|
| 评测跑得太慢 | 增大 batch size → 数据并行 → 换推理库 → 降精度 | §1.1 |
| 模型太大放不进 GPU | 量化 → 模型并行(pipeline / tensor)→ CPU offloading | §1.2 |
| 装得下却 OOM | 怀疑 context size,用 dummy 数据测试 | §1.3 |
| 数学评测分数异常偏低 | 检查 LaTeX 解析器(sympy 自洽只有 0.94) | §2 |
| 复现不出论文分数 | 逐项对齐:代码库 / seed / 指标 / normalization / prompt / 生成参数 / 加载方式 | §3 |
贯穿全章的三条核心心法:① 评测工具链本身也是被测对象——解析器、normalization、指标实现都会系统性改变分数;② 评测不只是"模型回答问题",而是"在特定环境里跑特定管道"——环境细节决定一切;③ 想对比两个分数,先确认它们是不是用同一套管道算出来的。
1 推理排错(Troubleshooting Inference)
评测中跑模型推理会遇到三类典型问题:慢、大(内存装不下)、以及装得下却 OOM。本节逐一给出排查思路。先给一张按症状定位的速查表:
| 症状 | 直接原因 | 对策 | 代价 / 注意 |
|---|---|---|---|
| 推理慢 | batch size 太小 | 增大 batch size | 破坏绝对可复现性 |
| 推理慢 | 只用了单张 GPU | 数据并行(多 GPU) | 需同节点,避免节点间瓶颈 |
| 推理慢 | 推理库实现不够优化 | 换更快推理库 / 参考优化清单 | 需要实测 |
| 推理慢 | 精度过高 | 降到 bfloat16/float16,或 8bit/4bit 量化 |
精度损失,部分量化库本身偏慢 |
| 模型太大 | 精度过高 | 量化 | 中规模模型建议停在 float16/8bit |
| 模型太大 | 单卡放不下 | 模型并行 / CPU offloading | 并行较难编码;offloading 显著更慢 |
| 装得下却 OOM | context size 过大 | dummy 测试 + 降 batch + 逆序呈现样本 | 让失败尽早暴露 |
1.1 模型太慢怎么办
① 修改 batch size
- 如果你追求绝对可复现(给定特定硬件与特定评测 prompt),通常只能用 batch size = 1。
- 但只要内存放得下,调大 batch size 几乎必然显著加速评测——这是最简单的提速手段。
② 数据并行(data parallelism)
- 思路:把模型复制到多张 GPU 上(而不是只加载到一张卡),把数据切成子集分给每张卡的副本,各自计算后再聚合结果。
- 效果:多条数据流同时被处理,总执行时间约除以 GPU 数量。
- 注意:尽量让所有 GPU 在**同一个节点(node)**上,避免节点间通信成为瓶颈(inter-node bottleneck)。
③ 更换推理代码
- 不是所有推理库速度都一样,有些实现优化得更好,需要针对你的用例实测对比。
- 如果使用 PyTorch,作者推荐参考 PyTorch 模型推理性能优化清单。
④ 降低精度(precision)
float32每个数占 32 bit,计算精确但内存与算力开销都大。- 降到
bfloat16/float16(一半精度),速度约翻倍,精度损失几乎可以忽略。 - 想进一步提速可量化到 8 bit 或 4 bit(例如用
gptq或bitsandbytes),n-bit 矩阵计算更快、模型占内存更少。 - ⚠️ 某些量化库本身可能偏慢,需要针对你的场景实测。
贯穿 1.1 的原则:以上手段不是二选一的单选题,而是可以叠加的组合拳(如"大 batch + 数据并行 +
bfloat16"),且提速效果必须在你的硬件与任务上实测确认——作者多次强调"test things out for your use cases"。
1.2 模型太大(GPU 装不下)怎么办
估算内存需求
用如下公式估算加载模型所需的最小理论内存:
<memory (in GB)> = <number of parameters (in G)> × <precision factor>
原理:1 Byte = 8 bit,总内存 ≈ 参数量 × 每个参数占用的 Byte 数。precision factor 取值:
| 精度 | precision factor |
|---|---|
float32 |
4 |
float16 / bfloat16 |
2 |
| 8 bit 量化 | 1 |
| 4 bit 量化 | 0.5 |
更稳妥的推荐公式(留出推理时的 batch 等额外开销):
<memory (in GB)> = <number of parameters (in G)> × (<precision factor> × 110%)
示例估算(用推荐公式
参数(G) × factor × 110%,取 7B 与 70B 两个常见规模):
| 模型规模 | float32 |
float16/bfloat16 |
8 bit | 4 bit |
|---|---|---|---|---|
| 7B | 7×4×1.1 ≈ 30.8 GB | 7×2×1.1 ≈ 15.4 GB | 7×1×1.1 ≈ 7.7 GB | 7×0.5×1.1 ≈ 3.9 GB |
| 70B | 70×4×1.1 ≈ 308 GB | 70×2×1.1 ≈ 154 GB | 70×1×1.1 ≈ 77 GB | 70×0.5×1.1 ≈ 38.5 GB |
由此可快速判断硬件选型:单张 80GB 的 GPU 要跑 70B 模型,
float16(154GB)不行,需要 8bit(77GB,一张卡勉强)或 4bit 量化 / 模型并行;而 7B 模型在float16下单张 16–24GB 的消费级卡即可胜任。
① 量化(quantization)
- 最直接的手段:调小上面的 precision factor。从
float32到 4 bit,内存需求直接缩小 8 倍。 - ⚠️ 精度过低会损害评测结果。对中规模模型建议保守停在
float16或 8 bit。 - 经验观察:量化对超大模型的性能影响反而较小(可能因为存在信息冗余)。
② 模型并行(model parallelism)
把模型切成小块,分别加载/运行在不同的 GPU 上;因为从不一次性加载完整模型,所以省内存,但可能更慢。两种主要类型:
| 类型 | 切分粒度 | 机制 | 代价 / 特点 |
|---|---|---|---|
| Pipeline parallelism(流水线并行) | 整层(layer)级别 | 按层分派到不同 GPU,层 1 输出是层 2 输入 | GPU 会空转等待,产生所谓 "bubble";把输入拆成更小的 batch 可缓解 bubble;需要 GPU 间传输数据 |
| Tensor parallelism(张量并行) | 矩阵计算级别 | 把矩阵按行/列切开,各 GPU 算完再聚合 | 只要 GPU 都在同一节点就极其高效(避免节点间网络瓶颈),但难以编码 |
- Pipeline parallelism 正被原生加入 PyTorch 的
PiPPy库,也是accelerate底层使用的并行方式。 - Tensor parallelism 在
vllm库中有很好的实现,作者形容其带来 "insane speedups"(惊人的加速)。 - 各类并行(含用于提速的 data parallelism)的最佳参考文档:Transformers 官方并行文档。
③ CPU offloading
- 把部分计算和模型参数挪到 CPU,以降低 GPU 显存占用。
- ⚠️ 比上面任何方法都慢得多——因为要持续在设备之间搬运数据。
- 典型实现:DeepSpeed 的 ZeRO-Offload(在 ZeRO-2 优化之上):优化阶段的梯度、optimizer states、fp32 参数计算放 CPU;GPU 上保留 fp16 参数与前向/反向传播,以"用 CPU 内存 + GPU 算力、最小化通信"为设计目标。
1.3 模型装得下,但还是 OOM
大概率是 context size(上下文长度) 的问题——显存峰值往往由"batch size × 序列长度"决定,模型权重本身反而放得下。作者建议:
- 先用虚拟推理数据(dummy inference data)测试模型是否真的放得下;虚拟数据要使用足够大、能代表你任务的 context size。
- 降低 batch size;如果你开了 auto-batch size search(自动搜索 batch size),考虑关掉——它可能导致意外的 OOM。
- 一般性原则:让样本按 context size 逆序(从大到小)呈现给模型——这样如果 context 太大,会一开始就立刻失败,而不是跑了几小时后才崩。
2 数学能力评测中的 LaTeX 解析问题(MATH & sympy)
📌 新版(2025 Space)更新:新版指南把 LaTeX 解析问题并入「Designing your automatic evaluation」的 Normalization 小节,并推荐使用专门的数学解析库 Math-Verify(替代 sympy 手工解析/字符串比较,见 08-2025-Edition §5)。下方记录的是旧版(sympy)的探索过程与教训,仍有参考价值。
2.1 问题背景
- 解析 LaTeX 非常困难。当评测任务期望模型输出 LaTeX 时(典型如 MATH benchmark,它用 LaTeX 表示数学计算与符号),问题就来了。
- 评测这类任务本应只是"解析并比较 ground truth 与模型输出",但实际上不存在"正确"的 LaTeX 解析方式(sympy 文档自己也这么说)。
2.2 sympy 的局限:0.94 的自洽准确率
lm-evaluation-harness使用sympy(Python 符号数学库)解析 LaTeX 并比较表达式。- 残酷的事实:即使用 ground truth 去解析 ground truth 本身(自己和自己比),
sympy也只有约 0.94 的准确率。 - 原因:
sympy无法解析一部分本身正确的 LaTeX 表达式。 - 这个"用 ground truth 自比"的测试本质是一个解析器健全性检查(round-trip test):它排除了模型因素,单独测量解析管道的上限。0.94 意味着即使模型 100% 输出正确答案,评测系统也会因解析失败丢掉约 6% 的分数——解析器成了评测误差的主要来源之一。
2.3 典型报错示例
以下三个示例中,sympy 都因语法问题拒绝了正确的 LaTeX:
例 1:半开区间 [0,1)(interval)
couldn't parse one of [0,1) or [0,1), I expected one of these: ']'
[0,1)
~~^
例 2:并集 \cup 与无穷 \infty(此处写作 \iny)
couldn't parse one of (-\iny,-5]\cup[5,\iny) or (-\iny,-5]\cup[5,\iny), I expected something else here
(-\iny,-5]\cup[5,\iny)
~~~~~~^
例 3:分数中的空分组 \frac{1}{{}2x}
couldn't parse one of -\frac{1}{{}2x} or -\frac{1}{{}2x}, I don't understand this
-\frac{1}{{}2x}
~~~~~~~~~~~^
小结:把上述失败归纳成三类典型盲区——
| 失败类别 | 报错示例 | 原因 |
|---|---|---|
| 区间表示(interval) | [0,1) |
半开区间 [/) 混用,sympy 期待 ] 之类的闭合符号 |
| 集合运算与特殊符号 | (-\iny,-5]\cup[5,\iny) |
\cup(并集)等集合运算符、\infty(示例中写作 \iny)不被支持 |
| 多余分组 | -\frac{1}{{}2x} |
分子/分母里的空分组 {} 导致语法不识别 |
三类都是合法、正确的 LaTeX,却会被解析器拒绝——这正是"解析器不是标准答案"的实证。
2.4 怎么绕过
两条路:
- 重写 LaTeX grammar:向
sympy的 LaTeX 语法文件latex.lark添加所需特性(为解析器增加新规则)。 - 在代码里加手动检查:为模型输出增加字符串比较等后处理兜底。
作者的选择:在几乎掉进"重写 grammar"这个深坑之后,决定只给代码加上字符串比较(string comparison)检查就足够了——即对 lm-evaluation-harness 打一个修复补丁(见原文附图中的 LM Eval Harness fix)。
为什么选"字符串比较"而不是"重写 grammar"?重写 parser grammar 是个无底洞:LaTeX 语法变体无穷无尽(区间、集合、特殊符号、各种分组写法),每补一个规则都可能引入新冲突,维护成本高。而字符串比较实现简单、可立刻生效——解析失败时退而求其次做规范化后的字符串比对,足以覆盖评测场景中大多数"模型其实答对了"的情况。对评测工程而言,够用、可维护,比理论上完美更重要。
2.5 修复效果:MATH 上旧/新解析器对比
修复后对 MATH benchmark 前 25 个模型的分数(原始解析器 vs 修复后解析器)对比如下(分数列为 0–100;"提升"为两列差值):
| 模型 | 原始 | 修复后 | 提升 | 排名变化 |
|---|---|---|---|---|
| rombodawg/Rombos-LLM-V2.5-Qwen-72b | 47.58 | 50.68 | +3.10 | 1 → 1 |
| MaziyarPanahi/calme-2.2-qwen2-72b | 41.16 | 43.43 | +2.27 | 2 → 2 |
| arcee-ai/Arcee-Nova | 40.48 | 42.90 | +2.42 | 3 → 3 |
| fblgit/TheBeagle-v2beta-32B-MGS | 39.43 | 42.52 | +3.09 | 4 → 4 |
| rombodawg/Rombos-LLM-V2.5-Qwen-32b | 39.12 | 41.99 | +2.87 | 5 → 5 |
| dnhkng/RYS-XLarge | 38.97 | 41.24 | +2.27 | 6 → 6 |
| dfurman/CalmeRys-78B-Orpo-v0.1 | 37.92 | 40.71 | +2.79 | 8 → 7 |
| MaziyarPanahi/calme-2.2-rys-78b | 37.92 | 39.95 | +2.03 | 8 → 9 |
| MaziyarPanahi/calme-2.4-rys-78b | 37.69 | 40.41 | +2.72 | 9 → 8 |
| MaziyarPanahi/calme-2.3-rys-78b | 36.56 | 38.97 | +2.41 | 10 → 10 |
| MaziyarPanahi/calme-2.1-rys-78b | 36.40 | 38.90 | +2.50 | 11 → 11 |
| Qwen/Qwen2.5-72B | 36.10 | 38.67 | +2.57 | 12 → 12 |
| MaziyarPanahi/calme-2.1-qwen2-72b | 36.03 | 38.07 | +2.04 | 13 → 15 |
| Qwen/Qwen2-Math-72B-Instruct | 35.95 | 38.14 | +2.19 | 14 → 14 |
| dfurman/Qwen2-72B-Orpo-v0.1 | 35.42 | 38.14 | +2.72 | 15 → 13 |
| abacusai/Smaug-Qwen2-72B-Instruct | 35.35 | 37.46 | +2.11 | 16 → 19 |
| anthracite-org/magnum-v1-72b | 35.27 | 37.69 | +2.42 | 18 → 16 |
| alpindale/magnum-72b-v1 | 35.27 | 37.69 | +2.42 | 18 → 16 |
| Qwen/Qwen2-72B-Instruct | 35.12 | 37.69 | +2.57 | 19 → 18 |
| dnhkng/RYS-XLarge-base | 34.67 | 37.16 | +2.49 | 20 → 20 |
| Undi95/MG-FinalMix-72B | 33.61 | 36.10 | +2.49 | 22 → 21 |
| abacusai/Dracarys-72B-Instruct | 33.61 | 35.65 | +2.04 | 22 → 22 |
| Qwen/Qwen2.5-32B | 32.85 | 35.50 | +2.65 | 23 → 23 |
| anthracite-org/magnum-v2-72b | 31.65 | 34.06 | +2.41 | 24 → 24 |
| dnhkng/RYS-Huge-bnb-4bit | 31.57 | 33.84 | +2.27 | 25 → 25 |
关键观察:
- 所有模型的分数都提升了约 2–3 分(最低 +2.03,最高 +3.10)——这个量级的差距足以改变一个模型的"好不好"结论,说明解析器(而非模型)曾经拖累了大量分数。
- 排名大体稳定,但个别模型有 ±1~3 位的变化(如 Smaug-Qwen2-72B-Instruct 从 16 掉到 19,Qwen2-72B-Orpo-v0.1 从 15 升到 13)——若按排名做基准对比,解析差异会改变排行榜序。
为什么分数整体平移、排名却会变? 解析器对每个模型的"扣分"并不均匀:模型 A 输出的 LaTeX 恰好多是 sympy 的盲区(区间、集合、多余分组),被多扣;模型 B 的输出风格恰好全被解析,少扣。所以修复解析器后,被多扣的模型分数抬升更多,相对位置就动了。结论:解析器不只是"对所有人一视同仁的常量误差",它还可能掩盖模型之间的真实差距。
引申教训:评测指标管道(metric pipeline)本身也是被测对象的一部分。解析器、normalization、后处理的实现差异会系统性抬高/压低某些模型的分数。
3 可复现性排错(Troubleshooting Reproducibility)
场景:你读了某篇最新技术报告,想在本地复现它的分数,却复现不出来?以下是作者拆解的原因清单。
3.1 不同的代码库(code base)
- 要复现到小数点,第一步是使用与论文完全相同的代码库。
- 通常意味着:用作者提供的评测默认代码,或用参考库中的标准实现——如 Eleuther AI 的
lm_eval、HuggingFace 的lighteval。这两个库是社区事实上的"标准管道":lm_eval(EleutherAI)是使用最广的评测框架,lighteval(HuggingFace)由 Open LLM Leaderboard 团队维护——用它们,等于和其他人共用同一套任务定义与指标实现,这是复现的前提。 - 如果论文没提供评测代码:几乎不可能精确复现,只能放弃精确比对。
- ⭐ 想直观理解不同实现带来的差异,读作者团队写的这篇博客:MMLU 在不同评测实现下的差异——它研究了 MMLU 在
lm_eval、helm与原始作者实现三种版本下的分数差异。 - 背景:正因为如此,HuggingFace 团队才发起 Open LLM Leaderboard,用统一、同质的评测来做模型间的横向比较。
3.2 同一代码库内也容易踩的坑
即使代码库相同,以下细节也容易出错:
① 不同的随机种子(random seed)
- 推理受 seed 影响通常比训练小,但仍可能影响:
- 部分 CUDA 操作(参考 PyTorch 可复现性文档);
- 非 greedy 生成策略下的预测结果;
- 使用 few-shot 时的 prompt 内容(抽样选出哪些示例);
- 某些前处理 / 后处理函数。
- 一个小 seed 差异就可能带来几分之差。
② 同名但实际不同的指标(metric)
指标名相同 ≠ 计算方式相同,例如:
- log likelihood 版
exact match(计算不同候选答案的对数概率) vs 生成式exact match(只把 greedy 生成与参考答案比较)——两者分数完全不同。 - 代码库里不少任务名叫
exact match,实际却是:prefix exact match(只比生成的开头与参考);suffix exact match(反过来,只比结尾);quasi exact match(带 normalization 的 exact match)。
- 结论:不能只靠指标名判断评测做了什么,必须看代码。
③ 不同的 normalization
- 回到上面生成式
exact match的例子:lm_evalv1 中不少任务只叫 generativeexact match,你会以为预测是"原样与参考比较";但看代码会发现预测先经过 normalization(去标点、数字同质化等)再比较——这会大幅改变结果。 lm_evalv2 已把 normalization 的名字写进大多数指标名。- 这是最容易被搞砸的点,尤其对需要大量 normalization / 答案后处理的任务,比如数学评测(需要从模型生成的解释里抽取最终答案再比较)。
3.3 不同的 prompt
prompt 变化有三个来源。
① prompt 本身(格式)
prompt 格式对分数的影响巨大。以多选题为例,仅呈现选项的格式就有多种"语义等价"的变体:
Question: <text of the question>
Choices:
| A. <Choice A> | (A) <Choice A> | <Choice A> |
| B. <Choice B> | (B) <Choice B> | <Choice B> |
| C. <Choice C> | (C) <Choice C> | <Choice C> |
| D. <Choice D> | (D) <Choice D> | <Choice D> |
Answer:
并要求模型预测 A/B/C/D,或直接输出 <Choice A/B/C/D> 的完整文本。
- 这些 prompt 语义等价(内容完全相同),但对同一模型仍可能差好几分:
- 有些任务还会带任务前缀 prompt(如
The following questions are about <topic>),其有无也会影响分数。 - ⭐ 这篇论文还揭示一个副作用:不少模型被训练成"过拟合基准的 prompt 与答案格式",代价是在评测时对其他 prompt 的适应能力下降。
- 实例(Open LLM Leaderboard 2 上的 Llama3.1):这些模型在 MATH-Hard 评测中能预测出正确答案,分数却很低——因为它们过拟合了 GSM8K(另一个数学评测)的 prompt 与答案格式,无法适配 few-shot 中提供的模板。
② system prompt 与 chat template
- Chat 模型通常经过指令/偏好训练(instruction/preference training 或 fine-tuning),这个阶段它们学会了遵循特定模板推理。
- 常见模板要素:
- 每轮对话以system prompt 开头(通常以特定 token 前缀,如
System:),用于给模型高层指令(人设、回答风格等); - 对话轮次给文本加前缀关键词,如
User(提问)与Assistant(回答)。
- 每轮对话以system prompt 开头(通常以特定 token 前缀,如
- 使用 few-shot 时还要决定:示例按多轮(multi-turn,模拟 user/assistant 轮次)提供,还是一次性放在单条 user prompt 里。
- ⚠️ 不遵循模型期望的 chat template,会严重损害性能——因为它把模型输出推向其已收敛的概率空间之外。
③ few-shot 样本
- 显然要用与参考任务相同的 few-shot 数量。
- 还要用完全相同的样本——不同样本会改变结果(这不太意外:有些样本更能表达任务)。
- 更反直觉的一点:样本完全相同还不够,顺序也必须完全相同。作者团队观察到:同样的样本仅改变顺序,在 MMLU 的某些子集上最多差 3 分(结果见这里,第三个 colorgrid)。
- 因此这里同样要注意随机种子。
3.4 不同的生成参数(generation parameters)
对生成式评测,需要对齐:
- 使用相同的 end of sentence token(EOS token);
- 允许模型生成相同数量的 token;
- 如果使用 sampling,确保相同的 seed / temperature 参数。
3.5 不同的模型加载(model loading)
已观察到的差异来源:
| 来源 | 说明 |
|---|---|
| 不同硬件 | PyTorch 不保证非确定性操作在不同硬件上可复现 |
| 不同推理库 | 例如用 transformers 还是 vllm 作为推理后端,矩阵计算的实现方式并不完全相同 |
| 不同 batch size | 多个评测库与模型后端都有文档记录:batch size 不同会改变推理结果;要完全可复现就固定 batch size(虽然内存受限时不一定总能做到) |
| 不同加载精度 | 用更低精度加载权重可省内存与推理成本,但用的是不同版本的权重,数值结果必然改变 |
排查复现问题时的总思路:从"最可能、最容易改"的项开始逐项对齐——先核对 prompt 与 few-shot(改动最频繁、影响最直接),再查指标与 normalization(需要看代码确认),最后核对生成参数与加载方式(涉及硬件环境)。每锁定一项就重跑一次对比,通常很快能找到分差来源。
3.6 可复现性检查清单(速查)
综合 3.1–3.5,复现一份评测分数前逐项核对(任一项不满足,分数就可能对不上):
- 使用与参考完全相同的代码库/评测框架(
lm_eval/lighteval/ 作者实现) - 相同随机种子(尤其非 greedy 生成、few-shot 抽样)
- 相同的指标定义(log-likelihood vs generative、prefix/suffix/quasi exact match,看代码确认)
- 相同的 normalization / 后处理(数学评测尤其注意答案抽取)
- 相同的 prompt 格式、system prompt、chat template(多轮 vs 单次 few-shot)
- 相同的 few-shot 数量、样本与顺序
- 相同的生成参数(EOS token、max tokens、seed / temperature)
- 相同的硬件、推理库、batch size、加载精度
核心要点(一句话版)
- 提速四杠杆(按性价比排序):调大 batch size → 数据并行 → 换更快推理库 → 降精度(
bfloat16/float16→ 8bit/4bit 量化)。 - 内存估算:
memory(GB) = 参数(G) × precision factor × 110%;factor 为float32=4、float16/bfloat16=2、8bit=1、4bit=0.5。 - 放不下时:先量化(最多省 8 倍内存),再模型并行(pipeline 慢在 bubble、tensor 慢在难编码但同节点极快),CPU offloading 是最后手段(显著更慢)。
- 装得下却 OOM:八成是 context size 问题——用大 context 的 dummy 数据先测、降 batch、样本按 context 逆序呈现让失败提前暴露。
- 数学评测的 LaTeX 解析没有标准答案:
lm-evaluation-harness用的sympy连 ground truth 自比都只有约 0.94 准确率;别去重写 grammar,加字符串比较兜底就够(修复后 25 个模型 MATH 分数全部 +2~3 分)。 - 复现不出分数 = 某个环境细节没对齐:代码库、随机种子、指标真实定义(prefix/suffix/quasi exact match)、normalization、prompt 格式与 chat template、few-shot 的数量/样本/顺序(顺序变化最多差 3 分)、生成参数(EOS、max tokens、seed/temperature)、硬件/推理库/batch size/加载精度——每一项都可能差几分。
- 最容易被低估的两处:① 同名指标的实现差异(必须看代码,别信名字);② prompt 格式的微小变化——语义等价也能差 7 分,还有模型专门过拟合基准 prompt 格式,换格式分数暴跌。
- 工具取向:优先使用维护中的标准框架(
lm_evalv2、lighteval),因为它们把 normalization 等细节暴露在指标名里,减少"实现悄悄不同"的踩坑概率;升级框架版本时,也要顺手核对指标定义是否变化。
参考资料
原文(GitHub 仓库)
- Troubleshooting inference(推理排错)
- Using LaTeX to evaluate MATH capabilities(LaTeX 解析)
- Troubleshooting reproducibility(可复现性排错)
- 仓库主页:huggingface/evaluation-guidebook
文中引用的外部链接
- PyTorch 模型推理性能优化清单
- PyTorch PiPPy(pipeline parallelism)
- Transformers 并行化文档(data / pipeline / tensor parallelism)
- ZeRO-Offload 论文(arXiv:2101.06840)
- MATH benchmark(lighteval/MATH)
- sympy(符号数学库)
- sympy 的 LaTeX grammar(latex.lark)
- ⭐ MMLU 在不同评测实现下的差异(HF 博客)
- Open LLM Leaderboard
- PyTorch 可复现性文档
- prompt 格式对分数影响的实验(X 原帖,最高差 7 分)
- Few-shot prompt 变化的影响(论文 arXiv:2310.11324)
- ⭐ 模型过拟合基准 prompt 格式(论文 arXiv:2407.07890)
- few-shot 顺序对 MMLU 子集分数的影响(HF 博客)