去年底我把工作流从云端搬回本地时,身边不少人劝我别折腾:一台32G的Mac mini M6,说白了就是个带风扇的小盒子,凭什么跟人家八卡A100集群比?可我偏偏就想搞清楚一件事——这个价位的机器跑大模型,算力到底够不够,官方宣传的TPS到底能不能信,以及什么时候该端上本地、什么时候该老实交回云上。
折腾了两个月,把Qwen、Llama、Mistral好几个系列的量化版来回跑了一遍,又把7B到32B的模型都塞进去实测过,我确定可以回答这个问题了:32G的Mac mini M6能跑大模型,而且不是只能跑着玩。但前提是你得知道它的算力边界在哪里,得自己动手测真实TPS,还得学会一套端云决策的取舍逻辑。这篇文章就把我这段时间的实测数据、踩坑经历和最终方案全部摊开讲,适合所有想在本地跑大模型但不想被显卡账单绑架的人。
1. 算力底牌:M6到底给大模型留了多少余量
很多人一听说"Mac跑大模型",第一反应是看神经网络引擎的TOPS数值。这个思路不能说错,但在大模型推理场景下,它离真相很远。
1.1 神经网络引擎的纸面算力,为什么当不了主战力
M6芯片的神经网络引擎理论算力比我之前用的M4又涨了一截,跑图像分类、语音识别这类固定结构模型确实快。但大模型是另一回事,它靠的是Transformer解码器的自回归过程——生成每个token都必须把前面所有token的注意力重新算一遍,这属于典型的长序列、动态形状计算。神经引擎喜欢的是静态、确定性的算子图,给它喂一个动态变化的attention矩阵,优势发挥不出来,多数推理后端甚至根本不会调它。
真正干活的主力是GPU核心和CPU核心。M6延续了M系列统一内存架构,GPU可以直接访问全部32G内存,不需要把数据从显存拷贝到内存再拷回去。这个特性在跑大模型时是决定性的,因为它直接把"显存不够"这个独显玩家最头疼的问题消解掉了。NVIDIA的RTX 4060笔记本版才8G显存,跑7B模型Q4量化都勉强,而M6的32G统一内存意味着我可以在内存里同时摆下模型权重、KV cache和系统其他进程,不用无休止地等swap。
但别高兴太早。统一内存解决了容量,没解决带宽。推理时GPU每个token都要把整个模型权重读一遍,内存带宽就是那根传送带,带宽不够,算力再强也得排队等着搬砖。这就是为什么同为32G,M6标准版的解码速度会比M6 Pro版明显慢——Pro版的内存通道数更多,带宽高出一大截。
1.2 内存带宽:一句话算出你的真实推理上限
这里有个特别实用的估算公式,我实测后验证过,误差不大:
生成TPS的上限 ≈ 有效内存带宽 ÷ 模型权重大小
因为自回归解码每生成一个token,理论上最少要把模型全部权重从内存读一遍。比如一个7B模型Q4量化后约4.5GB,如果有效带宽按250GB/s算(M6标准版的实际水平在200~300GB/s之间),那理论峰值就是250÷4.5,约55 token/s。14B模型Q4约9GB,理论峰值就掉到27 token/s左右。32B模型Q4约18GB,理论峰值只剩13 token/s上下。
这个计算把"为什么大模型在Mac上跑不快"一句话说透了:不是算力不够,是带宽锁死了天花板。M6的GPU每秒能做几十万亿次浮点运算,但每次生成token都得把那几GB权重从头搬一遍,搬运时间远大于计算时间。所以你在网上看到那些宣称"XGB显存跑70B模型60 token/s"的跑分,要么用了极高压缩的量化,要么根本没算KV cache带宽——后文我会详细拆这个。
1.3 32G统一内存里,实际能拿多少给模型
标称32G,系统本身要占掉8~10G(开着浏览器和IDE更夸张),所以跑模型时可用的也就22~24G。我没用虚拟内存膨胀的骚操作,因为M系芯片的swap本质上是吃SSD带宽,一旦模型超过物理内存,速度会从每秒几十token直接掉到个位数,体验崩坏。
我自己习惯用一个更保守的判定标准:模型权重加KV cache的峰值占用不超过18G,留4G给系统和其他应用,这样既能稳定跑,又不至于让整个机器卡成PPT。SPR:别碰第三条路。
2. 量化后,哪些模型在32G M6上真正值得跑
选择模型不是看排行榜,是看你的内存账本。我把32G M6能舒适运行的模型范围摸得很清楚,这里直接给结论和计算过程。
2.1 用"参数量×量化系数"做选型,而不是凭感觉
一个10B参数的模型,FP16精度下权重约20GB,32B约64GB,70B约140GB——都不适合32G机器。但量化把这套账本重写了。Q4_K_M量化大概能把参数压缩到每参数0.6字节左右,也就是说:
- 7B/8B模型:约4.5GB权重,32G内存放得很舒服,还能开长上下文;
- 13B/14B模型:约8~9GB权重,属于"性价比最优区",日常用很稳;
- 24B模型:约14GB权重,32G能跑但KV cache空间开始紧张;
- 32B模型:约18GB权重,勉强塞下,但上下文只能开很短,生成速度也掉得厉害;
- 70B模型:约40GB权重,32G直接出局,别想。
我实际跑下来,32G M6的甜蜜区集中在**7B到24B(Q4/KV cache适量)**之间。用它跑32B Q4不是不行,我拿GLM-4-32B Q4试过,加载完权重后内存剩余不到4G,只能开4K以下上下文,生成速度稳定在13~15 token/s——能对话,但稍微聊长一点就开始卡顿。这种体验怎么说呢,像开一辆满载超重卡车,不是说不能走,只是每一步都让我担心。
2.2 KV cache和上下文长度:那个被所有人忽略的隐形大户
很多人只算模型权重,忘了一个同样吃内存的东西:KV cache。它存的是历史token的注意力中间结果,随上下文长度线性增长。以7B模型为例,4K上下文的KV cache约0.5GB,32K上下文直接飙到4GB——这个开销甚至会反超模型权重本身。
在M6上,KV cache不单占内存,还占带宽。解码时每生成一个token不只是读4.5GB权重,还要同时读全部KV cache,上下文越长,单token耗时越长,TPS降得越明显。所以网上某些"70B模型本地跑出60 token/s"的截图,十有八九是开2K短上下文、单轮短测试跑出来的神仙数据,拿到32K长对话场景立刻露馅。
我的实操习惯是:除非场景真的需要,否则把上下文限制到8K以内。32G M6适合跑14B Q4模型配8K上下文,这套组合能兼顾质量、速度、内存三者平衡。如果非要上24B模型,我建议上下文压到4K,否则KV cache一膨胀,生成速度会肉眼可见地跌。
2.3 我实测下来最舒服的模型清单
直接给个我现在还在用的配置表,都是32G M6上跑过的、稳定可复现的:
| 模型 | 量化等级 | 权重大小 | 推荐上下文 | 实测生成TPS | 用途 |
|---|---|---|---|---|---|
| Qwen2.5-7B-Instruct | Q4_K_M | 4.7GB | 8K~16K | 55~65 | 日常问答、摘要、代码补全 |
| Llama-3.1-8B-Instruct | Q4_K_M | 5.0GB | 8K | 50~60 | 英文写作、通用对话 |
| Qwen2.5-14B-Instruct | Q4_K_M | 9.0GB | 6K~8K | 32~38 | 复杂推理、长文分析 |
| Mistral-Small-24B | Q4_K_M | 14.5GB | 4K | 18~22 | 多轮长任务、工具调用 |
| GLM-4-32B | Q4_K_M | 18.2GB | 4K | 12~15 | 边缘场景,能用但不推荐日常 |
这个表是基于我自己的实测环境(macOS最新稳定版、MLX后端、温度参数默认、单用户串行请求)跑出来的,跑分从来不是普适真理,但同一台机器上做横向对比很可靠。说实话,日常80%的事情我用7B模型就够了,14B只在写复杂代码和做长文档分析时才启用。
3. 真实TPS:拆穿那些虚高数字背后的三类口径
"TPS虚高"这个词最近在很多硬件讨论里被反复提起,我觉得有必要把它掰开揉碎讲清楚。因为很多人兴冲冲跑到评论区质问"为什么我的TPS只有你的一半",问题往往出在——你们说的TPS根本不是同一个东西。
3.1 为什么厂商标称TPS在你电脑上永远跑不出来
厂商宣传的TPS有两种典型套路。第一,用极端高batch并发测吞吐。模型同时处理十几个请求,GPU的利用率被拉满,总吞吐确实好看,但摊到单个对话请求上,感受速度可能只有个位数令牌每秒。第二,用极短的prompt、极短的生成长度测"峰值",模型刚加载完权重、KV cache几乎是空的,这时候测出来的速度当然高,但真实对话里context一长就原形毕露。
我试过一个特别极端的情况:用同一个Qwen2.5-7B Q4,短prompt短生成长度测试时能跑出73 token/s,但把prompt加长到12K、生成长度拉到1024之后,TPS掉到了41——下降幅度将近一半。不是说模型变了,而是KV cache读取量的增加实实在在地挤占了带宽。所以这里重要的事情说三遍:测TPS必须写明上下文长度、生成长度和batch数,否则数字没有任何意义。
3.2 正确测TPS的三步法
我现在每个模型会固定测三个指标,建议你也照这个套路来:
- 首token延迟(TTFT):从提交请求到吐出第一个token的时间。这个决定"打字感",太长会让人烦躁;
- 解码吞吐(Decoder TPS):生成阶段的稳态token速度,用连续生成512个token的平均值计算;
- 端到端总耗时:把整个请求从发送到完整接收的总时间除以总token数,包含所有调度开销。
命令行测法我用的是最笨但最有效的方式:让模型生成固定长度(比如512 token)的文本,用time记录总耗时,再统计生成token数。举例,我用mlx-lm跑Qwen2.5-14B-Q4时,脚本大概是这样的:
time mlx_lm.generate \ --model mlx-community/Qwen2.5-14B-4bit \ --prompt "写一篇关于本地大模型部署的技术分析,不少于300字" \ --max-tokens 512 \ --temp 0.7然后看终端输出的token/s,并核对系统监控确认内存没被打到swap区。如果是llama.cpp后端,则固定-n 512,读取最后的eval time输出。这套方法不依赖任何花哨工具,人人都能复现,排掉了软件和缓存波动带来的水分。
3.3 32G M6上的真实TPS实测数据
先说明测试条件:mlx-lm后端、Q4量化、上下文4K、生成长度512、温度0.7、单用户、机器空载(只保留系统常驻进程)。这个条件下:
- 7B Q4:首token约0.6~0.9秒,解码TPS约55~65,是真正的"日常主力";
- 14B Q4:首token约1.2~1.8秒,解码TPS约32~38,需要耐心但可用;
- 24B Q4:首token约2.5秒,解码TPS约18~22,能接受但明显慢一截;
- 32B Q4:首token约3秒,解码TPS约12~15,只适合没有时效要求的离线任务。
把TP S乘以一个感受度换算:Qwen标注的中文对话体验,大约20 token/s就已经接近正常人类阅读速度。14B模型的30+ token/s日常用完全够,24B的20 token/s左右也可以接受。如果你拿这个数字去和云端的几百token/s比,当然没有可比性,但端侧的诉求本来就不是追极速,而是保隐私、零边际成本、断网可用。
4. 端云决策:什么时候该本地跑,什么时候老实交回云上
讲真,Mac mini M6的出现让"端云协同"从一个伪命题变成了真需求。它不是一个"二选一"的问题——到底是把模型全放本地,还是全交给云API?我的答案是:按请求动态路由,小活本地,大活上云,中间状态用规则做兜底。
4.1 用隐私和成本两条线画决策边界
画一条最简单的分界线,把任务分成四类:
| 场景 | 本地端(M6) | 云端API |
|---|---|---|
| 代码片段补全、翻译、草稿改写 | 优先本地 | 不上云 |
| 含内部数据的文档摘要 | 必须本地 | 禁止上云 |
| 超长文档(100K+)分析 | 上下文装不下 | 上云 |
| 高并发、多轮复杂Agent任务 | 算力不够 | 上云 |
我把这条规则沉淀成了一个脚本里的route()函数:如果输入文本长度小于8K,且文本里有手机号、身份证、企业内网路径等敏感标记,直接路由到本地14B模型;如果输入超长、或者需要联网检索、或需要调用外部工具,才走云端API。这样既保住了80%场景的隐私底线,又不会在复杂任务上死磕本地算力。
4.2 端云协同的正确姿势:不是二选一,是两级流水线
我试过两种端云协作方式,第一种是"本地意图理解,云端深度执行":在本地跑一个7B小模型,只负责判断用户请求的意图、抽取关键参数,然后把"用户想干复杂任务"这个结论交给云端大模型执行。因为小模型识别意图只需要跑几秒,成本极低,但把绝大多数简单请求挡在了本地,云端API调用量能降到原来的三分之一。
第二种是"本地缓存上下文,云端做增量生成":把历史对话塞给本地模型做摘要压缩,压缩完的关键信息再拼进云端请求。这招对API按token计费的服务特别有效,长对话的上下文成本被大幅削减。本质上是让本地模型做预处理器,云端只做精加工。这两种模式都需要代码配合,但对端云协同的理解就完全不一样了——不是互斥的备胎关系,而是流水线上下游。
4.3 端云协同的低成本兜底方案
还有一个思路值得展开:把32G M6当常驻推理缓存层。我平时会把云API返回过的高频结果缓存到本地,下次遇到相似查询直接走本地7B模型回答,不再调云端。这个方案对客服问答、代码报错解读这类模式化场景特别适用。缓存量一旦超过阈值就清理最旧的条目,始终保持本地占用稳定。
这么说吧,如果你的需求是"既要数据不出门,又要能处理复杂任务",那这套本地小模型过滤+云端大模型兜底的路由方案,很可能就是端云协同落地性价比最高的形态,比硬买一台64G M6甚至更贵的服务器实在得多。
5. 实操调优:从开箱到顺手的几件关键事
最后这章写给准备动手的人。我说点实在的,别踩我踩过的坑。
5.1 推理后端选型:MLX、Ollama还是llama.cpp
在M6上,我的优先级排序是MLX > Ollama(MLX后端) > llama.cpp(Metal后端)。
MLX是苹果自家的机器学习框架,对M系芯片的算子调度调校最彻底。同样的Qwen2.5-7B Q4,MLX跑64 token/s,llama.cpp Metal后端大概跑50 token/s,差距约20%。这个差距在14B模型上会更明显。Ollama其实底层也能调MLX,胜在部署省事,一条命令拉模型、一条命令起服务,适合不想折腾的人。
llama.cpp的价值在于GGUF生态,模型权重的选择面最广,想要的最偏门模型可能只出GGUF格式。我的做法是:日常主力用MLX跑量化模型,遇到值得试的新模型先用llama.cpp跑通,确认值得留在本地再转成MLX格式。需要提一句,千万别在macOS上装Windows虚拟机跑CUDA版推理,开销全在虚拟化层,速度直接腰斩,白白浪费M6的Metal性能。
5.2 让TPS不掉链子的四条内存经验
这四条是我真的踩过坑才总结出来的,分享给你:
第一,把浏览器当作头号敌人。Chrome开20个标签页,内存占用能吃掉七八个G,模型被迫用swap之后,TPS从60掉到20都不意外。我现在写代码、跑模型用的是一台关了浏览器的主力机,轻度网页浏览走另一台设备。
第二,别把上下文拉到最大。很多人的习惯是模型支持多大上下文就开多大,但文档前面分析过,KV cache是线性膨胀的,上下文从8K拉到32K,生成TPS能掉三成。真实需求是多少就开多少,我通常保持模型最大上限的一半。
第三,量化等级够用就好。Q4_K_M是实测性价比之王,Q8和FP16在32G M6上只适合7B小模型,但提升的质量远小于多占的内存。14B以上老老实实用Q4,不要跟内存过不去。
第四,控制单次生成长度。一次性生成2048个token会让后半段速度明显下降,因为KV cache越来越大。我现在所有任务默认生成长度512,不够就手动续写,体验反而更稳定。
5.3 从零到跑通的落地清单
如果你是第一次在Mac mini M6上跑大模型,照着这几步走,半小时就能通:
# 1. 检查系统版本,确保是支持M系列最新特性的版本 sw_vers # 2. 安装MLX生态 pip install mlx-lm # 3. 拉取一个轻量模型 mlx_lm.generate \ --model mlx-community/Qwen2.5-7B-4bit \ --max-tokens 128 \ --prompt "你好,介绍一下你自己" # 4. 跑通后测速,记录基线 # 5. 看内存占用:Activity Monitor -> Memory -> Memory Pressure 保持绿色跑通第一个模型之后,再一步步升级到14B/24B,每次升级都同步记录TPS和内存压力,你会形成属于自己的最佳配置表。我的最终方案是常驻两个模型:7B做路由和日常快答,14B做深度任务,一个shell脚本按场景动态加载。32G M6这台机器,说实话在跑大模型这个方向上并不是堆料的选择,但只要你摸清了算力边界、TPS的真实口径和端云协作的取舍,它能给你的是GPU服务器给不了的安静、低功耗和完全属于自己的数据控制权。