一台机器有 8 张 GPU,模型用 2 张就能装下。接下来把 Tensor Parallel 从 2 调到 8,用户收到回答就会更快吗?
这个问题不能靠显存总量回答。Tensor Parallel(张量并行,简称 TP)让多张卡共同执行同一层,每张卡只保存、计算其中一部分。省下的是每卡的权重和部分计算,新增的是各卡之间反复交换结果的代价。一次请求会经过许多层。生成下一个 Token 时,这些协作还要再发生。
本文沿这个取舍展开:先把两张卡上的运算算清楚,再看模型结构和硬件连接怎样改变收益,最后给出一份可以填写的 8 卡对照实验记录。文中的矩阵是可手算示例,配置比较是实验设计,均不代表作者做过 GPU 性能实测。
两张卡如何共同算出一层
先看一个线性变换 Y = XW。这里约定 X 是行向量,W 的行对应输入特征、列对应输出特征。实际框架存储权重时可能采用转置布局。
设输入是 X = [1, 2],权重为:
W = [[1, 2, 3, 4],
[5, 6, 7, 8]]
完整结果为 [11, 14, 17, 20]。如果按输出特征把 W 切成左右两块,GPU 0 算出 [11, 14],GPU 1 算出 [17, 20]。这叫 Column Parallel:每张卡拿到相同输入,生成不同部分的输出。
下一步是否必须把两份输出拼到一起?取决于后续运算能否直接消费分片。逐元素激活可以在各卡本地完成。如果紧接着的线性层恰好沿输入维度切分,也可以直接接上。
为方便手算,先省略激活,令下一层权重是:
V = [[1], [2], [3], [4]]
GPU 0: [11, 14] × [[1], [2]] = 39
GPU 1: [17, 20] × [[3], [4]] = 131
完整结果: 39 + 131 = 170
这一步叫 Row Parallel。两张卡得到的都是同一个输出位置的部分和,不能把 39 和 131 拼成两个输出。必须求和,才能得到正确的 170。
AllReduce 正是这种“求和后让参与者都得到结果”的集合通信操作。AllGather 则是收集各卡分片,二者不能互换。NCCL 官方给出了这两种操作的区别。NCCL 集合通信定义
复制输入 X
├─ GPU 0:第一层左半权重 → 本地激活 → 第二层上半权重 → 部分和
└─ GPU 1:第一层右半权重 → 本地激活 → 第二层下半权重 → 部分和
↓
求和,得到输出
这样配对的意义是避开中间一次不必要的完整聚合,而不是消除所有通信。Megatron-LM 原论文 Figure 3 就展示了这种 MLP 与 Attention 的配对方式。经典结构中,每个 Transformer 层的前向包含两次 AllReduce。这里引用的是该论文的布局,不将这个次数推广到所有现代模型和内核。Megatron-LM 原论文,第 3 节与 Figure 3
Attention 中也可以让不同卡处理不同注意力头,再在输出投影处合并。到这里,TP 的运行关系已经明确:这些卡在合作完成一批请求,不是每张卡独立接走一批用户。

每张卡少算了,整个请求为什么还可能更慢
把一层耗时粗略拆开:
层耗时 ≈ 分片后的本地计算 + 关键路径上的通信 + 启动、同步与不均衡
这只是诊断模型,不能直接用“单卡耗时除以 TP”预测结果。缩小矩阵可能改变内核效率。通信有固定延迟,也有随数据量增长的传输开销。某个 Rank(通信组中的一个进程)晚到,其他卡就需要等它。
还要区分推理的两段工作。Prefill 是处理已有输入,长输入常带来较大的矩阵计算。Decode 是继续生成,低并发时每一步的计算规模较小。扩大 TP 后,本地工作减少,通信和同步未必同比减少,因此短请求、小批量 Decode 尤其值得单独测。
这不等于“Decode 必然不适合 TP”。TP 同样能分摊权重读取,较大的批量也会改变计算与通信的比例。究竟节省了多少计算、显存读取,新增了多少等待,需要用所选模型和请求分布测量。
有一个容易漏掉的变化:假设两张卡已经足以容纳完整工作负载,一台 8 卡机器既可以部署一份 TP=8 副本,也可以部署四份 TP=2 副本。后者的每个副本可以独立接请求。前者的八张卡仍共同处理同一批请求。
但四份副本并不保证四倍吞吐。请求路由可能不均匀,每份副本的批量可能变小,前缀缓存也可能分散。大 TP 副本可能因更大容量、更好的批处理或更低单请求延迟而胜出。要比较的是同一台机器在用户等待目标内完成了多少请求,而不是某一个实例的峰值 Token/s。
权重变小,不代表所有显存都按比例变小
将全部显存直接除以 TP,会在 KV Cache 上遇到一个具体反例。
KV Cache 保存已处理 Token 的注意力键值,避免逐步生成时重复计算。采用 GQA(分组查询注意力)的模型,多个查询头共享更少的 KV 头。假设一个模型有 32 个查询头、8 个 KV 头,且实现支持所选切分度,那么按 KV 头分片时:
| TP | 每卡查询头 | 每卡 KV 头 | KV 分片意味着什么 |
|---|---|---|---|
| 4 | 8 | 2 | KV 头可继续分摊 |
| 8 | 4 | 1 | 每卡已经只有一个 KV 头 |
| 16 | 2 | 1 | 在采用复制的实现中,每个 KV 头由两个 Rank 持有 |
这是结构示例,不指向某个已部署模型。在上述布局下,TP 从 8 加到 16,查询头继续分摊,每卡 KV 头数却没有再减半。
vLLM 的 QKVParallelLinear 文档明确说明:当 KV 头少于查询头时,查询头分片而 KV 头可能复制。部署时应核对目标版本的模型实现,不能把这个行为推广到所有注意力架构。vLLM QKVParallelLinear
因此,容量估算至少分成三项:可分片权重、按实际布局保存的 KV Cache、每 Rank 额外开销。通信缓冲区、运行时上下文和工作区都需要留余量。先确认模型的查询头、KV 头、量化布局与 TP 支持范围,再用启动日志和目标上下文、并发下的压力结果确认容量。仅模型加载成功,还没有证明业务负载装得下。
这也改变了扩卡判断:如果 OOM 的主要增量来自 KV Cache,新增 TP 又没有减少每卡 KV 头数,那么调整上下文、并发或受支持的 KV 精度,可能比继续增加 TP 更直接。精度变化需要单独验证输出质量。

A6000 的双卡 NVLink,不等于八卡高速全互联
NVIDIA RTX A6000 单卡提供 48 GB 显存,官方 NVLink Bridge 连接的是两张 A6000。不能把它理解成任意八张卡之间都具有同样的互联路径。NVIDIA RTX A6000 产品说明
同一台服务器中,某两卡可能通过 NVLink 连接,另两卡之间需要经过 PCIe Switch 或 CPU 之间的互联。实际是否安装桥接器、卡插在哪里,都要查看机器。
nvidia-smi topo -m
nvidia-smi topo -p2p r
nvidia-smi topo -p2p w
第一条查看拓扑矩阵及 CPU/NUMA 关联,后两条查询 GPU P2P 读写能力。NV# 表示 NVLink 路径,PIX、PXB、PHB、SYS 描述不同 PCIe/主机路径。它们帮助确定候选分组,不能直接当成实测带宽排名。NVIDIA nvidia-smi 拓扑说明
如果拓扑证实 0、1 是一对高速连接的卡,可以先以这组作为 TP=2 候选。把 TP 扩成 4 或 8 时,通信组可能跨过原来的快速边界。即使每张卡承担的计算更少,层间等待仍可能增加。
无高速互联的机器也值得比较按层切分的 Pipeline Parallel(流水线并行,PP)。vLLM 当前扩展文档对无 NVLink 的场景专门提出了 PP 选项。它减少切分层内部的通信,但有流水线气泡、阶段不均衡和不同延迟代价。应把它列为候选,不把它当成无条件赢家。vLLM Parallelism and Scaling

把八张卡的选择变成一次可复查的实验
先找出支持目标模型、且能容纳目标上下文与并发的最小 TP。它是实验起点,不是性能最优值。对于能够在 TP=2 上稳定容纳目标工作负载的模型,比较下列整机布局:
| 布局 | 独立副本数 | 优先观察的代价 |
|---|---|---|
| 四份 TP=2 | 4 | 路由不均、缓存分散、单副本批量变小 |
| 两份 TP=4 | 2 | 是否跨快速互联域,延迟改善能否补偿副本减少 |
| 一份 TP=8 | 1 | 更多 Rank 的同步、容量收益和单副本故障影响 |
如果 TP=1 也能容纳目标负载,应增加八份单卡副本的基线。如果至少需要 TP=4,则不能把无法正常运行的 TP=2 当作性能候选。涉及 MoE、流水线或其他并行维度时,也不要用这张只讨论 Dense TP 副本的表替代完整设计。
单实例启动可从以下结构开始。假设模型已经下载到指定目录,设备 0、1 的分组来自真实拓扑,命令只展示 TP 参数,不是一份完整部署配置:
CUDA_VISIBLE_DEVICES=0,1 vllm serve /path/to/local-model \
--tensor-parallel-size 2
实际测试需固定引擎版本、权重版本、量化与 KV 精度、最大上下文、生成参数和调度配置。四个副本还需要互不重叠的 GPU 分组、不同监听端口和明确的请求路由。vLLM 单节点部署说明
分两轮比较,才能区分收益来源。
第一轮只测单副本的低并发延迟:同样的输入和输出长度,分别测短输入与长输入,记录首 Token 延迟 TTFT、后续 Token 的输出间隔,以及服务端可获得的 Prefill/Decode 指标。客户端 TTFT 包含排队等开销,不能直接叫 Prefill 计算时间。
第二轮启用整机全部副本,用同一入口、同一请求序列和同一总到达速率逐档加压。给四副本布局的每个副本各发一份完整流量,会把总负载变成四倍,失去可比性。固定缓存冷/热起点与路由规则,记录实际输入输出长度。相同生成上限不保证实际输出一样长。
定义本次测试的 Goodput 为:单位时间内,成功完成且同时满足预先约定 TTFT 与逐请求平均 TPOT 上限的请求数。其中 TPOT 是首 Token 之后的平均每 Token 时间。输出不足两个 Token 的请求单独统计。若业务关心流式卡顿,再另报相邻 Token 间隔的长尾,不能让平均值掩盖停顿。
下面是一份待填写记录。所有结果目前都是未测,不是跑分结论:
模型/权重版本、引擎/驱动版本:
GPU 型号、分组、拓扑文件:
布局(副本数 × TP)、路由与缓存起点:
精度、上下文、调度配置:
请求集、到达速率、实际输入/输出长度分布:
预热规则、观测窗口、重复轮次:
TTFT P50/P95/P99:未测
逐请求平均 TPOT P50/P95/P99:未测
成功请求数、超时数、失败数、结束时仍未完成数:未测
满足两项等待目标的请求数 / 观测窗口秒数:未测
每卡显存峰值、整机功耗(若可采集):未测
异常 Rank 与日志/trace 文件:未测
所有布局采用相同的预热、计时与结束处理规则。失败、超时和未完成请求不能从报告里消失。先重复测出差异是否稳定,再延长运行以观察容量和抖动。短时峰值不足以决定常驻服务配置。
如果扩大 TP 后更慢,下一步是沿证据缩小范围:短输入 Decode 恶化而长输入改善,优先查看通信与每 Rank 工作粒度。换到局部 GPU 组后改善,优先检查拓扑。单副本表现正常但整机 Goodput 下降,则继续看路由、批量和共享资源争用。这些是诊断方向,必须用日志或性能剖析证实,不能仅凭 GPU 利用率归因。
最终留下的应是一句有适用范围的选择:在这份模型、拓扑、请求分布和等待目标下,某种布局的有效完成量更高,且错误与长尾可接受。TP 的职责是让多张卡协同完成模型计算。增加到多少张,要由这次比较回答。
