一个常见说法:3 卡跑不了 vLLM,只能跑 llama.cpp;3 卡通信损失可接受,4 卡就不行了,除非有高速互联。这话大方向没错,但魔鬼都在细节里。今天把这件事彻底讲清楚,最后再看一个把两种并行路线同时实现的实战案例------纯 .NET 推理引擎 TensorSharp。
一、vLLM 为什么"歧视"3 卡?
很多人觉得 vLLM 硬性规定张量并行(Tensor Parallelism)只能是 1、2、4、8 卡------这个理解其实不准确。
vLLM 的真实约束只有一条:
Attention Head 数量(以及 KV Head 数量)必须能被 TP size 整除。
那为什么实践中就变成了"只能 1/2/4/8"?因为主流模型的头数几乎都是 2 的幂:
| 模型 | Attention Heads | KV Heads | TP=3 可行? |
|---|---|---|---|
| Llama-3-70B | 64 | 8 | ❌ 直接报错 |
| Qwen2.5-72B | 64 | 8 | ❌ 直接报错 |
| Mistral-7B | 32 | 8 | ❌ 直接报错 |
64、32 这些数字除以 3 除不尽,--tensor-parallel-size 3 会直接抛 ValueError,于是 6 卡也不行,实际效果就退化成了"只能 1/2/4/8"。
结论:这是整除约束,不是框架写死的限制。 如果哪天遇到头数能被 3 整除的模型,vLLM 跑 3 卡完全没问题。
二、llama.cpp 为什么对卡数无所谓?
关键在于切分方式完全不同。
llama.cpp 默认采用 Layer Split(按层切分):
- 每张卡拿连续的若干层;
- 层与层之间只传一次隐状态激活值,量级只有几百 KB 到几 MB;
- 对互联带宽几乎没要求,普通 PCIe 绰绰有余。
这才是"3 卡能跑 llama.cpp"的真正原因------不是"3 卡通信损失可接受",而是 layer split 模式下通信量本来就小到可以忽略。
三、"3 卡行、4 卡不行"?这个阈值其实不成立
这是流传最广、也最容易误导人的一个说法。拆开看:
对 llama.cpp(layer split)
4 卡和 3 卡的通信量几乎一样低------仍然只在层边界传激活值。4 卡没问题,6 卡、8 卡也一样没问题。唯一的瓶颈是显存够不够分,而不是通信。
对 vLLM(tensor parallel)
真正的悬崖不在 3→4,而在互联类型:
- TP 模式每一层都要做 all-reduce,通信频繁且量大;
- 在 PCIe 下,2 卡就开始明显掉速;
- 4 卡以上基本必须 NVLink / NVSwitch 才有意义。
所以"除非高速互联"这个判断是对的,只是门槛比想象中来得更早------不是 4 卡才需要,而是 2 卡以上就明显受益。
四、一张图总结

五、实战案例:TensorSharp------同一个引擎里的两种切分
前面讲的还是"两个引擎两种路线",有没有一个引擎把两条路都实现了,可以直接对比?有------TensorSharp,一个纯 .NET 实现的 GGUF 推理引擎,性能上和 C++ 手写优化的 llama.cpp 互有胜负(CUDA prefill 最高快 1.28×,Vulkan decode 最高快 1.21×)[[1]](#[1])。
它对多卡的处理方式,简直就是本文论点的活体演示:
默认:Layer Split,卡数随意
权重默认按层自动切分到所有可见 GPU ------3 卡、5 卡、7 卡都行,没有任何整除要求。官方的一个标志性测试就是在 3 张 RTX PRO 6000 上跑 744B 参数的 GLM-5.2 MoE:layer split + CPU MoE offload(把 92% 的专家权重放内存),prefill 2048 tokens 跑出 918.9 tok/s,反超 llama.cpp 的 763.1 tok/s [[1:1]](#[1:1])。
3 卡、PCIe 时代的常识告诉我们这"不该"跑得动------但 layer split 下卡数本来就不是变量,这就是最直接的证据。
可选:--tp N,但要面对真实代价
TensorSharp 也提供 Megatron 风格的张量并行(列/行并行 + 分层 AllReduce),支持单机多卡和跨机 TCP 集群[[1:2]](#[1:2])。但它的官方基准数据恰恰暴露了 TP 的软肋:
| 场景 | TP=2 相对单卡加速 |
|---|---|
| Gemma 4 E4B decode | 1.39× |
| Muse-Glimmer 30B decode | 1.57× |
| Muse-Glimmer 30B prefill | 1.34× |
理想情况下 2 卡应该是 2×,实际只有 1.4× 左右------消失的那 0.6× 就是 all-reduce 通信和同步开销。这正是"TP 对互联敏感"的量化体现。
更有意思的是它的跨机方案:多节点 TP 走普通 TCP 网络 ,在没有 CUDA P2P 时还会自动回退到主机内存中转[[1:3]](#[1:3])。工程上能跑,但性能显然要靠真正的硬件互联(NVLink 级别)来救------互联质量决定 TP 上限,这和前面 vLLM 一节的结论完全一致。
六、实操建议
- 卡数是 3 的倍数或奇数卡 → 优先 layer split 路线的引擎(llama.cpp,或 .NET 技术栈下的 TensorSharp),别跟 vLLM 的整除约束较劲;
- 卡数是 2/4/8 且模型头数匹配 → vLLM /
--tp N可以上,但注意互联:PCIe 环境控制卡数,有 NVLink 再放开; - layer split 多卡部署时,重点调的是显存分布和 prompt processing 阶段瓶颈(TensorSharp 这类引擎还可以叠加 CPU MoE offload 进一步省显存),而不是纠结 3 卡还是 4 卡。
一句话总结:layer split 对卡数免疫,tensor parallel 对互联敏感------决定你能不能跑、跑得快的,从来不是"3 还是 4"这个数字本身。