我这周把公司一台闲置的 Mac Studio(M1 Ultra, 128GB)和一台 ThinkPad P1 Gen 5(i7-12800H, 64GB)翻了出来,专门测 Ollama 跑 DeepSeek-R1 蒸馏模型的本地推理速度。
原因是上个月我们团队在云端跑 DeepSeek-R1(671B 满血版)时,账单飙到了 4800 元,包含 API 调用和按小时计费的 GPU 实例。肉疼。
血泪教训
云端按量付费看着便宜,一天 200 次请求,一个月下来够买半张消费级显卡。所以我们决定试试蒸馏模型能不能扛住日常的代码生成和文档总结。
为什么选蒸馏模型而非原版
DeepSeek-R1 有 671B 参数,FP16 权重就要 1.3TB 显存。单卡 A100 80GB 得插 17 张才放得下,没 100 万预算别想这事。
蒸馏版 R1-Distill 有 1.5B/7B/8B/14B/32B/70B 六个规格。我们用 Ollama 拉模型时发现 7B 和 8B 是 Qwen 基座,14B 和 32B 是 Qwen2.5 基座,70B 是 Llama 3.1 基座。
选择逻辑很直接:14B 以下跑代码太吃力,70B 在 ThinkPad 上会爆内存,所以主力测 14B 和 32B。
- 32B Q4_K_M 量化包是 20GB,Mac Studio 的 128GB 内存轻松扛
- 14B Q4_K_M 量化包是 9GB,ThinkPad 的 64GB 也能跑
- 8B 留给 CPU-only 模式做对照组
我们团队其实还测过 Ollama 的 qwen2.5-coder:14b,但不是 R1 蒸馏版,结果放在最后对比。
实测环境与参数
Day 1 晚上先做了基础环境校准。
| 设备 | 处理器 | 内存 | Ollama 版本 | 量化格式 |
|---|---|---|---|---|
| Mac Studio | M1 Ultra (48核 GPU) | 128GB 统一内存 | v0.9.6 | Q4_K_M |
| ThinkPad P1 | i7-12800H (6核 12线程) | 64GB DDR4 | v0.9.6 | Q4_K_M |
| Mac mini | M1 (8核 GPU) | 16GB 统一内存 | v0.9.6 | Q8_0 |
每个设备测 3 组任务:代码补全(生成一个 React Hook)、文档总结(压缩 5000 字英文文档)、数学推理(鸡兔同笼变体)。
测速工具用 ollama run 自带的 --verbose 输出 tokens/s。每个任务跑 5 次取中位数,避免冷启动影响。
Day 2 上午发现一个诡异现象:Mac Studio 跑 14B 模型时,第一次调用花了 23 秒才出第一个 token,后续调用只要 300ms。热缓存效应太明显,所以后面全部热身 1 次再计时。
三个真实踩坑
坑 1:Ollama 默认只吃一半 CPU
ThinkPad 上跑 14B Q4_K_M,第一次测试只有 2.3 tokens/s,慢到怀疑人生。
检查 top 发现 Ollama 进程只用了 6 个线程中的 3 个。查了 GitHub 才知道,Ollama 的 num_thread 默认值是物理核心数的一半,Intel 处理器有超线程所以变成 6/2=3。
解法是写 OLLAMA_NUM_THREADS=12 环境变量重启服务。
改完直接翻倍:2.3 -> 4.8 tokens/s。但 CPU 温度从 71°C 飙到 89°C,ThinkPad 风扇起飞。
说实话,这个默认值设计得莫名其妙。既然物理核心有 6 个,凭什么只跑一半线程?又不是怕功耗墙。
坑 2:量化格式不同,速度差 2.7 倍
测试中途我们想把 Mac Studio 的模型从 Q4_K_M 换成 Q8_0 看精度差异。
结果 Q8_0 的 14B 模型跑代码补全只有 6.1 tokens/s,Q4_K_M 是 16.8 tokens/s。
原因是 M1 Ultra 的内存带宽是 800GB/s,但 Q8_0 的权重是 Q4_K_M 的两倍,每次前向传播要多读 9GB 数据。带宽成了瓶颈。
最后换回 Q4_K_M。精度损失在代码生成任务上其实不明显——两次生成同一个 React Hook,逻辑完全一致,只是变量命名略有不同。
回头看,这不算坑,是量化模型的基本物理规律。不过新手很容易忽略模型下载页面上 Q4_K_M 和 Q8_0 的标注差异。
坑 3:32B 模型在 16GB 内存的 Mac mini 上直接 OOM
第 2 周我们想验证低配设备的极限,拿 Mac mini 跑 32B Q4_K_M。
ollama run deepseek-r1:32b 命令刚敲下,3 秒后直接报错 failed to allocate memory。
系统监视器显示 16GB 内存吃满 21GB(含 swap)。Ollama 不会自动换回小模型,必须手动删除模型文件再拉取新模型。
解法:卸载 32B,改用 8B Q8_0,内存占用 7.8GB,能跑,但生成速度只有 3.2 tokens/s,实际不可用。
说实话,16GB 内存的机器别碰 14B 以上的模型。 就算勉强塞进去,swap 导致的延迟会让人崩溃。
速度实测数据与对比
测试总耗时 3 天半,有效数据点 45 个。取每设备每任务的最佳成绩:
- Mac Studio + R1 14B Q4:代码补全 16.8 tok/s,文档总结 14.2 tok/s
- Mac Studio + R1 32B Q4:代码补全 9.1 tok/s,文档总结 7.8 tok/s
- ThinkPad + R1 14B Q4:代码补全 4.8 tok/s,文档总结 4.1 tok/s
- Mac mini + R1 8B Q8:代码补全 5.6 tok/s,文档总结 4.9 tok/s
对比组:qwen2.5-coder 14B 在 Mac Studio 上跑代码补全 12.3 tok/s,数学推理反而只有 6.1 tok/s(R1 蒸馏版 14B 数学推理能到 10.9 tok/s)。
| 模型 | 设备 | 代码补全 (tok/s) | 文档总结 (tok/s) | 数学推理 (tok/s) |
|---|---|---|---|---|
| R1-14B Q4 | Mac Studio | 16.8 | 14.2 | 10.9 |
| R1-32B Q4 | Mac Studio | 9.1 | 7.8 | 6.7 |
| R1-14B Q4 | ThinkPad | 4.8 | 4.1 | 3.5 |
| R1-8B Q8 | Mac mini | 5.6 | 4.9 | 4.2 |
| qwen2.5-coder 14B | Mac Studio | 12.3 | 8.9 | 6.1 |
人机交互的临界点是每秒 8 tokens,低于这个值,等输出的时候会不自觉走神。 只有 Mac Studio 上的 14B 和 32B 超过这条线。
实际使用感受与建议
上个月我们用 14B 模型跑了一批真实工作任务,包括从一个内网项目里提取 API 文档(320 行 Markdown),以及为 5 个遗留 Python 脚本补注释。
- 14B 模型生成的注释质量能接受,但偶尔出现幻觉——它会把不存在的参数写进 docstring
- 代码补全在 90% 场景下够用,但遇到需要跨文件引用上下文时,14B 明显不如 32B 准确
- 数学推理能力出人意料,鸡兔同笼变体题解对了,但中间步骤跳了两行
我们团队最终把 32B 模型作为 Mac Studio 的常驻模型,14B 留给 ThinkPad 出差用。
个人看法:Ollama 的定位是本地快速实验工具,不是生产环境。 如果你需要每秒 40 tokens 的流式响应,乖乖用云端 API。本地跑蒸馏模型的价值在于零延迟、离线可用、数据不出内网。
不过呢,14B 蒸馏模型在 Mac Studio 上 16.8 tok/s 的速度已经超过了我们预期。比之前测过 llama3.1:8b 的 11.2 tok/s 快了一截,DeepSeek 这波蒸馏质量确实在线。
温度与功耗的附加发现
Mac Studio 跑 32B 连续推理 30 分钟,功耗稳定在 45-50W,风扇转速 1500rpm(基本听不见)。ThinkPad 跑 14B 时功耗冲到 72W,风扇声音像吹风机。
如果你要在笔记本上跑模型,优先选 Apple Silicon 或带良好散热的游戏本。办公本别抱幻想。
结论与局限
R1-Distill 14B Q4 在 Apple Silicon 上是目前性价比最高的本地代码助手组合。M1 Ultra 跑 16.8 tok/s、零 API 成本、数据不出内网,这套组合拳打下来,云端 API 在我司内部已经快失宠了。 但如果你用 16GB 内存的机器,还是老实回到 8B 模型或者直接用云端 API。
但我也要承认 R1 蒸馏版不如原版 DeepSeek-R1 的地方有两点:一是推理链长度明显缩短——蒸馏版给的解释只有原版的 40% 左右,遇到复杂逻辑题容易跳步;二是对提示词敏感度更高,原版能理解模糊指令,蒸馏版如果指令不清就直接跑偏。
至于 70B 蒸馏版,因为 ThinkPad 内存不够 32GB 都上不去,所以本文没测。如果后续我们拿到 64GB 以上的 Intel Mac,再补数据。
Day 5 早晨最后测试时,Ollama 刚更新到 v0.5.4,我们没重测——版本变动太快,追不上了。建议你部署时先跑一次本文的基准任务,再按自己的硬件微调参数。
你们的 14B 模型在 CPU 上跑到过多少 tokens/s?