8G 显存跑 llama.cpp 怎么调:32K 更稳,64K 要开 KV Cache 量化

整理 8G 显存场景下使用 llama.cpp 的几个关键调优结论:什么是 32K、64K 和 KV Cache,为什么 32K 往往更稳,64K 为什么更依赖缓存量化,以及为什么一味拉高 CPU 线程反而可能更慢。

8G 显存到底还能不能把本地大模型跑顺,尤其是在长上下文场景下还能不能保住速度,这是很多人在折腾 llama.cpp 时都会遇到的问题。

核心结论可以先记住三条:

  • 8G 显存来说,32K 上下文通常是更稳的平衡点
  • 如果一定要跑 64KKV Cache 量化基本是必选项
  • 在全显卡运行场景里,盲目拉高 CPU 线程数,反而可能让速度明显下降

一、先解释清楚:32K、64K 和 KV Cache 是什么

很多人第一次看这类调优文章,最容易卡住的就是这三个词。

32K64K 说的是上下文长度,也就是模型一次最多能处理多少 token。这里的 K 就是千,32K 大约是 32000 token64K 大约是 64000 token。上下文越长,模型一次能看到的历史内容越多,适合长文档问答、长对话和多轮分析。

KV Cache 则是模型为了加速连续生成而保留的一份中间结果缓存。你可以把它理解成:模型已经读过、算过的一部分内容,不会每次都从头重算,而是把关键结果先存起来,后面继续接着用。这里的 KV,来自 Transformer 里的 KeyValue

为什么这三个词总是一起出现?因为:

  • 32K64K 决定你想让模型一次记住多长内容
  • KV Cache 决定为了维持这段记忆,要额外占多少显存
  • 上下文越长,KV Cache 通常越大,显存压力也越高

所以很多长上下文变慢的问题,本质上并不是模型“不会算”,而是缓存太大,把显存挤到了临界点。

二、为什么 32K 和 64K 的速度会差这么多

这里用《三体》大约 3 万字的文本做压力测试,对比 32K64K 两种上下文设置。结果很夸张:在文档长度接近的情况下,64K 模式的速度显著下降,总耗时也明显拉长。

问题不在模型突然变笨,而在显存边界被撞到了。

32K 模式下,模型权重加缓存还能基本塞进 8G 显存里,数据大多走显卡显存带宽,速度还能维持在比较可用的区间。但一旦切到 64K,缓存体积继续上涨,总占用逼近甚至超过显存上限,系统就会把部分数据挤到内存里。

这时候真正掉下去的,不是算力,而是带宽。

也就是说,很多人看到的是“上下文翻倍后速度暴跌”,本质上其实是数据路径从显存掉到了共享内存或系统内存,推理链路不再跑在高速通道上。

三、64K 还能不能跑,关键在 KV Cache 量化

第二个很关键的结论,是 KV Cache 量化对 8G 显存用户特别重要。

如果不改变模型本身,只针对缓存做量化,长上下文下最直接的收益就是把缓存占用压缩下来,让原本已经溢出的那部分重新回到显存里。这样一来,64K 模式虽然依然比 32K 更吃资源,但至少不会直接跌进最慢的区间。

换句话说:

  • 32K 更像是 8G 显存的默认推荐区间
  • 64K 不是完全不能跑
  • 但如果不上缓存量化,性能很容易从“能用”直接掉到“很难用”

如果你的目标是尽量稳定地跑长上下文,那优先级通常应该是:

  1. 先确认显存是否已经逼近上限
  2. 再决定是否开启 KV Cache 量化
  3. 最后才去继续尝试更激进的吞吐量参数

四、GPU 占用不高,不代表显卡没干活

这是一个很容易打破直觉的点。

很多人看到任务管理器里 GPU 使用率只有二三十,就会怀疑:

  • 是不是参数没设对
  • 是不是模型没真正跑到显卡上
  • 是不是显卡根本没吃满

但这组测试给出的判断是,llama.cpp 这类推理很多时候首先卡的不是核心算力,而是显存读写速度。

也就是说,显卡核心可能很快就把一批计算做完了,但后面还得等下一批权重和缓存数据搬过来。于是你看到的现象就会变成:

  • 核心占用不算高
  • 但整体速度还是上不去

这不是显卡在偷懒,而是数据通路太窄。

所以看本地大模型速度时,不能只盯着 GPU Usage。显存容量、显存带宽、缓存是否溢出,往往更影响最终体验。

五、调大吞吐量参数,确实可能再快一截

这里还做了一个思路很清晰的测试:既然显卡核心并没有完全忙满,那能不能通过调大吞吐量相关参数,让显卡一次处理更多数据,把并行能力进一步压出来。

测试结果表明,这种做法确实有机会把速度再往上拉一段。

但这里也有一个前提:显存还得扛得住。

因为吞吐量相关参数调大之后,往往会带来额外显存占用。如果你本来就在 64K、高缓存、显存见底的状态下继续往上推,就很容易出现两种情况:

  • 直接崩溃
  • 没崩,但被迫进入更慢的共享内存模式

所以更稳妥的顺序通常不是“先把参数拉满”,而是:

  • 先守住显存边界
  • 再考虑吞吐量优化
  • 每调一步都重新看速度和稳定性

六、CPU 线程不是越多越好

这也是整篇内容里最值得记住的坑点之一。

很多人做本地推理调优时,容易下意识觉得线程越多越快,既然机器有那么多线程,不用满就像浪费。但实测给出的结果恰恰相反:在模型已经主要跑在显卡上的情况下,强行把 CPU 线程拉高,性能反而会明显变差。

原因不复杂。

在全显卡运行时,CPU 更像是调度者和预处理协作者,而不是主力计算单元。这时候如果开太多线程,CPU 端的线程竞争、调度切换和上下文切换开销都会变重,最终把本来应该更流畅的数据流打乱。

结果就是:

  • CPU 更忙了
  • 但整体速度变慢了

所以在这种场景下,默认设置或者较低线程数,往往比一味拉满更靠谱。

七、对 8G 显存用户更实用的一套思路

如果把上面的结论压成一套更容易执行的思路,大概可以整理成这样:

1. 先把 32K 当成默认目标

如果你用的是 8G 显存显卡,先别急着追 64K32K 往往是速度、稳定性和显存占用之间更现实的平衡点。

2. 想上 64K,先处理缓存问题

不要先想“还能不能再榨一点速度”,而是先确认 KV Cache 有没有量化、显存是不是已经压线。

3. 不要用 GPU 占用率判断一切

低占用不一定代表设置错了,也可能只是显存带宽在拖后腿。

4. 吞吐量优化可以做,但别越过显存边界

这类参数确实能带来收益,但前提是显存还有余量。

5. CPU 线程先保守,再逐步测试

如果模型已经基本跑在显卡上,CPU 线程并不是越高越好。先用默认值或低线程值测试,再看是否值得继续调整。

结语

这组内容最有价值的地方,不只是给出几个测试数字,而是把一个经常被忽略的事实讲清楚了:

本地大模型调优,很多时候拼的不是“有没有把所有参数开到最大”,而是你有没有搞清楚瓶颈到底在算力、显存容量、显存带宽,还是在 CPU 调度。

8G 显存用户来说,真正更稳的思路通常不是硬冲最长上下文,而是先守住显存边界,再决定要不要继续往上加。

如果只记一句话,那就是:

32K 往往是 8G 显存更稳的工作区间;64K 不是不能跑,但前提是你已经把 KV Cache 和显存占用管住了。

记录并分享
使用 Hugo 构建
主题 StackJimmy 设计