两年前我还在为云端API账单头疼,每个月跑些分类、摘要、RAG调用,轻轻松松烧掉几百块,数据还要往别人的服务器过一遍。后来我把主力推理搬到了这台32G的Mac mini M6上,状态彻底变了:大部分任务本地跑,只有真正复杂的生成才会上云。这篇文不打算复述官网参数,也不会拿"行业平均TPS"来糊弄人。我会把三个核心问题讲透:32G统一内存下算力到底能撑起多大规模的模型、真实TPS怎么测怎么读、以及端云决策的边界应该画在哪。测试引擎以Ollama、llama.cpp和MLX为主,模型以Qwen、Llama系列GGUF量化版为主,数据全部来自我自己实测,适合正在犹豫要不要本地部署大模型、或准备做企业私有化部署方案的读者参考。
1. 为什么是Mac mini M6:统一内存的算力底层逻辑
1.1 衡量LLM算力的三个真指标
很多新手挑机器时,第一眼看的是"几个核心""几级缓存""显卡多少TFLOPS",这些在游戏领域有参考价值,但在跑大模型时真的没那么关键。大模型推理,尤其是一次只推一个请求的场景,真正的瓶颈几乎都落在三个东西上:内存带宽、统一内存容量、KV Cache的腾挪空间。
M系列芯片有个标志性设计——统一内存。CPU、GPU、神经网络引擎共享同一块物理内存,数据不需要通过PCIe总线来回拷贝,这跟传统PC上"显存和系统内存割裂"的思路完全不同。带来的直接好处是:你可以用非常高的吞吐访问模型权重,跑一个7B或14B模型时,不需要操心权重在哪里、拷贝出去多少,GPU核心直接访问就好。
第一个硬指标是内存带宽。LLM推理的decode阶段,本质上是把模型参数从内存里搬到计算单元做矩阵乘,参数搬运速度直接制约生成速度。粗略估算一个数:假设一个模型量化后是5GB权重,内存带宽如果是150GB/s,那理论上最高也就30 token/s左右,因为每生成一个token,都要把全部权重过一遍。所以不要被GPU核心数量洗脑,带宽上不去,核心再多也得排队等权重。
第二个硬指标是统一内存总容量。M6的32G版本,听起来比很多人的PC内存还小,但你要知道这32G是CPU和GPU共享的,NE引擎也不额外占独立显存。跑模型时,权重、KV Cache、嵌入层、中间激活值全要从这里面分。实际操作中,模型权重占用最好控制在25GB之内,剩下的要给系统和推理框架留余地。
第三个指标经常被忽略——神经引擎。苹果的ANE在视频处理和部分小型Transformer模型上有奇效,但主流LLM推理主要吃GPU Metal pipeline,ANE能参与的部分很有限。换句话说,别指望神经引擎帮你把7B模型跑出火箭速度,真正决定体验的还是Metal GPU和内存带宽。
1.2 32G到底能装下哪些模型:量化与体积对照
拿一个大致的清单来看,32G统一内存适合什么规模:
| 模型规模 | 常见格式 | 权重占用 | 32G能否流畅运行 | 备注 |
|---|---|---|---|---|
| 7B-8B | FP16 | 14-16GB | 可以运行,但KV Cache空间紧张 | 建议Q4/Q8量化 |
| 7B-8B | Q4_K_M | 4.5-5GB | 非常流畅 | 日常助手首选 |
| 14B-16B | Q4_K_M | 8-9.5GB | 流畅 | 质量与速度的甜点区 |
| 32B | Q4_K_M | 19-21GB | 可运行,需控制上下文长度 | 峰值内存接近上限 |
| 70B | Q4_K_M | 约40GB | 无法直接运行 | 只能靠低量化或投机采样降档 |
| 7B多模态VL | Q4_K_M | 5-7GB | 流畅 | 适合图文理解 |
这个表是我长期实际操作下来的经验值。注意,就算32B Q4权重只有20GB,你在跑长文档时,KV Cache还会吃掉几个GB,加上操作系统和其他应用,32G内存很容易出现交换。换句话说,32G并不是"32G都能给模型",真正能自由支配的通常只有24-27G。
1.3 为什么GPU核心数不能直接推算TPS
有个反直觉的结论:在Mac上跑LLM,GPU核心数量对decode阶段的影响远小于内存带宽。原因在于decode是"访存密集型"而非"计算密集型"。每生成一个token,需要读取模型所有权重做矩阵乘,此时计算单元大部分时间是空闲的,卡在等待权重从内存到达。
这也是为什么同样一个7B模型,你放在M6的入门款和高配版上,核心数差了一截,但token生成速度差距未必有那么大,真正拉开差距的是内存总线位宽和频率。Mac mini M6不同档位之间的内存带宽差异不小,入门款可能在100-150GB/s附近,高配能到300GB/s以上。所以选机器时,预算有限的情况下,我宁愿选择内存带宽更高的版本,也不要只看GPU核心数。
2. 实测TPS:如何测出真实数据,而不是被虚高指标耽误
2.1 把TPS拆开看:prefill、decode与TTFT
讨论TPS之前,先搞清楚它不是一个单一数字。在推理过程中,有两个完全不同的阶段:
- prefill:处理用户输入的prompt,并行计算,速度快得多,通常能达到每秒几百到几千个token。
- decode:逐token生成答案,每一步都依赖前面的结果,无法并行,速度慢得多,这才是我们平时说的"生成速度"。
还有一个关键指标叫TTFT,即从发出请求到收到第一个token的时间。它受prefill速度和网络、框架调度影响。很多榜单把两个阶段混在一起给一个"TPS",如果prefill占比高,整体数字会被显著抬高。
更隐蔽的问题在于:某些测试用极短的输出、提前终止,或者把重复的定式文本当成有效生成。比如同样是"1+1等于几",模型可能走了缓存路径直接吐结果,这种速度对你日常写长文章没有任何参考意义。我管这种数字叫"TPS虚高",它在很多社区榜单里非常常见。
2.2 一套相对标准的实测流程
我建议放弃听厂商宣传,自己动手测。最干净的方法是直接用llama.cpp自带的计时参数:
./llama-cli -m qwen2.5-14b-instruct-q4_k_m.gguf \ -p "写一段关于量化投资策略的300字分析" \ -n 256 -c 4096 --no-display-prompt \ --timing输出里会显示:
prompt eval time = 154.23 ms / 31 tokens (4.97 ms per token, 201.13 tokens per second) eval time = 8034.11 ms / 247 runs (32.53 ms per token, 30.74 tokens per second)第二行的30.74 tokens per second就是decode阶段真实速度。如果你用的是Ollama,可以通过开启调试模式看类似信息:
OLLAMA_DEBUG=1 ollama run qwen2.5:14b或者写个Python脚本,对API发请求,按时间戳和返回字符数算:
import time, requests, json prompt = "请写一段关于本地部署大模型成本分析的详细说明" url = "http://localhost:11434/api/generate" payload = { "model": "qwen2.5:14b", "prompt": prompt, "stream": True, "options": {"temperature": 0.7, "num_ctx": 4096} } start = time.time() total_tokens = 0 with requests.post(url, json=payload, stream=True) as resp: for line in resp.iter_lines(): data = json.loads(line) if data.get("response"): total_tokens += 1 end = time.time() print(f"耗时 {end - start:.2f}s,生成了约 {total_tokens} token,速度 {total_tokens / (end - start):.2f} token/s")注意大模型按token计,中文一个字大概对应1-1.5个token,所以英文指标和中文实际体感会有差异。
2.3 我手里各规模模型的实际速度
以我手头这台32G Mac mini M6(内存带宽中等档位)为例,场景统一为短对话、temperature=0.7、上下文4K,连续测5次取中位数,数据如下:
| 模型 | 量化 | decode速度 | prefill速度 | 峰值内存 |
|---|---|---|---|---|
| qwen2.5:7b | Q4_K_M | 28-33 token/s | 500-700 token/s | 6-7GB |
| llama3.1:8b | Q4_K_M | 25-30 token/s | 450-600 token/s | 7-8GB |
| qwen2.5:14b | Q4_K_M | 14-18 token/s | 300-450 token/s | 10-12GB |
| qwen2.5:32b | Q4_K_M | 7-9 token/s | 150-250 token/s | 22-25GB |
| qwen2.5:7b | Q8_0 | 18-22 token/s | 400-550 token/s | 8-9GB |
可以看到,7B到14B这个区间速度是完全可以接受的,32B Q4虽然也能跑,但每秒7-9个token的体感明显偏慢,适合批量任务或后台处理,不适合交互式聊天。实测时还发现,32B模型如果上下文拉长到8K,峰值内存会逼近27GB,再往上开就随时可能触发Swap,速度会骤降到1-2 token/s,体验直接崩。
2.4 TPS虚高在哪里:常见话术拆穿
关于"TPS虚高",我总结了几种常见操作:
- 只算decode不算prefill。某些厂商说"500 token/s",可能是prefill阶段的速度,而不是你真正等答案的生成速度。
- 使用极短上下文。上下文512和8192时,KV Cache占用完全不同,长上下文会让有效带宽下降,很多测试只跑短文本。
- 缓存命中。同一个prompt反复发,推理引擎可能走了语义缓存,根本不算模型计算。
- 贪心解码。temperature设为0可以稳定输出,但真实用户不可能都用贪心解码,采样带来的随机性会让耗时分布更宽。
- 多并发压测值。云端推理用高并发把硬件跑满,平均值很漂亮,但你一个人去调API,拿到的是单请求延迟,根本到不了那个数。
所以看到任何"XX模型在XXX平台TPS"结论时,先问一句:测试时上下文多长?输出多少token?是否包含prefill?温度和top_p设的多少?这些都对齐了,数字才有可比性。
3. 端云决策:边界、原则与一个工业场景
3.1 先算一笔账:本地与云端真实成本
很多团队纠结端云,第一反应是"本地省钱、云端费钱",这个判断太粗糙。真实成本要从几个维度算:
- 按量付费:如果每天只有几十次调用,云端按token计费其实很便宜;但如果一天几千次更推任务,费用很快就上来了。
- 本地电费:Mac mini满载功耗大约几十瓦,一年7x24跑,电费也就一两百块钱,几乎可以忽略。
- 时间成本:本地部署要处理模型下载、量化、版本升级、上下文调优,这些不是免费午饭。
- 模型能力差异:云端可以直接用最新的超大参数模型和更强大的工具调用,本地只能靠开源模型的上限。
常见误区是拿"本地7B模型"对比"云端4万亿参数模型",然后下结论说本地不行。合理的方式是任务分级:简单分类、实体抽取、意图识别、摘要清洗,这些7B-14B模型本来就能做得不错;创意写作、复杂推理、长文档多跳问题,才需要上调云端大模型。
3.2 任务分级:什么留在端侧,什么上云
我习惯按四个维度打分:隐私等级、调用频率、延迟敏感度、模型能力要求。
- 高隐私 + 高频率 + 中低能力要求:必须本地,比如员工合同信息抽取、财务摘要。数据根本不该出内网。
- 低隐私 + 高频率 + 中低能力要求:本地优先,省API费用,例如客服话术分类、舆情情感判断。
- 高隐私 + 低频 + 高能力要求:私有化部署大模型,或者本地加一层脱敏后再上云。
- 低隐私 + 中低频 + 高能力要求:云端可以直接用,例如市场周报生成、行业研究总结。
还有一个容易被忽略的因素是延迟。本地模型TTFT通常在几百毫秒,而云API加上网络和排队,TTFT经常要2-5秒。像代码补全、交互式问答这类场景,延迟敏感度极高,本地甚至比"用更强模型但在云端"体验更好。
3.3 像"工业AI检测、服装检测"这类场景,该用单机还是云?
我看到热搜里有"工业ai检测、服装检测这类ai用的是云联网还是单机的ai,用的什么大模型足够"这个问题,这里多聊几句。工业视觉检测,本质上不是大模型的主场。绝大多数产线上的缺陷检测、服装瑕疵识别,靠的是YOLO这类轻量目标检测模型,或者传统图像分割算法,推理速度极快,几百MB到几个GB的模型就能在边缘单机上跑得很好。这类任务完全没必要上云,原因有三个:产线延迟要求毫秒级、网络不稳定导致停机风险、工件图像涉客户保密。
如果你确实想引入LLM能力,比如做"看图说话"、生成不合格品描述、或者处理质检文本报告,那7B-13B级别的多模态模型,在32G本地设备上已经够用。直接用Qwen2-VL、LLaVA等7B版本,图像输入用本地推理,单机即可搞定。更合理的架构是:本地小模型负责图像粗筛和结构化输出,只有低置信度样本或需要复杂语义判断的才上传云端,既控制成本又保住隐私。
3.4 本地前置、云端兜底:务实架构的一种解法
我最后落地的是混合路线,不是非此即彼。流程是:所有请求先到本地Ollama服务,本地14B模型负责意图识别和轻量生成。如果任务难度低,直接出结果;如果任务检测到需要复杂推理、长文学创作或总结构建,再转交云端API。这种做法能把90%的API成本砍掉,同时不会因为本地模型能力弱就牺牲质量。
更进阶的做法是搭一个"路由模型"。拿7B小模型当router,对输入打标签,然后根据标签决定走本地还是云端。这个路由能力不需要太强,准确率有80%就够,剩下的边界情况可以靠兜底策略解决。整个工程落地后,你会发现端云不是对立关系,而是互补关系。
4. 部署与调优的实操手册:从安装到稳定运行
4.1 两条主要技术路线怎么选
在M6上跑模型,主流就两套方案加一个补充:
- Ollama:开箱即用,一条命令拉模型,自带OpenAI兼容API,支持模型管理和上下文参数调整。适合新手和快速原型。
- llama.cpp:需要自己编译或下载预编译包,但控制力最强,能做各种量化、并发参数、CPU/GPU offload微调,Metal后端也比较成熟。
- MLX:苹果自家机器学习框架,在Apple Silicon上延迟优化做得更彻底,适合想要动手写推理代码的人。
如果是公司内部用,我一般推荐直接上Ollama,运维成本低;如果要压榨性能或者做自定义采样逻辑,就编译llama.cpp。
4.2 模型下载与量化选型
模型文件有很多格式,最常用的是GGUF。它是llama.cpp社区主导的格式,支持分层量化,直接对接Metal。我在Ollama里拉模型通常是:
ollama pull qwen2.5:14b-instruct-q4_K_M ollama pull qwen2.5:7b-instruct-q8_0量化等级直接决定质量和速度。Q4_K_M可以理解为"甜点级",体积小、速度高、质量损失可控;Q5_K_M质量更好但体积大10%左右;Q8_0接近无损,但权重文件大、decode速度会明显下降。我的选型逻辑是:
- 日常对话/抽取/摘要:7B-14B的Q4_K_M。
- 财务/法律等需要严谨文本:14B-32B的Q5_K_M。
- 短prompt、低并发场景可以试Q8_0,但不建议用来长上下文。
不要在FP16格式上纠结。FP16权重在32G设备上跑7B可能还有空间,但decode速度会因内存带宽占用过高而明显低于Q4版本,得不偿失。
4.3 上下文长度、KV Cache与内存管理
这是跑大模型最容易爆雷的地方。KV Cache随上下文长度和模型层数线性增长,32B模型开32K上下文,KV Cache能占掉好几个GB,最后跟系统抢内存。我的建议是:默认开8K,长文档任务单独起一个服务实例开16K或32K,用完后立刻关掉。
Ollama里通过环境变量控制:
export OLLAMA_CONTEXT_LENGTH=8192 export OLLAMA_NUM_PARALLEL=1 ollama servellama.cpp的llama-server则直接加参数:
./llama-server -m qwen2.5-32b-instruct-q4_k_m.gguf \ -c 8192 --host 127.0.0.1 --port 8080如果发现内存压力大、速度骤降,第一件事检查是不是上下文开太长,而不是怀疑模型问题。
4.4 并发与长驻服务的一个小提醒
32G统一内存不是服务器内存,别指望它扛大量并发。我实测Ollama开单并发时,14B模型稳定在15 token/s;一旦并行请求超过2个,每个请求的有效吞吐会明显下降,因为KV Cache平分、内存带宽也平分。所以作为个人工作站或者小团队内网服务,Ollama默认单请求串行就够了;真的要多人用,建议加一层简单队列,或者干脆把模型切到云端。
5. 一个可照抄的本地知识抽取与文档理解工作流
5.1 RAG:先把文档切成块,再交给大模型
本地模型理解长文档,最靠谱的方式不是直接把几万字塞进上下文,而是用RAG(检索增强生成)。步骤很简单:
- 把文档按500-800字切成块,保留段落语义。
- 用嵌入模型把每块转成向量,存进Chroma或SQLite。
- 用户提问时先做相似度检索,取Top 3-5块。
- 把检索结果和问题拼成prompt,交给本地LLM生成答案。
在32G设备上,嵌入模型用bge-m3或国产轻量模型,占内存不到1GB,完全不影响主力推理模型。实测下来,14B Q4跑RAG文档问答,准确性和唤起率都够日常使用。
5.2 用OneKE这类框架做结构化抽取
如果你不满足于"回答问题",而是想从合同、论文、工单里抽出实体、关系和事件,那就需要知识抽取框架。OneKE这类工程化框架的价值在于,它把实体识别、关系抽取、事件抽取封装成统一schema,只要给模型一个结构化输出模板,就能得到JSON结果。
在本地跑14B模型时,我习惯用一个通用prompt模板:
prompt = f""" 从下面的文本中抽取所有公司实体和并购关系,输出JSON。 格式: {{"entities": [{{"name": "", "type": "company"}}], "relations": [{{"from": "", "to": "", "label": "acquired"}}]}} 文本: {text} """关键是约束模型输出JSON结构,配合低温采样和固定的few-shot示例,抽取结果稳定性非常高,而且数据完全不出本机,合规压力小很多。
5.3 多模态本地方案的取舍
工业检测或者服装检测这类场景,如果真要跑多模态,我的建议是用Qwen2-VL 7B或LLaVA 7B这类小模型,对单张图片做描述和属性抽取,速度每秒1-3张图,足够做离线批处理。但实时视频流就别指望LLM了,老老实实用YOLO传统检测。
另外提一句:不要对着多模态模型做像素级任务,比如要求它框出每个瑕疵的精确坐标。LLM擅长语义层面的描述,精确定位是CV模型的工作。合理分工是:YOLO负责找框,LLM负责解释框里的内容。
6. 避坑清单与个人体会
6.1 六件我踩过并建议你避开的坑
- 不看量化后缀乱下载。
-q2_K和-q8_0差距极大,名字相似,实际体验天差地别。下载前先看文件名末尾的量化标记。 - 无脑开长上下文。32G跑32B模型还要开32K上下文,秒变PPT式播放。
- 拿别处榜单数字当自己机器表现。不同内存带宽、不同量化、不同上下文长度下,同样模型速度可能差一倍以上。
- 只重推理不重路由。把所有请求交给本地中等模型,会抱怨"本地模型太笨",其实大部分简单任务根本不需要大模型解决,路由做不好,端云决策就是空话。
- 长期不更新推理引擎。Ollama和llama.cpp的Metal优化迭代很快,旧版本和新版本跑同样模型,速度差20%很正常。
- 想在一台32G设备上既要推理又要微调。LoRA微调7B模型在32G上勉强能跑,但几乎是"走钢丝",稳定做法是租卡微调,导出GGUF后本地推理。
6.2 我最终的取舍:14B Q4主力,32B Q4次之
踩完这些坑之后,我当前的固定配置是:14B Q4作为日常主力,负责RAG问答、意图识别、摘要生成;32B Q4负责偶尔的长文档综合分析和难一点的代码修复;7B多模态模型处理图片;嵌入模型单独部署。这套方案在32G的Mac mini M6上稳定跑了几个月,没有一次OOM导致服务宕掉。
如果你问我要不要加内存、换更高配版本,我的建议是:32G已经覆盖了绝大多数本地大模型实际场景。真正要升级,优先选内存带宽更高的档位,其次是更大的模型省去量化焦虑,最后才是CPU或GPU核心数。别被"越大越好"绑架,算好自己的调用频率、任务类型和数据隐私边界,端云之间做一次务实决策,比堆硬件有用得多。