
1. 为什么大家开始用 CPU 跑 LLaMA1.1 LLaMA 是什么为什么能上 CPU先说一句很多人的误区LLaMA 虽然名字里带着“大”但它并不是只能在数据中心里靠 A100/H100 才能转起来的大模型。LLaMA 是 Meta 在 2023 年开源的 Transformer 架构大模型系列从 7B、13B、33B 一路到 65B/70B开源社区很快就围绕它搭起了一整套推理工具链。正是这套工具链把“LLaMA 只能跑 GPU”的印象彻底打破了。最关键的一步是 GGUF/GGML 格式的出现。传统 PyTorch 权重用 FP16/BF16 存储单个 7B 模型就要占 14GB 显存CPU 端几乎没法直接碰。后来 llama.cpp 项目把权重重排、分块、量化打成 GGUF7B 模型的 4-bit 版本只有 3.7~4.2GB内存 8GB 以上的普通电脑就有机会完整加载。于是标题里那句“LLaMA Now Goes Faster on CPUs”就变得顺理成章了CPU 推理追求的不是“超过 GPU”而是把硬件门槛拉低到真正的日常级别。从实用角度看现在用 CPU 跑 LLaMA 的典型场景主要有三类。第一类是开发调试工程师在本地先把 Prompt、参数和输出格式调通再决定要不要上 GPU 集群第二类是隐私敏感环境数据不离开本机也不经过第三方接口适合处理内部文档和代码片段第三类是预算受限的临时环境比如云上只开了 8 核 CPU 的虚拟机也能在几分钟内部署一个小型对话模型。这些场景的共同点是性能不追求极致但“能跑、可改、不花钱”的弹性非常重要。所以这篇文章的核心不是让你用 CPU 去挑战 GPU 的算力而是告诉你在 2024 到 2025 年这个时间点CPU 推理在 7B~13B 量级模型上已经进入了“日常可用”区间。只要知道瓶颈在哪、怎么选量化、怎么调参数一台两三千块钱的办公主机就能跑出每秒 5~10 个 token 的速度用来做摘要、写作辅助、代码补全这类轻量任务完全够用。1.2 选 CPU 推理的三个真实理由第一个理由是成本。公司或个人手里往往已经有现成的 CPU 服务器或高配电脑没有必要为跑一次实验立刻买 GPU。GPU 不只硬件贵配套的电源、散热、机箱甚至机房电费都要跟着涨。CPU 推理可以把这些存量资源盘活尤其是 7B 模型这种量级用 CPU 跑的成本几乎可以忽略。第二个理由是隐私与数据安全。本地推理意味着模型权重和输入数据都在自己手里不需要把内容上传给模型托管平台。对于代码片段、发票信息、内部邮件这类数据留在本地方是很多团队的首要需求。llama.cpp 这样的纯本地推理框架天然适合这种场景。第三个理由是环境兼容性好得离谱。x86 的 Windows/Linux 能跑ARM 的树莓派和 Apple Silicon 也能跑甚至在没有 GPU 的老服务器上只要系统内存够大就能部署。兼容性好的另一层意思是你不用再跟 CUDA 版本、显卡驱动、显存占用这些历史包袱纠缠一个可执行文件加一个模型文件所有的事就都齐了。2. 影响 CPU 推理速度的关键因素2.1 内存带宽是真正的天花板如果你想用一句话判断 CPU 跑 LLaMA 快不快这句话就是LLM 生成 token 时每次都要把模型权重完整地从内存里读一遍。这个规律决定了 CPU 推理的天花板不是 CPU 的计算频率而是内存带宽。我解释一下原因。大模型生成是一个 token 一个 token 来的每个 token 的计算过程里神经网络的每一层都要按顺序和全部权重做矩阵运算。即使用了 4-bit 量化权重总量摆在那儿例如 4GB 的量化模型一次 token 生成理论上就要从主存搬运约 4GB 数据。内存带宽越高搬运越快你体验到的生成速度就越快。拿参数来算账会清楚很多。DDR4-3200 双通道内存的理论带宽大约是 51.2GB/s用 4.1GB 的 Q4 模型来跑理论上限约等于 51.2 ÷ 4.1也就是 12.5 token/s。实际还要算上并行开销、缓存命中、内存控制器争用所以能跑到 6~9 token/s 就已经算正常。换句话说如果你看到有人在 8 核 CPU 上用 7B 模型跑出 25 token/s不用怀疑那多半是内存带宽特别高比如 Apple Silicon 的统一内存带宽接近 100GB/s跑 4-bit 7B 才能有这个成绩。这里还要区分两个阶段Prompt 处理阶段主要是矩阵乘多核 CPU 的计算能力更关键生成阶段才是权重扫内存内存带宽成了唯一瓶颈。实际表现是生成时 CPU 占用率反而会下降但风扇依然狂转因为险了很久的内存控制器忙着搬运数据。如果你发现自己的 CPU 有多核却用不满别急着调线程先看看内存是不是跑在双通道上、频率是不是被 BIOS 降到 2133 了。内存带宽这回事情按经验优先级排个序双通道 高频 低延迟。DDR4-2400 升到 DDR4-3600 能带来约 15~20% 的生成提速而你从 6 核换到 8 核 CPU 带来的提升往往还没有这么明显。尤其是在 13B 模型上内存带宽对速度的影响几乎就是生死线。2.2 指令集与线程数不是越多越好除了带宽CPU 的指令集扩展也对 LLaMA 推理速度影响巨大。GGUF 量化格式在 x86 CPU 上需要把 4-bit 权重反量化回浮点数再计算这一步强依赖 SIMD 指令。AVX2 是绝对的分水岭支持 AVX2 的 CPU 跑 Q4_K_M效率比只支持 SSE 的老 CPU 高出几倍而 AVX-512 在部分服务器 CPU 上还能再快一截但因为会触发降频在桌面端反而忽快忽慢。llama.cpp 的官方编译版本会默认启用一些通用优化如果你自己编译一定要用 Release 模式并且带上 native 优化参数。具体做法后文会写。这里想先纠正一个惯性思维不是把线程开到最大就能得到最大速度。生成阶段受带宽限制线程数超过物理核心数以后超线程虚拟核心反而会争抢内存控制器性能甚至会倒退。我自己常用的方法是先取物理核心数比如 8 核 16 线程就设-t 8然后跑一个短采样再试-t 12和-t 16速度哪个高就用哪个。个别 CPU 上 16 线程比 8 线程还慢不用惊讶。Prompt 处理阶段更吃多核这时可以考虑单独调--threads-batch让前处理阶段用更多线程生成阶段保持受限两头都能兼顾。2.3 量化精度选择速度、质量与内存的三方平衡GGUF 家族里量化标记看起来像暗号Q4_0、Q4_K_S、Q4_K_M、Q5_K_M、Q6_K、Q8_0。简单拆解一下Q 后面的数字代表平均每个权重占多少 bit字母后缀代表分类分组的策略。K 系列用了 k-quant 方法对不同张量分配不同 bit 数效果比普通线性量化更好。如果你只想记一个结论那就是7B 量级模型优先选 Q4_K_M。原因有三个内存占用合适速度接近 Q4_0质量明显优于 Q4_0。Q5_K_M 质量更好但文件体积和读取量都涨一档生成速度会回落 10~20%。Q8_0 在 CPU 上除非内存特别富裕否则生成速度下降更明显多数情况下不划算。如果你的内存实在吃紧比如 6GB 内存还想跑 7B 模型可以试着用 Q3_K_M 或 Q2_K但要做好质量明显下降的准备尤其是中文长文本和代码任务很可能出现句式破碎、逻辑不通。遇到这种情况我更建议换一个小一点的模型而不是死守 7B 硬上低比特。量化只能帮你在同一模型里省内存救不了“模型本身太大”的窘境。3. 从零编译 llama.cpp 到成功加载模型3.1 环境准备与源码编译实战要体验 CPU 提速最稳的路线是用 llama.cpp 而不是 Python 推理框架。llama.cpp 是 C/C 实现不用装 PyTorch不依赖 CUDA资源开销小启动速度快并且所有优化都针对 CPU 设计。理论上 Windows、Linux、macOS 都能用我下面的命令以 Linux 和 macOS 为主。先克隆仓库git clone https://github.com/ggerganov/llama.cpp cd llama.cpp然后创建 Release 构建目录并编译cmake -B build -DCMAKE_BUILD_TYPERelease cmake --build build --config Release -j 8-j 8是编译并行度根据你的 CPU 核心数调整比如 16 核就-j 16。在 Linux 下编译完成后可执行文件会集中放到build/bin常见的几个分别是llama-cli、llama-server、llama-quantize、llama-bench。Windows 下建议安装 Visual Studio 的 C 生成工具然后打开“x64 Native Tools Command Prompt”进入 llama.cpp 目录再执行相同命令。需要注意的是编译路径不要带中文和空格否则 CMake 配置阶段可能报一些莫名其妙的错误。编译时如果你确认 CPU 是近几年的 x86 型号可以加一个-DGGML_NATIVEON 让编译器针对本机指令集自动优化速度通常能再提升几个百分点。但这样做出来的可执行文件不能随意拷贝到别的电脑上否则可能直接触发非法指令崩溃。3.2 拿到 GGUF 模型文件的三种方式第一种方式是直接从 Hugging Face 下载别人转好的 GGUF 文件。以常见的 Qwen2.5-7B-Instruct 为例huggingface-cli download Qwen/Qwen2.5-7B-Instruct-GGUF qwen2.5-7b-instruct-q4_k_m.gguf --local-dir ./model如果没有安装 Hugging Face CLI也可以翻到模型页面找到下载链接用 wget 或 curl 直接拉wget https://huggingface.co/Qwen/Qwen2.5-7B-Instruct-GGUF/resolve/main/qwen2.5-7b-instruct-q4_k_m.gguf第二种方式是“自己动手转换”。如果你手上只有一个 PyTorch 格式的 HF 权重目录可用 llama.cpp 自带的转换脚本先转 GGUF FP16再量化python convert_hf_to_gguf.py ./qwen2.5-7b-instruct --outfile ./qwen2.5-7b-f16.gguf ./build/bin/llama-quantize ./qwen2.5-7b-f16.gguf ./qwen2.5-7b-q4_k_m.gguf q4_k_m这个流程的好处是你能亲眼看到“从原始权重到量化模型”的完整变化也方便自己拿不同量化等级做对比。转换时记得把convert_hf_to_gguf.py换成仓库当前路径下的实际位置转换脚本可能需要安装ggufPython 包缺了就顺手 pip 装一下。第三种方式是官方或第三方已经提供完整 GGUF 目录的镜像站点。无论是哪种方式核心原则是确保 GGUF 文件与模型架构、聊天模板匹配。llama-cli 在加载时一般能自动识别模板但如果你下载的是一个裸的基座模型而不是指令模型生成内容大概率是在续写而不是对话别怀疑是程序坏了。3.3 核心运行参数逐个说llama.cpp 最基础的运行命令长这样./build/bin/llama-cli \ -m ./model/qwen2.5-7b-instruct-q4_k_m.gguf \ -p 用一句中文解释什么是CPU推理 \ -t 8 \ -c 4096 \ -n 512 \ --mlock \ --temp 0.7 \ --repeat-penalty 1.15逐项解释。-m指定模型路径-p是输入提示词-t是线程数先按物理核心数来-c是上下文长度普通任务 4096 足够开得越大 KV cache 占用越多-n是生成 token 数的上限--mlock把已加载模型锁在物理内存里防止系统把内存页换到磁盘造成掉速--temp和--repeat-penalty是采样参数前者控制随机性后者压制重复病句。如果只想做普通的单轮生成上面的命令就够了。想要交互式对话加参数-i -cnv进入多轮聊天模式这样每次输入用户消息模型都会参考前文继续回复./build/bin/llama-cli -m ./model/qwen2.5-7b-instruct-q4_k_m.gguf -t 8 -c 4096 -i -cnv交互模式下按CtrlC退出注意不同版本的按键定义略有区别。我这里特别提示一句第一次运行看到“llama_new_context_with_model: n_ctx 4096”这样的日志不要慌张它只是在告诉你上下文配置好了。接下来最要紧的是观察两行信息一行是“llama_model_load: model size”告诉你实际加载的模型体积另一行是“load time”如果加载耗时超过几十秒说明磁盘或内存可能有问题也可能是--mlock参数没生效。4. 实际跑分与调优思路4.1 不同硬件环境下取得的实测速度我把自己在几类硬件上跑 7B/8B 量化模型的实际数据整理成一个表供你对照参考。这里的数值都是在 llama.cpp 默认 Release 编译、量化等级 Q4_K_M、上下文 4096 的条件下得到的近似结果不代表某一颗 CPU 的绝对极限。CPU/设备内存配置模型生成速度token/s备注AMD Ryzen 5 5600XDDR4-3600 双通道Qwen2.5-7B Q4_K_M8~10生成阶段线程并没有吃满Apple M2Mac mini16GB 统一内存Llama-3-8B Q4_K_M25~30内存带宽优势明显双路 Xeon E5-2678 v3DDR4-2133 八通道Llama2-13B Q4_K_M6~8老服务器NUMA 影响较大Intel i5-4460DDR3-1600 双通道7B Q4_K_M3~4无 AVX2体感非常慢从表里能看出决定生成速度的第一要素是内存带宽而不是 CPU 品牌或核心数。Ryzen 5 5600X 的单核性能不差但它受限于双通道 DDR4 带宽最终只能跑到每秒 8~10 token。Apple M2 的强项在于统一内存带宽非常宽等效带宽接近 100GB/s所以即便核心数量不多token 生成速度也能比传统 x86 平台高出三倍。老平台的问题则更明显。i5-4460 那台机器不仅内存带宽低而且还缺少 AVX2 指令集跑 4-bit 量化模型时反量化速度严重拖后腿体感从模型开始输出到第一个字出来都要等好几秒。如果你手里的 CPU 是 2015 年以前的入门级型号建议先确认有没有 AVX2没有的话优化空间会非常有限。4.2 调整线程与批处理的优先级当你面对一台完全未知的机器调整顺序应该按作用大小来。先把量化模型换好这是基准再确认内存是不是双通道、频率有没有被锁然后才去试线程数和批处理大小而不是盲目堆参数。线程数的测试方法很简单用同一段 prompt 分别跑-t 4、-t 6、-t 8、-t 12记录每个配置下的生成 token/s。我实测的经验是生成速度的差异通常只在 10% 以内极端情况下还会出现线程越多越慢的情况。Prompt 处理速度则明显受线程数影响这时你需要调整--threads-batch参数让它高于-t比如生成用 8 线程批处理用 16 线程。批处理大小对应的参数是-b和-ub比如你可以加-b 512 -ub 512。批处理越大模型在 prompt 阶段一次扫描的 token 数越多前处理时间越短但同时会临时占用更多内存并提高延迟峰值的波动脉动。我的建议是只有在 Prompt 明显很长或首 token 延迟不能接受时才把-b从默认值提高到 512 或 1024日常短 Prompt 用默认值就足够。4.3 KV Cache 对内存的压力很多人只算模型文件大小却忘了上下文本身也要吃内存。KV Cache 存的是模型在推理过程中为每个 token 保留的键值向量长度越大缓存越大。公式大约是这样KV 缓存字节数 ≈ 层数 × KV 头数 × 头维度 × 上下文长度 × 2K 和 V 两组× 2FP16 需要 2 字节。以 Llama-3-8B 为例它大约有 32 层、8 个 KV 头、每个头维度 128如果上下文设为 8192KV 缓存会占到大约 1GB。如果你同时加载了一个 5GB 的量化模型内存总量很容易冲到 7GB 以上。这也是为什么运行时要根据实际内存来设-c而不是随手开到 32768。关掉不需要的长上下文能省下的内存远比换一个更小的量化模型要现实。如果你的 llama.cpp 版本支持 Flash Attention记得加-fa 1。FA 会重新计算部分注意力矩阵而不是全程缓存长上下文下既能降低 KV 缓存占用又有机会减少部分计算量。对于 7B 模型来说短上下文下提升不明显但 8192 以上时值得一试。5. 常见问题与避坑记录5.1 高频报错与解决方案速查我在实践和帮朋友排查时遇到的报错九成都能归到下面这张表里。现象原因解决方案Illegal instruction (core dumped)可执行文件用了当前 CPU 不支持的指令集比如在没 AVX2 的机器上跑了带 AVX2 的二进制源码重新编译不拷贝别人的可执行文件检查 BIOS 是否关闭了相关指令扩展failed to allocate memory模型加 KV Cache 总需求大于可用内存调小-c或-b换 Q3/Q4 量化关闭其他内存大户生成速度极慢甚至不到 1 token/s没有 AVX2 指令集或线程设置过多优先确认指令集其次降低线程数最后换更小量化加载模型后系统开始疯狂 swap--mlock没生效或内存不足确认物理内存足够用free -h检查剩余空间输出是乱码或中英文混杂终端编码或聊天模板不匹配在 UTF-8 终端下运行换 prompt 模板或重新转换模型双路服务器提速不明显NUMA 跨节点访问导致远端内存延迟高用taskset/numactl绑定 CPU 和内存节点尽量一个模型跑在一个 NUMA 域内如果你的问题没有列在里面先跑一行带--verbose的命令把加载信息完整看一遍。llama.cpp 启动时会把模型超参数、上下文大小、内存占用都打印出来大部分答案就在日志里。报错解决不了时别急着怀疑代码先重新下载一个干净模型文件很多莫名其妙的崩溃都是文件损坏或是不完整下载导致的。5.2 我这几条独家经验踩过不少坑第一不要一上来就追求大模型。在 CPU 上13B 比 7B 更吃内存带宽速度会掉到 7B 的三分之二左右。如果你只有 16GB 内存我建议老老实实跑 7B/8B 模型把速度做稳之后再考虑更大参数量的模型。第二线程数设置请务必实测。同一颗 CPU 在-t 8和-t 16之间可能只有 5% 差距但在老款超线程 CPU 上成绩很可能开倒车。别相信别人说的“16 线程一定比 8 线程快”内存带宽才是老大。第三检查内存频率非常值钱。很多人主板上明明插着 3200MHz 的内存却因为忘了开 XMP 或 BIOS 里默认 2133MHz白白损失 20% 带宽。你在 BIOS 里把内存频率调上去之后再跑一次llama-bench看数字变化往往会惊掉下巴。第四启动时加--mlock但不一定加--no-mmap。--mlock避免换页--no-mmap则是让模型一次性完整读入内存。虚拟内存比较混乱的环境里我可以保底使用但如果内存紧张--no-mmap会导致加载失败所以只在确有必要时打开它。5.3 如何判断自己的 CPU 该选哪种量化先用固定命令跑一个基准测试比如./build/bin/llama-bench -m ./model/q4_k_m.gguf -t 8llama-bench 会分别给出 Prompt 处理速度和生成速度它比手动掐秒表靠谱得多。然后在同一台机器上换另一个量化文件比如 Q5_K_M 和 Q8_0分别跑一遍对比生成速度。如果 Q8_0 比 Q4_K_M 慢 25% 以上说明你的内存带宽已经到瓶颈继续增大量化位宽带来的质量提升根本不划算。选量化的黄金法则可以概括成一句话内存装得下、速度可接受时挑你情感上能接受的质量档位。7B 模型上我更推荐 Q4_K_M 做日常主力Q5_K_M 做质量敏感任务Q8_0 只在内存实在宽裕时才考虑。请记住CPU 推理追求的是“综合可用”而不是单一指标上的极致。6. 从“能跑”到“好用”的几点体会最近这半年我在本地 CPU 上跑 LLaMA 的次数越来越多甚至有些正式原型验证工具也直接用 llama.cpp 当后端。最让我意外的不是模型能跑起来——这是早就可以做到的事而是当我把内存带宽、量化粒度、线程调度这些因素理解清楚之后一台普通机器的推理速度居然还能再压出近一倍的差距。有一次我在一台 8 核 16 线程的台式机上跑 Qwen2.5-7B一开始生成速度只有 5 token/s可把我烦得不行。仔细排查后发现两个问题一是内存跑在 2133MHz二是线程数设成了 16。把内存频率调到 3600MHz、线程改回 8再重新编译带 native 优化参数的 llama.cpp生成速度硬生生提到了 10 token/s。这个过程看起来不起眼但工程实践中“顺畅可用”和“勉强能跑”往往就差这几步调整。如果你也想在自己的机器上复现整套流程我建议从 7B 模型加 Q4_K_M 开始先把一条命令跑通再逐步尝试不同线程数和内存配置。量化和推理框架的发展速度很快说不定过几个月 CPU 上的 token 速度又会被刷新一遍但内存带宽、指令集和量化选择这些底层逻辑不会变。把底层逻辑吃透以后无论换模型还是换框架你都能快速判断什么改动真正值得做什么只是表面繁荣。