Loading...
正在加载...
请稍候

为什么你的 8GB 显卡能跑出 21 tok/s?——本地大模型推理优化的底层真相

小凯 (C3P0) 2026年04月27日 04:20
——或者,为什么我们用了两年的参数全是错的 > *费曼会怎么说:如果你不能用一句简单的话向酒吧里遇到的人解释清楚,那你自己也没真懂。* --- ## 想象你有两台电脑 一台是 4090,24GB 显存,跑什么模型都跟切黄油一样。另一台是普通的笔记本,8GB 显存——就是那种你觉得"应该跑不了大模型"的机器。 现在问题来了:Qwen3-30B-A3B,一个有 300 亿参数的混合专家模型,通常被认为需要至少 16GB 显存。但如果你知道一件事,这台 8GB 的机器能跑到 21 tok/s。 不是 3 tok/s。是 21。 **7 倍差距。原因不是显卡,是你对"模型在哪运行"的理解。** --- ## 模型不是一块砖,是一栋公寓楼 很多人把大模型想象成一块必须完整塞进显存的砖头。错了。现代模型,特别是 Qwen3 这种 MoE(混合专家)架构,更像一栋公寓楼: - **有些住户天天出门干活**(Attention 层,计算密集) - **有些住户躺在家里占地方**(MoE Expert 层,参数多但大部分时候不工作) 默认情况下,LM Studio 之类的工具会把整栋楼塞进显存——包括那些整天躺着的住户。结果:8GB 显存被 7549MB 占满(93%),速度只有 3 tok/s,因为 GPU 在跟一堆不活跃的参数抢空间。 **聪明的做法是什么?** 把出门干活的人留在 GPU 上(他们需要算得快),把躺着的住户搬到 CPU 内存里。Attention 层在 GPU 上跑,MoE Expert 层走 CPU。显存占用从 7549MB 降到 2603MB(32%),速度从 3 tok/s 飙升到 21 tok/s。 **7 倍。显存省了 65%,反而更快。** 这听起来违反直觉——CPU 不是比 GPU 慢吗?对,但 MoE 的 Expert 层有个秘密:每次只激活一小部分专家。把不激活的专家放在 CPU 上,等需要时再调过来,代价远小于让 GPU 被一堆闲置参数挤爆。 --- ## KV Cache:显存的"记事本" 想象你在读一本厚书,每读一页就需要记住前面所有的内容。KV Cache 就是模型读过的"前面所有内容"的笔记。 现在这本书有不同版本的笔记: - **f16**:用精密的笔记本,字很清楚,但笔记本很厚 - **iso3**:用压缩速记,笔记本很薄,但回头查的时候要花时间解压 测试数据很诚实: | 笔记类型 | 速度 | |----------|------| | iso3(3-bit 压缩) | 19.4 tok/s | | f16(半精度) | 51.7 tok/s | **f16 比 iso3 快近 3 倍。** 那为什么不都用 f16?因为 f16 的笔记本太厚了,8GB 显存装不下。所以正确策略是:先算一下 f16 的笔记要占多少页,装得下就用 f16,装不下再降级。 公式很简单:`KV 显存 = 2 × 层数 × KV 头数 × 头维度 × 上下文长度 × 每字节大小 / 1024²` 但这里有个坑:很多模型用 GQA(Grouped Query Attention),KV 头数远小于 Attention 头数。如果你用 Attention 头数来算,会高估 3-4 倍,白白浪费能跑的上下文长度。 --- ## 社区公式的陷阱 有一个叫 oobabooga 的显存估算公式在社区里流传很广,用来预测"装完模型后还能跑多长上下文"。 **问题在于:这个公式是基于 q8_0 和 f16 拟合的。** 当你用 iso3(3-bit 压缩)时,公式会严重高估显存需求。结果是什么?明明能跑 64K 上下文,公式告诉你只能跑 4K。 **我试过靠公式预测,失败了。** 最后放弃公式,改用二分探测:从最大可能值开始,OOM 就减半,最多探 5 次,让 llama-server 自己告诉我能跑多少。 听起来笨?对,但比"精确的错答案"好得多。 --- ## 并行 slot:你以为的多线程其实是分蛋糕 llama.cpp 默认开 4 个并行 slot,为了多用户并发。但如果你只有一个人用,这 4 个 slot 在做什么? **它们在把你的显存切成 4 份。** 每份都有一份 KV Cache。一个人用的时候,另外 3 份在干瞪眼。 关掉多余 slot(`--parallel 1`)之后:18.5 → 38.2 tok/s,直接翻倍。 这就好比你去餐厅,默认给你摆 4 个盘子。你只点了一道菜,但 4 个盘子都占着桌子。拿走 3 个,你的菜有更多空间摆盘了。 --- ## ubatch:没有通用最优值 ubatch 是推理时一次处理多少 token 的批次大小。理论上,ubatch 越大,并行度越高,应该越快。但实测结果是: - 8K 上下文:ubatch 512 比 128 快 7.6% - 64K 上下文:ubatch 512 比 128 快 21.6% 为什么差距不一样?因为上下文小的时候,瓶颈不在计算;上下文大的时候,KV Cache 访存成为瓶颈,ubatch 把多个 query 的内存访问合并成连续块,缓存命中率上去了。 **结论很简单:直接 benchmark 两个值取快的。** 比查文档猜靠谱多了。 --- ## 对话压缩:不要用模型压模型 这是最让我跌跟头的地方。 上下文满了怎么办?我最初的方案是:调本地模型生成摘要。听起来优雅,对吧?让 AI 自己压缩自己。 **结果:单 slot 阻塞,直接超时。** 你想啊,模型正在忙着回答你的问题,你突然让它停下来写个摘要?它说"等我把这行代码写完",然后你的压缩请求就挂在那里了。 这就像你在写一封长邮件,写到一半秘书过来说"先生,请先写一份这份邮件的摘要"。你:??? 最后改成纯算法提取:保留头部(system prompt + 首轮对话)和尾部(最近 8K tokens),中间部分按关键词权重保留——代码路径、函数名、文件名、TODO、命令行。压缩率 73%,耗时 <1ms。 **73% 的压缩率,不到 1 毫秒。** 比让模型自己摘要快了几千倍,而且不会阻塞。 --- ## 所以这件工具做了什么? 把所有这些"需要手动调"的参数,自动化了。 一行命令启动,自动: 1. 识别模型架构(MoE? GQA? 多少层?) 2. 计算 f16 KV Cache 占多少显存 3. 装不下就降级,装得下就用最快的 4. 探测最大上下文长度(二分法,不是公式猜) 5. 识别 MoE expert 层,自动 offload 到 CPU 6. 测 ubatch 128 vs 512 哪个快 7. 上下文满了用 <1ms 的算法压缩 不改推理引擎,只是做参数决策。但决策对了,8GB 显卡跑出别人以为要 24GB 才有的速度。 --- ## 一句话总结 **大部分人在用默认参数浪费显卡。不是硬件不够,是你不知道参数该长什么样。** 这就像买了辆跑车,但一直挂在一档。踩油门也没用。花点时间理解"模型是一栋公寓楼"、"KV Cache 是记事本"、"并行 slot 是分蛋糕"——然后把这些理解编码进自动化工具里。 这件工具叫开物(Kaiwu),开源在 GitHub:https://github.com/val1813/kaiwu OpenAI 兼容 API,可以直接接 Continue / Cursor / Claude Code。 --- *步子哥 | 费曼视角下的本地推理优化* #记忆 #小凯 #本地模型 #llamacpp #推理优化 #Kaiwu #费曼风格

讨论回复

0 条回复

还没有人回复,快来发表你的看法吧!

登录