<?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/%E5%A4%9Agpu/</link>
        <description>Recent content in 多GPU on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Sat, 09 May 2026 15:05:41 +0800</lastBuildDate><atom:link href="https://www.knightli.com/tags/%E5%A4%9Agpu/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>llama.cpp 多 GPU 性能实测思路：2x V100 16GB 会比单卡 32GB 快吗？</title>
        <link>https://www.knightli.com/2026/05/09/llama-cpp-multi-gpu-offload-performance/</link>
        <pubDate>Sat, 09 May 2026 15:05:41 +0800</pubDate>
        
        <guid>https://www.knightli.com/2026/05/09/llama-cpp-multi-gpu-offload-performance/</guid>
        <description>&lt;p&gt;大概结论：llama.cpp 多 GPU offload 不是“多一张卡就白捡一倍性能”。如果模型本来能完整放进一张 32GB 显卡，2x V100 16GB 通常不如单张 32GB 显卡省心，甚至可能更慢；如果模型单张 16GB 放不下，双卡的主要价值是“能把模型放进 GPU”，这时收益会很明显。&lt;/p&gt;
&lt;h2 id=&#34;先分清-split-mode&#34;&gt;先分清 split mode
&lt;/h2&gt;&lt;p&gt;llama.cpp 的多 GPU 主要围绕 &lt;code&gt;--split-mode&lt;/code&gt; 和 &lt;code&gt;--tensor-split&lt;/code&gt; 使用。实际讨论性能时，先要区分几种模式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;layer&lt;/code&gt;：按层切分到不同 GPU，兼容性较好，也是多数人优先尝试的方式。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tensor&lt;/code&gt;：把张量计算拆到多张 GPU 上，更接近并行计算，但更依赖 GPU 之间的互联带宽和后端支持。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;row&lt;/code&gt;：旧的行切分方式，在不少场景里仍能看到，但新部署通常不建议优先从它开始。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;简单说，&lt;code&gt;layer&lt;/code&gt; 更像“把不同楼层放在不同卡上”，单 token 生成时不一定能让两张卡同时满负载；&lt;code&gt;tensor&lt;/code&gt; 更像“同一层两张卡一起算”，理论上更能并行，但跨卡通信会成为关键瓶颈。&lt;/p&gt;
&lt;h2 id=&#34;单卡-32gb-能放下时双-16gb-不一定更快&#34;&gt;单卡 32GB 能放下时：双 16GB 不一定更快
&lt;/h2&gt;&lt;p&gt;如果模型和 KV cache 能完整放进一张 32GB 显卡，那么单卡通常更稳，也常常更快。对 1x V100 32GB 和 2x V100 16GB 这类同代硬件来说，后者未必能赢。&lt;/p&gt;
&lt;p&gt;比较保守的预期是：2x V100 16GB 可能比单张 V100 32GB 慢 10% 到 40%，尤其是单人聊天、Continue Agent、代码问答这类一次主要生成一个回答的场景。&lt;/p&gt;
&lt;p&gt;原因不复杂：多 GPU 不是简单合并显存。按层切分时，推理会在不同 GPU 之间流转，单 token 生成阶段经常是部分 GPU 等另一部分 GPU；按张量切分时，两张卡可以一起算，但中间结果需要跨卡同步，互联带宽和延迟会直接影响吞吐。&lt;/p&gt;
&lt;p&gt;所以如果你的选择是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1x V100 32GB&lt;/li&gt;
&lt;li&gt;2x V100 16GB&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;并且目标模型单张 32GB 已经能完整放下，那么单张 32GB 往往是更舒服的选择。&lt;/p&gt;
&lt;h2 id=&#34;单卡-16gb-放不下时双卡价值很大&#34;&gt;单卡 16GB 放不下时：双卡价值很大
&lt;/h2&gt;&lt;p&gt;另一种情况完全不同：模型单张 16GB 放不下，但两张 16GB 合起来可以放下。&lt;/p&gt;
&lt;p&gt;这时双卡的价值就很直接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单张 16GB：可能需要大量 CPU offload，速度明显变慢。&lt;/li&gt;
&lt;li&gt;2x 16GB：权重尽量留在 GPU 上，速度可能比 CPU/GPU 混跑快很多。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这种场景下，2x V100 16GB 不一定比单张 32GB 快，但它可能比“单张 16GB 加大量系统内存 offload”快几倍。也就是说，双卡的第一价值不是加速，而是避免模型被迫落到更慢的系统内存里。&lt;/p&gt;
&lt;h2 id=&#34;v100-pcie-和-v100-sxm2-差别很大&#34;&gt;V100 PCIe 和 V100 SXM2 差别很大
&lt;/h2&gt;&lt;p&gt;多 GPU 推理最容易被忽略的是互联。&lt;/p&gt;
&lt;p&gt;如果是 V100 SXM2，并且机器里有 NVLink，跨卡通信带宽高很多。NVIDIA 的 V100 资料里，NVLink 互联最高可到 300GB/s。这种环境下，&lt;code&gt;tensor&lt;/code&gt; 或更高 batch 的场景才更有机会接近甚至超过单卡表现。&lt;/p&gt;
&lt;p&gt;如果是 V100 PCIe，情况就保守得多。V100 PCIe 的互联主要走 PCIe Gen3，资料里标的 interconnect bandwidth 是 32GB/s。这个带宽和 NVLink 不是一个量级，所以双卡经常出现“显存够了，但速度没有翻倍”的情况。&lt;/p&gt;
&lt;p&gt;因此判断 2x V100 16GB 值不值得，不能只看显存相加是 32GB，还要看它们是 PCIe 版还是 SXM2/NVLink 版。&lt;/p&gt;
&lt;h2 id=&#34;怎么选更实际&#34;&gt;怎么选更实际
&lt;/h2&gt;&lt;p&gt;如果模型能放进单张 32GB 显卡，优先选单卡。它的延迟、稳定性和调参成本通常更好。&lt;/p&gt;
&lt;p&gt;如果模型单张 16GB 放不下，而两张 16GB 能放下，双卡值得用。此时重点是让权重尽量留在 GPU，而不是期待性能线性翻倍。&lt;/p&gt;
&lt;p&gt;如果是 V100 PCIe 双卡，优先尝试 &lt;code&gt;--split-mode layer&lt;/code&gt;，把目标放在“能稳定跑”和“少走 CPU”上。&lt;/p&gt;
&lt;p&gt;如果是 V100 SXM2/NVLink，才更值得测试 &lt;code&gt;tensor&lt;/code&gt; 相关模式，尤其是 prefill、大 batch 或并发请求场景。&lt;/p&gt;
&lt;h2 id=&#34;什么时候买-2x16gb什么时候买-1x32gb&#34;&gt;什么时候买 2x16GB，什么时候买 1x32GB
&lt;/h2&gt;&lt;p&gt;如果你只服务一个人，主要做聊天、代码补全、Continue Agent、长上下文问答，并且目标模型能放进 32GB，那么 1x32GB 通常更值得。它少了跨卡调度，延迟更稳定，排查问题也简单。&lt;/p&gt;
&lt;p&gt;如果你已经有一张 16GB 卡，想用较低成本扩到能跑 30B、32B 或更高量化模型，2x16GB 就有意义。它不一定让 token/s 翻倍，但可以把原本必须 CPU offload 的权重留在 GPU 上。&lt;/p&gt;
&lt;p&gt;如果你准备重新采购，优先级可以这样排：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;单模型、单用户、重视响应延迟：优先 1x32GB。&lt;/li&gt;
&lt;li&gt;模型单卡放不下、预算有限：可以考虑 2x16GB。&lt;/li&gt;
&lt;li&gt;有 NVLink 或 SXM2 机器：2x16GB 的可玩性明显高于普通 PCIe 双卡。&lt;/li&gt;
&lt;li&gt;未来想跑更长上下文：不要只看权重大小，还要预留 KV cache 显存。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;layer-split-和-tensor-split-怎么用&#34;&gt;layer split 和 tensor split 怎么用
&lt;/h2&gt;&lt;p&gt;实用建议是：先用 &lt;code&gt;layer&lt;/code&gt;，再测 &lt;code&gt;tensor&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;layer&lt;/code&gt; 适合作为默认起点。它按层分配模型，兼容性较好，对 PCIe 双卡更友好。缺点是生成阶段可能更像流水线，某些时刻只有一张卡在忙，另一张卡在等。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;tensor&lt;/code&gt; 更适合互联带宽好的机器，例如 V100 SXM2/NVLink。它把同一层的部分计算拆到多张卡上，理论上更有并行空间，但跨卡同步更频繁。如果是 PCIe 双卡，&lt;code&gt;tensor&lt;/code&gt; 可能会被通信开销吃掉收益。&lt;/p&gt;
&lt;p&gt;实际测试时可以从这几组开始：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;llama-bench -m model.gguf -ngl &lt;span class=&#34;m&#34;&gt;99&lt;/span&gt; --split-mode layer --tensor-split 1,1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;llama-bench -m model.gguf -ngl &lt;span class=&#34;m&#34;&gt;99&lt;/span&gt; --split-mode tensor --tensor-split 1,1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;llama-bench -m model.gguf -ngl &lt;span class=&#34;m&#34;&gt;99&lt;/span&gt; --split-mode layer --tensor-split 1,0
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;第三条不是为了长期使用，而是给单卡结果做一个参照。这样才能看出双卡到底是更快，还是只是把显存压力分摊出去了。&lt;/p&gt;
&lt;h2 id=&#34;prefill-和-decode-为什么表现不同&#34;&gt;prefill 和 decode 为什么表现不同
&lt;/h2&gt;&lt;p&gt;本地大模型性能通常要分成两个阶段看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;prefill&lt;/code&gt;：处理输入 prompt，典型指标是 &lt;code&gt;pp512&lt;/code&gt; 这类 prompt processing 吞吐。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;decode&lt;/code&gt;：逐 token 生成回答，典型指标是 &lt;code&gt;tg128&lt;/code&gt; 这类 token generation 吞吐。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;prefill&lt;/code&gt; 更像大批量矩阵计算，batch 较大时更容易把 GPU 喂饱，也更可能从多 GPU 并行里受益。&lt;code&gt;decode&lt;/code&gt; 是一个 token 接一个 token 生成，batch 小、同步频繁，跨卡通信和调度延迟更容易暴露出来。&lt;/p&gt;
&lt;p&gt;所以你可能会看到一种结果：双卡的 &lt;code&gt;pp512&lt;/code&gt; 更好，但 &lt;code&gt;tg128&lt;/code&gt; 没明显提升，甚至更慢。对聊天和 Agent 来说，用户体感更接近 &lt;code&gt;tg128&lt;/code&gt;；对长文档导入、批量预填充、并发服务来说，&lt;code&gt;pp512&lt;/code&gt; 也很重要。&lt;/p&gt;
&lt;h2 id=&#34;kv-cache-会不会成为第二个显存瓶颈&#34;&gt;KV cache 会不会成为第二个显存瓶颈
&lt;/h2&gt;&lt;p&gt;会。很多人只算模型权重，忘了 KV cache。&lt;/p&gt;
&lt;p&gt;模型权重决定“能不能加载模型”，KV cache 决定“能不能开足上下文”。上下文越长、并发越高、batch 越大，KV cache 占用越明显。你可能遇到这种情况：模型本体能放进 32GB，但一开 32K 或 64K 上下文，显存又不够了。&lt;/p&gt;
&lt;p&gt;判断时至少要留出几块显存余量：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;KV cache&lt;/li&gt;
&lt;li&gt;CUDA graph 或后端运行时开销&lt;/li&gt;
&lt;li&gt;prompt batch 和 ubatch&lt;/li&gt;
&lt;li&gt;系统桌面、驱动和其它进程占用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果你用的是 2x16GB，显存不是一个完全等价的 32GB 大池子。某些缓冲区、KV cache 或中间张量仍然会受单卡剩余显存影响。测试长上下文时，最好直接用目标 &lt;code&gt;--ctx-size&lt;/code&gt; 和目标并发数测，而不是只看模型能不能启动。&lt;/p&gt;
&lt;h2 id=&#34;用-llama-bench-做自己的双卡测试&#34;&gt;用 llama-bench 做自己的双卡测试
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;llama-bench&lt;/code&gt; 比直接聊天更适合做硬件对比，因为它会把 prompt processing 和 token generation 拆成可比较的指标。官方 README 的默认示例就是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;llama-bench -m model.gguf
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对双 V100，可以至少测这几组：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 单卡基线&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CUDA_VISIBLE_DEVICES&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; llama-bench -m model.gguf -ngl &lt;span class=&#34;m&#34;&gt;99&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 双卡 layer split&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CUDA_VISIBLE_DEVICES&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;0,1 llama-bench -m model.gguf -ngl &lt;span class=&#34;m&#34;&gt;99&lt;/span&gt; --split-mode layer --tensor-split 1,1
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# 双卡 tensor split&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;CUDA_VISIBLE_DEVICES&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;0,1 llama-bench -m model.gguf -ngl &lt;span class=&#34;m&#34;&gt;99&lt;/span&gt; --split-mode tensor --tensor-split 1,1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;重点看两列：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pp512&lt;/code&gt;：prompt processing，长输入和批量预填充更相关。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tg128&lt;/code&gt;：token generation，单人聊天和 Agent 体感更相关。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;测试时尽量固定模型、量化格式、上下文、batch、驱动版本和 llama.cpp 版本。每组多跑几次，取中位数，比只看一次结果可靠。最后再用真实工作流跑一遍，例如 Continue Agent、OpenAI-compatible server 或你自己的 RAG 请求，因为 benchmark 好看不代表交互体验一定更好。&lt;/p&gt;
&lt;h2 id=&#34;一句话结论&#34;&gt;一句话结论
&lt;/h2&gt;&lt;p&gt;2x V100 16GB 的优势主要是显存容量，而不是必然的生成速度。模型单卡能放下时，单张 32GB 往往更快、更稳；模型单卡放不下时，双 16GB 的价值就很大，因为它能避免大量 CPU offload。至于能不能更快，关键看 split mode、batch、模型大小，以及两张 V100 之间到底是 PCIe 还是 NVLink。&lt;/p&gt;
&lt;p&gt;参考资料：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/ggml-org/llama.cpp/blob/master/tools/server/README.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;llama.cpp server README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.mintlify.com/ggml-org/llama.cpp/concepts/backends&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;llama.cpp Compute Backends&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.nvidia.com/en-gb/data-center/tesla-v100/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;NVIDIA Tesla V100&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://images.nvidia.com/content/technologies/volta/pdf/tesla-volta-v100-datasheet.pdf&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;NVIDIA V100 Datasheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
