<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>GPU调优 on KnightLi的博客</title>
        <link>https://www.knightli.com/tags/gpu%E8%B0%83%E4%BC%98/</link>
        <description>Recent content in GPU调优 on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Thu, 23 Apr 2026 12:13:04 +0800</lastBuildDate><atom:link href="https://www.knightli.com/tags/gpu%E8%B0%83%E4%BC%98/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>8G 显存跑 llama.cpp 怎么调：32K 更稳，64K 要开 KV Cache 量化</title>
        <link>https://www.knightli.com/2026/04/23/llama-cpp-8g-vram-32k-64k-kv-cache-tuning/</link>
        <pubDate>Thu, 23 Apr 2026 12:13:04 +0800</pubDate>
        
        <guid>https://www.knightli.com/2026/04/23/llama-cpp-8g-vram-32k-64k-kv-cache-tuning/</guid>
        <description>&lt;p&gt;&lt;code&gt;8G&lt;/code&gt; 显存到底还能不能把本地大模型跑顺，尤其是在长上下文场景下还能不能保住速度，这是很多人在折腾 &lt;code&gt;llama.cpp&lt;/code&gt; 时都会遇到的问题。&lt;/p&gt;
&lt;p&gt;核心结论可以先记住三条：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对 &lt;code&gt;8G&lt;/code&gt; 显存来说，&lt;code&gt;32K&lt;/code&gt; 上下文通常是更稳的平衡点&lt;/li&gt;
&lt;li&gt;如果一定要跑 &lt;code&gt;64K&lt;/code&gt;，&lt;code&gt;KV Cache&lt;/code&gt; 量化基本是必选项&lt;/li&gt;
&lt;li&gt;在全显卡运行场景里，盲目拉高 &lt;code&gt;CPU&lt;/code&gt; 线程数，反而可能让速度明显下降&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;一先解释清楚32k64k-和-kv-cache-是什么&#34;&gt;一、先解释清楚：32K、64K 和 KV Cache 是什么
&lt;/h2&gt;&lt;p&gt;很多人第一次看这类调优文章，最容易卡住的就是这三个词。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;32K&lt;/code&gt; 和 &lt;code&gt;64K&lt;/code&gt; 说的是上下文长度，也就是模型一次最多能处理多少 &lt;code&gt;token&lt;/code&gt;。这里的 &lt;code&gt;K&lt;/code&gt; 就是千，&lt;code&gt;32K&lt;/code&gt; 大约是 &lt;code&gt;32000 token&lt;/code&gt;，&lt;code&gt;64K&lt;/code&gt; 大约是 &lt;code&gt;64000 token&lt;/code&gt;。上下文越长，模型一次能看到的历史内容越多，适合长文档问答、长对话和多轮分析。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;KV Cache&lt;/code&gt; 则是模型为了加速连续生成而保留的一份中间结果缓存。你可以把它理解成：模型已经读过、算过的一部分内容，不会每次都从头重算，而是把关键结果先存起来，后面继续接着用。这里的 &lt;code&gt;K&lt;/code&gt; 和 &lt;code&gt;V&lt;/code&gt;，来自 Transformer 里的 &lt;code&gt;Key&lt;/code&gt; 和 &lt;code&gt;Value&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;为什么这三个词总是一起出现？因为：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;32K&lt;/code&gt;、&lt;code&gt;64K&lt;/code&gt; 决定你想让模型一次记住多长内容&lt;/li&gt;
&lt;li&gt;&lt;code&gt;KV Cache&lt;/code&gt; 决定为了维持这段记忆，要额外占多少显存&lt;/li&gt;
&lt;li&gt;上下文越长，&lt;code&gt;KV Cache&lt;/code&gt; 通常越大，显存压力也越高&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以很多长上下文变慢的问题，本质上并不是模型“不会算”，而是缓存太大，把显存挤到了临界点。&lt;/p&gt;
&lt;h2 id=&#34;二为什么-32k-和-64k-的速度会差这么多&#34;&gt;二、为什么 32K 和 64K 的速度会差这么多
&lt;/h2&gt;&lt;p&gt;这里用《三体》大约 &lt;code&gt;3&lt;/code&gt; 万字的文本做压力测试，对比 &lt;code&gt;32K&lt;/code&gt; 和 &lt;code&gt;64K&lt;/code&gt; 两种上下文设置。结果很夸张：在文档长度接近的情况下，&lt;code&gt;64K&lt;/code&gt; 模式的速度显著下降，总耗时也明显拉长。&lt;/p&gt;
&lt;p&gt;问题不在模型突然变笨，而在显存边界被撞到了。&lt;/p&gt;
&lt;p&gt;当 &lt;code&gt;32K&lt;/code&gt; 模式下，模型权重加缓存还能基本塞进 &lt;code&gt;8G&lt;/code&gt; 显存里，数据大多走显卡显存带宽，速度还能维持在比较可用的区间。但一旦切到 &lt;code&gt;64K&lt;/code&gt;，缓存体积继续上涨，总占用逼近甚至超过显存上限，系统就会把部分数据挤到内存里。&lt;/p&gt;
&lt;p&gt;这时候真正掉下去的，不是算力，而是带宽。&lt;/p&gt;
&lt;p&gt;也就是说，很多人看到的是“上下文翻倍后速度暴跌”，本质上其实是数据路径从显存掉到了共享内存或系统内存，推理链路不再跑在高速通道上。&lt;/p&gt;
&lt;h2 id=&#34;三64k-还能不能跑关键在-kv-cache-量化&#34;&gt;三、64K 还能不能跑，关键在 KV Cache 量化
&lt;/h2&gt;&lt;p&gt;第二个很关键的结论，是 &lt;code&gt;KV Cache&lt;/code&gt; 量化对 &lt;code&gt;8G&lt;/code&gt; 显存用户特别重要。&lt;/p&gt;
&lt;p&gt;如果不改变模型本身，只针对缓存做量化，长上下文下最直接的收益就是把缓存占用压缩下来，让原本已经溢出的那部分重新回到显存里。这样一来，&lt;code&gt;64K&lt;/code&gt; 模式虽然依然比 &lt;code&gt;32K&lt;/code&gt; 更吃资源，但至少不会直接跌进最慢的区间。&lt;/p&gt;
&lt;p&gt;换句话说：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;32K&lt;/code&gt; 更像是 &lt;code&gt;8G&lt;/code&gt; 显存的默认推荐区间&lt;/li&gt;
&lt;li&gt;&lt;code&gt;64K&lt;/code&gt; 不是完全不能跑&lt;/li&gt;
&lt;li&gt;但如果不上缓存量化，性能很容易从“能用”直接掉到“很难用”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你的目标是尽量稳定地跑长上下文，那优先级通常应该是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先确认显存是否已经逼近上限&lt;/li&gt;
&lt;li&gt;再决定是否开启 &lt;code&gt;KV Cache&lt;/code&gt; 量化&lt;/li&gt;
&lt;li&gt;最后才去继续尝试更激进的吞吐量参数&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;四gpu-占用不高不代表显卡没干活&#34;&gt;四、GPU 占用不高，不代表显卡没干活
&lt;/h2&gt;&lt;p&gt;这是一个很容易打破直觉的点。&lt;/p&gt;
&lt;p&gt;很多人看到任务管理器里 &lt;code&gt;GPU&lt;/code&gt; 使用率只有二三十，就会怀疑：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;是不是参数没设对&lt;/li&gt;
&lt;li&gt;是不是模型没真正跑到显卡上&lt;/li&gt;
&lt;li&gt;是不是显卡根本没吃满&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但这组测试给出的判断是，&lt;code&gt;llama.cpp&lt;/code&gt; 这类推理很多时候首先卡的不是核心算力，而是显存读写速度。&lt;/p&gt;
&lt;p&gt;也就是说，显卡核心可能很快就把一批计算做完了，但后面还得等下一批权重和缓存数据搬过来。于是你看到的现象就会变成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;核心占用不算高&lt;/li&gt;
&lt;li&gt;但整体速度还是上不去&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这不是显卡在偷懒，而是数据通路太窄。&lt;/p&gt;
&lt;p&gt;所以看本地大模型速度时，不能只盯着 &lt;code&gt;GPU Usage&lt;/code&gt;。显存容量、显存带宽、缓存是否溢出，往往更影响最终体验。&lt;/p&gt;
&lt;h2 id=&#34;五调大吞吐量参数确实可能再快一截&#34;&gt;五、调大吞吐量参数，确实可能再快一截
&lt;/h2&gt;&lt;p&gt;这里还做了一个思路很清晰的测试：既然显卡核心并没有完全忙满，那能不能通过调大吞吐量相关参数，让显卡一次处理更多数据，把并行能力进一步压出来。&lt;/p&gt;
&lt;p&gt;测试结果表明，这种做法确实有机会把速度再往上拉一段。&lt;/p&gt;
&lt;p&gt;但这里也有一个前提：显存还得扛得住。&lt;/p&gt;
&lt;p&gt;因为吞吐量相关参数调大之后，往往会带来额外显存占用。如果你本来就在 &lt;code&gt;64K&lt;/code&gt;、高缓存、显存见底的状态下继续往上推，就很容易出现两种情况：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;直接崩溃&lt;/li&gt;
&lt;li&gt;没崩，但被迫进入更慢的共享内存模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以更稳妥的顺序通常不是“先把参数拉满”，而是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;先守住显存边界&lt;/li&gt;
&lt;li&gt;再考虑吞吐量优化&lt;/li&gt;
&lt;li&gt;每调一步都重新看速度和稳定性&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;六cpu-线程不是越多越好&#34;&gt;六、CPU 线程不是越多越好
&lt;/h2&gt;&lt;p&gt;这也是整篇内容里最值得记住的坑点之一。&lt;/p&gt;
&lt;p&gt;很多人做本地推理调优时，容易下意识觉得线程越多越快，既然机器有那么多线程，不用满就像浪费。但实测给出的结果恰恰相反：在模型已经主要跑在显卡上的情况下，强行把 &lt;code&gt;CPU&lt;/code&gt; 线程拉高，性能反而会明显变差。&lt;/p&gt;
&lt;p&gt;原因不复杂。&lt;/p&gt;
&lt;p&gt;在全显卡运行时，&lt;code&gt;CPU&lt;/code&gt; 更像是调度者和预处理协作者，而不是主力计算单元。这时候如果开太多线程，CPU 端的线程竞争、调度切换和上下文切换开销都会变重，最终把本来应该更流畅的数据流打乱。&lt;/p&gt;
&lt;p&gt;结果就是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CPU&lt;/code&gt; 更忙了&lt;/li&gt;
&lt;li&gt;但整体速度变慢了&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以在这种场景下，默认设置或者较低线程数，往往比一味拉满更靠谱。&lt;/p&gt;
&lt;h2 id=&#34;七对-8g-显存用户更实用的一套思路&#34;&gt;七、对 8G 显存用户更实用的一套思路
&lt;/h2&gt;&lt;p&gt;如果把上面的结论压成一套更容易执行的思路，大概可以整理成这样：&lt;/p&gt;
&lt;h3 id=&#34;1-先把-32k-当成默认目标&#34;&gt;1. 先把 32K 当成默认目标
&lt;/h3&gt;&lt;p&gt;如果你用的是 &lt;code&gt;8G&lt;/code&gt; 显存显卡，先别急着追 &lt;code&gt;64K&lt;/code&gt;。&lt;code&gt;32K&lt;/code&gt; 往往是速度、稳定性和显存占用之间更现实的平衡点。&lt;/p&gt;
&lt;h3 id=&#34;2-想上-64k先处理缓存问题&#34;&gt;2. 想上 64K，先处理缓存问题
&lt;/h3&gt;&lt;p&gt;不要先想“还能不能再榨一点速度”，而是先确认 &lt;code&gt;KV Cache&lt;/code&gt; 有没有量化、显存是不是已经压线。&lt;/p&gt;
&lt;h3 id=&#34;3-不要用-gpu-占用率判断一切&#34;&gt;3. 不要用 GPU 占用率判断一切
&lt;/h3&gt;&lt;p&gt;低占用不一定代表设置错了，也可能只是显存带宽在拖后腿。&lt;/p&gt;
&lt;h3 id=&#34;4-吞吐量优化可以做但别越过显存边界&#34;&gt;4. 吞吐量优化可以做，但别越过显存边界
&lt;/h3&gt;&lt;p&gt;这类参数确实能带来收益，但前提是显存还有余量。&lt;/p&gt;
&lt;h3 id=&#34;5-cpu-线程先保守再逐步测试&#34;&gt;5. CPU 线程先保守，再逐步测试
&lt;/h3&gt;&lt;p&gt;如果模型已经基本跑在显卡上，CPU 线程并不是越高越好。先用默认值或低线程值测试，再看是否值得继续调整。&lt;/p&gt;
&lt;h2 id=&#34;结语&#34;&gt;结语
&lt;/h2&gt;&lt;p&gt;这组内容最有价值的地方，不只是给出几个测试数字，而是把一个经常被忽略的事实讲清楚了：&lt;/p&gt;
&lt;p&gt;本地大模型调优，很多时候拼的不是“有没有把所有参数开到最大”，而是你有没有搞清楚瓶颈到底在算力、显存容量、显存带宽，还是在 &lt;code&gt;CPU&lt;/code&gt; 调度。&lt;/p&gt;
&lt;p&gt;对 &lt;code&gt;8G&lt;/code&gt; 显存用户来说，真正更稳的思路通常不是硬冲最长上下文，而是先守住显存边界，再决定要不要继续往上加。&lt;/p&gt;
&lt;p&gt;如果只记一句话，那就是：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;32K&lt;/code&gt; 往往是 &lt;code&gt;8G&lt;/code&gt; 显存更稳的工作区间；&lt;code&gt;64K&lt;/code&gt; 不是不能跑，但前提是你已经把 &lt;code&gt;KV Cache&lt;/code&gt; 和显存占用管住了。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
