教程·阅读约 3 分钟·
在 13 年前的 Xeon 服务器上跑 Gemma 4 26B:一份实操指南

在 13 年前的 Xeon 服务器上跑 Gemma 4 26B:一份实操指南

用不到 300 美元的老旧服务器跑谷歌 Gemma 4 26B 大模型,详细记录从硬件选型、编译修复到性能调优的全过程

原文来源:Neomind Labs Blog — 详细记录如何在一台 13 年前的双路 Xeon 服务器上(无 GPU,总价不到 300 美元)用 AVX1 指令集跑 Gemma 4 26B,解码速度约 5.2 token/s

这件事为什么值得一做

现在大家都在讨论 GPU 集群、云端推理、A100/H100 这些高端方案。但你有没有想过:如果 API 服务挂了怎么办?如果预算有限但又想跑本地模型怎么办?或者你手头正好有一台落满灰的老服务器,能不能把它变成一台 AI 推理机?

这篇文章给了你一个明确的答案:能,而且花费不到 300 美元。

Neomind Labs 的作者用一台 2013 年的 HP StoreVirtual 服务器(双路 Xeon E5-2690 v2,Ivy Bridge 架构,DDR3 内存,没有 GPU),成功跑起了谷歌最新发布的 Gemma 4 26B 模型(Mixture-of-Experts 架构),解码速度达到约 5.2 token/s,提示词处理约 16 token/s。

这个速度够用吗?看场景。做实时聊天不够,但做批量处理、后台任务、或者实验性项目,完全够了。更重要的是,这个案例告诉我们:当你在「足够老的硬件」和「足够新的模型」之间架起桥梁时,中间需要的不是钱,而是解决问题的耐心和正确的方法。

—— 广告 ——

硬件准备:什么样的旧机器能跑

先说说硬件基线。作者用的是 HP StoreVirtual,双路 Xeon E5-2690 v2,这是 Ivy Bridge 架构(2013 年发布),指令集支持到 AVX1 为止。没有 AVX2,没有 FMA3。

关键参数:

  • CPU:双路 Xeon E5-2690 v2(共 20 核 40 线程)
  • 内存:DDR3(具体容量作者没提,但跑 26B 模型 Q8_0 量化需要约 26-30GB)
  • GPU:无
  • 总成本:不到 300 美元(二手服务器价格)

注意:你的机器不需要和作者一模一样,但有几个关键点要满足:

  • 至少支持 AVX 指令集(2008 年后的 CPU 基本都有)
  • 有足够的 RAM 加载模型(26B 模型 Q8_0 量化需要约 28GB)
  • 最好是双路或多核配置,因为 CPU 推理是内存带宽瓶颈,多通道内存有帮助

软件栈:为什么普通的 llama.cpp 不行

乍看之下,跑 Gemma 4 只需要下载 llama.cpp 或者它的优化分支 ik_llama.cpp,编译,然后跑就行了。但作者在这里踩了一个大坑。

ik_llama.cpp 是一个高度优化的分支,支持推测解码(speculative decoding)、CPU 上的 MoE 路由、flash attention 等特性。但问题在于:ik_llama.cpp 的优化代码默认是为 AVX2/FMA3 设计的,而老的 Ivy Bridge CPU 只有 AVX1。

作者第一次编译后,模型确实跑起来了——但输出的是「看起来流畅的多语言乱码」。具体表现是:输出是确定性的(每次输入同样的内容,输出都一样),没有 NaN,但 token 分布均匀地散落在 262K 词汇表的各个位置。

从表面上看,一切似乎正常。但为什么输出是乱码?

调试过程:AI 帮我找到的 Bug

这就是这篇文章最有价值的部分——作者不是直接修代码,而是让 AI(Claude)来诊断问题

找到问题的第一步是观察 logits。正常推理时,模型输出的 logits 应该是一个稀疏分布:少数 token 的 logit 值较高,大多数 token 的 logit 值接近负无穷或非常低。但作者发现:

  • 平均 logit 值约为 +16(正常应该接近 0)
  • 大约 80% 的词汇表位置 logit 为正数
  • 这是典型的未初始化内存被使用的迹象

这意味着模型在推理过程中,有一部分计算实际上没有执行——而是在读内存中的随机垃圾数据。

根本原因:两个「消失」的算子

经过深入追查,问题的根源找到了:代码的图构建器(graph builder)无条件地发射了两个算子——MOE_FUSED_UP_GATE(每个专家的 gate+up 矩阵乘法融合了 SwiGLU)和 FUSED_UP_GATE(密集版本)——但计算分发器(compute dispatcher)在 GGML_USE_IQK_MULMAT 关闭时,没有处理这两个算子的逻辑分支

结果就是,每次前向传播都要消耗 30 层 × 8 个激活专家 = 240 个张量的未初始化内存

这里的关键教训是:AI 模型的「看起来能跑」和「真正正确地跑」是两回事。 如果作者只看生成结果的表面(格式整洁、语言流畅),他可能永远不会发现这个 bug。正是因为他检查了原始 logits,才找到了问题。

修复方案

修复分三个 commits,都在 ik_llama.cpp 的 PR #2138 中:

1. 编译修复:

  • iqk_quantize.cpp 中 AVX2 专用路径的标量 fallback 分支仍然引用了 AVX2 内联函数,替换为可移植的标量循环
  • ggml.cggml-quants.c 中添加 #if GGML_USE_IQK_MULMAT 守卫
  • iqk_cpu_ops.cpp 添加缺失的 include

2. 运行时修复:GGML_USE_IQK_MULMAT 关闭时,对 up_gate_exps 组合张量做如下处理:

  • 拆分为两个 ggml_view_3d 切片
  • 分别执行 ggml_mul_mat_id 调用
  • ggml_fused_mul_unary(gate, up, SILU) 合并

这个修复带来的性能损失可以忽略不计——因为 CPU 推理的瓶颈是内存带宽,融合算子的优势只在 AVX2 上才能体现。在 AVX1 上,分开计算和融合计算的差别基本没有。

3. CI 修复: 修复了缺失的 <cstdint> 头文件、不匹配的函数签名、以及非 AVX2 构建中的 undefined reference 问题。

另一个陷阱:--run-time-repack 参数

还有一个重要的坑点:--run-time-repack 参数。这个参数的作用是将量化权重重新排列成 AVX2 专用的交错布局(Q8_0_R8)。在 AVX1 机器上使用这个参数会导致输出乱码。在预 AVX2 的 CPU 上运行时,必须省略 --run-time-repack

实操步骤总结

如果你的旧服务器满足硬件要求,以下是完整操作流程:

code
# 1. 克隆 ik_llama.cpp 并切换到 PR 分支
git clone https://github.com/ikawrakow/ik_llama.cpp.git
cd ik_llama.cpp
git fetch origin pull/2138/head:fix-avx1
git checkout fix-avx1
 
# 2. 编译(关闭 IQK_MULMAT)
mkdir build && cd build
cmake .. -DGGML_USE_IQK_MULMAT=OFF
make -j$(nproc)
 
# 3. 下载 Gemma 4 26B Q8_0 量化模型
# (从 HuggingFace 或其他模型仓库下载)
 
# 4. 运行(注意不要加 --run-time-repack)
./llama-cli \
  -m /path/to/gemma-4-26b-q8_0.gguf \
  -p "你的提示词" \
  -n 256 \
  -t 8

性能预期

在双路 Xeon E5-2690 v2 上,作者的实测数据:

  • 解码速度:约 5.2 token/s
  • 提示词处理:约 16 token/s

作为对比,一台中等配置的 GPU 机器可以跑到 50+ token/s。但考虑这台机器的成本不到 300 美元,而一块 RTX 4090 要 1600 美元,这个速度其实是相当划算的。

这件事的深层价值

这篇文章最让我触动的一点是作者的观点:「用好 AI」不应该等于「买得起订阅」。真正的好手是那些愿意打开引擎盖、阅读陌生人的代码、不断追问,直到一台 13 年前的 CPU 完成它从未被设计来完成的任务的人。

这个修补让任何拥有老旧企业级硬件的人都能运行现代本地模型——无论云端 API 是否可用,无论预算是否充裕。对于批量处理、后台任务、原型验证这类场景,这种低成本方案有很高的实用价值。

如果你手头正好有一台闲置的旧服务器,不妨试试这个方案。300 美元换一台本地推理机,也许是你今年最值得的实验项目。

参考链接

分享到
微博Twitter

© 2026 四月

原文链接:https://www.aprilzz.com/tutorials/running-gemma-4-on-old-xeon