news 2026/9/18 8:42:50

多卡推理更慢?张量并行通信开销深度解析与优化实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多卡推理更慢?张量并行通信开销深度解析与优化实践

1. 先搞清楚 Tensor Parallel 到底在并行什么

1.1 模型为什么放不进一张卡 —— 显存墙

做推理部署的人,迟早会撞上显存这堵墙。以 70B 参数量的大模型为例,哪怕用 FP8 量化,光权重就得占 70GB 左右。现在消费级显卡 24GB 是常态,数据中心里 A100/H100 大多也就 80GB,一张卡纯放权重都紧张,更别说推理过程中还得留出 KV Cache、激活值、临时缓冲区的空间。

我见过不少团队一开始的方案是“既然一张卡放不下,那就拆到多张卡上呗”。这句话听上去没毛病,但拆法有讲究。最常见的三种并行方式:数据并行(Data Parallel, DP)、流水线并行(Pipeline Parallel, PP)、张量并行(Tensor Parallel, TP)。DP 是每张卡放一份完整模型,处理不同的 batch,它解决的是吞吐问题,不解决显存问题;PP 是把模型按层切开,前一层算完传给后一层,每张卡只负责其中几层,显存压力确实下降不少,但它天然有流水线气泡,而且层与层之间是串行依赖的。

TP 的思路更激进:把某一层内部的矩阵运算切开,多张卡一起算这一层。也就是说,权重矩阵被横七竖八地拆到了多张卡上,每张卡只持有完整矩阵的一个分片。前向计算时,多张卡协同完成一次矩阵乘法,然后再把结果拼起来或者叠加起来。

听起来 TP 是最能解决显存问题的方案,也确实如此。但这里埋着一个大坑:矩阵被切开之后,卡与卡之间需要频繁同步中间结果,这个同步开销会随卡数增加而暴涨。很多人第一次跑 TP 推理时都会懵:我加了卡,速度怎么不升反降?这篇文章就把这个反直觉的现象掰开揉碎讲清楚。

1.2 TP 的两种切法:按行切与按列切

要说清楚 TP 为什么有通信开销,得先看它到底怎么切矩阵。一次典型的前向计算可以简化为 Y = X × W,X 是输入激活矩阵,W 是权重矩阵。TP 的切法有两种:按行切 W 和按列切 W。

按列切 W 比较简单。把 W 按列切成两块 W1 和 W2,分别放在 GPU 0 和 GPU 1 上。输入 X 需要完整地发给两张卡,各自计算 Y1 = X × W1,Y2 = X × W2。因为 W1 和 W2 是 W 的左右两半,所以 Y1 和 Y2 拼接起来就是完整的 Y。这个拼接动作在 All-Gather 类通信中完成,通信量等于 Y 的完整大小。

按行切 W 稍微绕一点。把 W 按行切成上下两块 W1 和 W2,分别放在两张卡上。输入 X 也要按列切成 X1 和 X2,分别送到对应的卡上。GPU 0 算 Z1 = X1 × W1,GPU 1 算 Z2 = X2 × W2。注意,Z1 和 Z2 是部分和,要得到最终结果 Y = Z1 + Z2,必须把两张卡的结果加起来。这个加法在 All-Reduce 通信中完成,通信量也等于 Y 的完整大小。

注意:现代大模型普遍采用“按行切 + All-Reduce”的方式,因为它在后续的激活函数、Dropout 等操作上更自然。但无论哪种切法,每一层 Transformer Block 里至少有一次跨卡同步,一次 All-Reduce 意味着每张卡既要发数据也要收数据,通信量随卡数线性打满。

1.3 为什么 TP 需要“全局同步”

Transformer Block 里有两个主要的矩阵运算块:Attention 的 QKV 投影和输出投影,MLP 的 up/gate 投影和 down 投影。每一处投影如果做了 TP,就需要一次跨卡同步。

以 MLP 为例:up 投影先按列切,各卡独立算完;激活函数逐元素操作,不需要通信;但 down 投影按行切,这时候必须做 All-Reduce,把两张卡的部分结果累加起来。也就是说,一个 MLP 块至少一次 All-Reduce,Attention 块至少两次。算下来,一层 Transformer 至少三次跨卡同步。

有人可能会想,All-Reduce 不就等所有卡算完,然后互相发一下数据吗?听起来很简单,但实际开销远不止“发数据”本身。All-Reduce 需要经过 Reduce-Scatter 和 All-Gather 两个阶段,每一阶段都是两两通信,还有一个隐式的全局同步屏障——所有卡必须等最慢的那张卡算完才能进入通信。

这就是问题的核心:模型被拆到多张卡上之后,计算从“单卡串行”变成了“多卡并行 + 跨卡同步”。如果计算时间降幅小于通信时间增幅,总耗时反而上升。多加 GPU,推理可能更慢——这句话不是玩笑,是实测里经常发生的事。

2. 多加 GPU 反而更慢的三个核心原因

2.1 通信才是真正的瓶颈:All-Reduce 的代价

为了说清楚这个问题,我拿一个具体例子做估算。假设我们有一个 13B 参数的模型,每层 hidden size 为 5120,MLP 的中间维度为 13824。用 FP16 推理时,一个 Token 在 MLP down 投影上的激活矩阵大小大约是 5120 × 1(单 Token 推理时序列长度视为 1)。

听起来很小对吧?5120 个元素,FP16 下才 10KB。但实际推理不会只处理一个 Token——生产环境里通常是连续批处理(continuous batching),一个 batch 可能包含几十甚至上百个序列,每个序列又有几百个 Token。假设 batch size × 序列长度 = 4096 个 Token,那么激活矩阵就是 5120 × 4096,FP16 下约 40MB。

在 8 卡 TP 配置里,down 投影的 All-Reduce 需要将这 40MB 在 8 张卡之间做归约和广播。通信量不能简单算 40MB,实际是每张卡发送约 7/8 的数据再接收 7/8 的数据,总数据量接近 70MB 级别。

拿数据说话:单张 H100 的 NVLink 双向带宽约 900GB/s,看起来很高,但 70MB 在这种带宽下也要约 78 微秒。而 13B 模型在单卡上算一个 layer 的前向,在 H100 上大概也就 100 到 200 微秒。也就是说,一次 All-Reduce 的通信时间几乎相当于一次完整计算的时间——翻一倍开销。

这里还没算通信发起时的延迟(latency)。NVLink 的点对点延迟通常在 1 到 2 微秒,看似可以忽略,但 All-Reduce 包含多个阶段,并且每层都要做,累计起来非常可观。一个 80 层的模型,每层 3 次 All-Reduce,总共 240 次,每一次 80 微秒——光通信就要 19.2 毫秒,这还不包括计算时间。

2.2 同步屏障:木桶效应被放大

TP 天然带全局同步屏障。All-Reduce 的语义是所有卡先把本地结果算完,然后才能开始归约。这意味着,如果一个 batch 里某些 Token 的 attention 计算路径特别长,或者某张卡因为显存带宽争抢而变慢,所有卡都得等它。

单卡推理时,不同 Token 之间的计算差异会被 GPU 内部的并行调度消化掉一部分。但 TP 多卡环境下,最慢的那张卡决定了整次迭代的耗时。这个现象在混合 batch 大小不均、或者序列长度差异很大的推理场景里特别明显。

我实测过一个场景:输入里有几个特别长的序列,它们需要更大的 KV Cache,attention 计算量也更大。在单卡上,有长序列的请求只是让整体延迟高一些,但如果这些长序列恰好被分配到了同一张卡上(TP 切分是按矩阵维度切的,不是按序列维度切的,所以理论上长序列的计算同样被切分到所有卡,但不同卡上 KV Cache 的显存占用、内存访问模式可能有差异),那张卡就变成瓶颈卡,整个 TP 组的耗时被拉高。

同步屏障还有一个容易被忽视的副作用:它限制了批处理带来的吞吐提升。TP 的 batch size 变大时,虽然计算时间增长,但通信量也成比例增长。在通信占比已经很高的情况下,增大 batch 带来的算力收益会被通信开销吃掉不少,这也是为什么大 batch 下 TP 扩展性更差的原因之一。

2.3 计算量没变,通信量却叠加了

关于 TP 效率,一个常见的误解是:8 张卡一起算,计算时间不是应该变成 1/8 吗?理论上确实如此。8 张卡各算 1/8 的矩阵乘法,计算时间可以接近 1/8。但总耗时是“计算时间 + 通信时间 + 调度时间”,通信时间不会因为卡变多而减少,反而会增加。

更扎心的是,计算时间不太可能真的变成 1/8。因为矩阵被切小之后,每张卡上的矩阵乘法规模变小,GPU 的利用率会下降。矩阵乘法要跑得满,需要足够的计算强度(compute intensity)。一个小矩阵的 GEMM 可能连 GPU 的 Tensor Core 都喂不饱,算力利用率只能到 40% 甚至更低。

这相当于:计算时间没有变成 1/8,可能是 1/4 或 1/5;通信时间却从 0 变成了完整的一份甚至更多。整体自然不划算。

实操心得:把模型从单卡换到 2 卡 TP,很多场景下速度是不会翻倍的,甚至下降。我见过最极端的案例:一个 7B 模型在单张 A100 上延迟 45ms,换到 8 卡 TP 后,延迟反而变成 68ms。8 张卡跑不过 1 张卡,这就是通信开销压过算力收益的典型例子。

3. 什么场景适合 TP,什么场景碰都不该碰

3.1 适合 TP 的场景特征

说了半天 TP 的坏话,但它绝不是一无是处。TP 是唯一能解决“单卡显存放不下”的并行方式,在模型大到必须跨卡时是绕不开的。

适合 TP 的第一类场景:模型大到单卡放不下,且没有量化空间。比如 70B 模型在 8 张 A100 上用 FP16 推理,一张卡 80GB 放不下完整权重,就只能用 TP 把权重分片。此时不做 TP 就没法做,属于“没得选”。

适合 TP 的第二类场景:卡间互联带宽极高,且节点内拓扑友好。8 张 H100 通过 NVLink 全互联,通信开销相对可控。相比之下,跨节点走 InfiniBand 做 TP 就非常痛苦,带宽和延迟都差一个数量级,强烈不推荐。

适合 TP 的第三类场景:单请求延迟敏感,且 batch 比较小。TP 能降低单请求的计算延迟,因为矩阵乘法被并行到多卡上。如果 batch 小到通信量相对可控,2 卡或 4 卡 TP 确实能压低延迟。但要记住边界:TP 卡数越多,边际收益越低,通常超过 4 卡就要非常谨慎。

3.2 不适合 TP 的场景特征

最不适合 TP 的场景有两个:一是模型本身单卡就能放下,二是对吞吐要求极高而延迟要求没那么苛刻。

模型单卡能放下时,TP 几乎总是纯亏。原因很简单:单卡推理没有任何跨卡通信,矩阵乘法全额利用 GPU 算力。TP 不但引入通信开销,还因为矩阵变小导致算力利用率下降,双重损失。很多人看网上说“多卡一定比单卡快”,结果是给自己找麻烦。

对吞吐要求高的场景,数据并行(DP)或张量并行 + 数据并行的混合方案通常更好。DP 的处理方式是每张卡独立跑完整模型,处理不同 batch,卡之间只需要在反向传播时同步梯度;推理时 DP 根本不需要同步,天然可扩展。如果在 DP 之上加一点 TP 来分摊显存压力,也可以,但要注意别让 TP 的通信开销反噬吞吐。

我见过一个典型案例:某个团队用 8 卡 A100 做 13B 模型的推理服务,先上了 TP=8,吞吐只有 120 tokens/s;后来改了 DP=8(每卡放一份量化后的模型),虽然显存紧张了些,但吞吐直接跳到 380 tokens/s。这就是选型带来的数量级差距。

3.3 TP、PP、DP 怎么选

三种并行方式各有适用面,合理的方案通常是组合使用,而非只用一种。

并行方式解决什么问题通信开销典型卡数适用场景
DP吞吐扩展推理无通信8 到 64模型单卡放得下,追求吞吐
PP显存扩展流水线气泡2 到 8模型按层切分,层间显存均衡
TP显存扩展 + 降低单请求延迟每层高频通信2 到 8(单节点)超大模型,卡间互联极好

实践中的通用配方:先 DP 横向扩展吞吐,再 PP 纵向切层分担显存,最后在单机内部用 TP 把单层切成更小块。比如 70B 模型做 8 卡部署,常见方案是 DP=2 × PP=2 × TP=2,既保证吞吐,又让卡间通信尽量收敛在 NVLink 域内。

需要特别提醒:TP 的卡数不要跨节点。跨节点的网络带宽再高,也远不如 NVLink,TP 的通信频率注定了它必须在物理上紧耦合的卡之间跑。

4. 实操优化:让多卡推理真正做到 1+1>1

4.1 通算重叠:把 All-Reduce 拆开

既然通信不可避免,那就想办法让通信和计算同时发生,而不是串行等待。这是 TP 性能优化里收益最大的一招。

标准 All-Reduce 的朴素实现是:全部算完 → 统一归约 → 全部广播。但 All-Reduce 本身可以分解成 Reduce-Scatter 和 All-Gather 两个阶段。Reduce-Scatter 是每张卡把本地结果按目标卡切块,发给对应卡做归约;All-Gather 是归约完成后,每张卡再把完整结果广播给所有卡。

聪明的做法是把矩阵乘法的行切分与 Reduce-Scatter 融合。比如 down 投影按行切成了 8 份,每张卡算完自己的那份后,不需要等到所有卡都算完才通信。可以先算完自己负责的那部分行,立刻把这部分结果发给目标卡,同时开始算下一个 Attention 块的 QKV 投影——这就是通信与计算的重叠。

在 PyTorch 生态里,这个优化通常由框架层完成。比如 Megatron-LM 的 Sequence Parallel 和 vLLM 的 TP 实现,都花了大量精力做通算重叠。自己做推理框架的话,最简单的切入点是检查通信是否被同步阻塞:如果 All-Reduce 是阻塞式的,后面所有计算都在等它,那就考虑把矩阵乘法切成更细粒度的 chunk,计算一个 chunk 后立刻通信这个 chunk,流水线式地重叠。

4.2 从 kernel 与框架层压开销

通信优化的另一条线是把通信次数本身变少。Transformer Block 里有几次独立的 All-Reduce,如果能把它们合并成一次,通信延迟直接减半,这就是 kernel fusion 的核心收益。

具体来说,Attention 输出投影和 MLP 的 down 投影之间,可以尝试融合。只要中间没有必须的同步操作,一次 All-Reduce 可以同时归约两个张量,代价只是通信数据量略增,但通信次数和同步屏障次数大幅下降。

vLLM 里做得更绝:它对连续的多个层做了通信合并,把跨层通信合并成更少次数的批量操作。这不是简单的框架参数调整,而是对底层通信原语的重新设计。自己做优化时,至少要做到的一点是:避免在每层内部引入多余的同步,比如不要在矩阵乘法之后立刻做 All-Reduce,再接一个只需要局部数据的操作——应该把 All-Reduce 尽量延迟到真正需要全局数据的那一刻。

框架层还有一个容易被忽视的点:通信后端的选择。NCCL 是首选,但 NCCL 的环境变量对性能影响很大。比如 NCCL_P2P_LEVEL 决定是否走 NVLink P2P,NCCL_BUFFSIZE 决定通信缓冲区大小,这些参数在 TP 场景下直接决定通信效率。用默认配置跑 8 卡 TP,和调过参数的跑,延迟可以差 20% 到 30%。

注意:NCCL 参数调优不是无脑改大就好。NCCL_BUFFSIZE 改得太大可能挤占显存,影响 KV Cache;改小了则通信吞吐上不去。我的习惯是先跑一轮基准测试,用 nvbandwidth 和 nccl-tests 摸清卡间实际带宽和延迟,再反向调参数。

4.3 实测流程与基准测试要点

做 TP 性能调优,第一步不是改代码,而是建立可复现的基准测试流程。我自己固定使用的流程分三层:

第一层,硬件摸底。用 nccl-tests 测 All-Reduce 在不同数据量下的带宽和延迟,从 1KB 测到 512MB。这一步能直观看到当前环境的通信天花板。比如数据量 40MB 时 All-Reduce 延迟 80 微秒,那后续预估推理延迟就按这个数据来,不凭感觉。

第二层,单层前向测试。构造一个 Transformer Block 的单层模型,分别测单卡和 TP 多卡下的前向时间。通过逐层分析定位是通信占比高,还是计算切分导致利用率低。我建议用 PyTorch 的 profiler 导出 kernel 级别的时间线,观察 All-Reduce 旁边是否有空白等待段。

第三层,端到端推理测试。跑真实模型和真实请求分布,记录 P50、P99 延迟和吞吐。如果 P99 明显高于 P50,大概率是某个 batch 里出现了长序列,触发了同步屏障等待。

基准测试最容易犯的错误是只看总延迟,不拆解时间组成。总延迟变差,到底是通信变差、计算变慢、还是负载不均衡?拆开看才能对症下药。我踩过一次坑:某次调 TP 参数,延迟稳中有降,但吞吐也降了,后来发现是批处理大小被悄悄改了,根本没对比到同一条基准线。

5. 常见问题与排查技巧实录

5.1 问题速查表

现象可能原因排查方法
TP 卡数增加,延迟反而上升通信占比过高 / 卡间拓扑不佳nccl-tests 测带宽,确认是否走 NVLink
某张卡显存占用明显高于其他卡权重切分不均 / KV Cache 不均profiler 查看各卡显存分配,检查切分逻辑
P99 延迟波动剧烈长序列请求触发同步屏障等待按序列长度分组压测,看延迟分布
吞吐随 batch 增大不涨反降通信量与计算量同比例增长对比不同 batch 下通信时间占比
8 卡 TP 比 4 卡 TP 更慢通信量线性增长,计算不再线性加速逐卡数测试(1/2/4/8),找拐点

具体到排查动作,推理性问题用 profiler 最快。PyTorch 的 torch.profiler 能导出每个通信算子的耗时,NCCL 的通信算子会标记为 ncclKernel_AllReduce。如果看到大量 ncclKernel 且旁边没有计算 kernel 重叠,说明通算没有重叠,需要做算子融合。

如果通信时间本身很长,先用 nvidia-smi topo 查看卡间拓扑。有些服务器是两两 NVLink 但不是全互联,TP 卡选错会导致通信走 PCIe,性能直接掉一个数量级。选卡时尽量选同一 NUMA 节点下、拓扑图上直连的卡。

5.2 容易被忽略的显存分配坑

TP 切分权重时,大部分框架按维度均分。但 Attention 里的 KV Cache 是按层分配的,不同层之间的 Cache 显存占用在不同卡上可能不均。有些模型的 embedding 和 lm_head 是共享参数的(tied embedding),TP 切分时共享权重如果没有正确复制到所有卡,会触发通信时额外的 All-Gather,拖慢速度。

还有个坑是框架层对中间缓冲区的分配。TP 推理时,每层前向都需要额外的通信缓冲区,这部分显存是隐藏开销。有些框架默认分配 2 到 4 倍模型大小的中间缓冲区,直接把 KV Cache 的空间挤掉了。遇到显存明明够但 OOM 的情况,优先检查是不是通信缓冲区吃掉了太多显存,把 NCCL_BUFFSIZE 调小试试。

5.3 我踩过的三个典型坑

第一个坑:只测吞吐不测延迟。有一次优化后吞吐涨了 15%,我正高兴,压测才发现 P99 延迟翻倍。原因是吞吐按 token 数计算,优化让并发变高,但单个请求的前向延迟因为通信串行反而变长了。推理服务既要看吞吐,也要看延迟分位数,两个指标一起看才靠谱。

第二个坑:忽略 CPU 侧的调度开销。TP 多卡推理需要 CPU 频繁发起通信原语,每个 All-Reduce 都涉及 CPU 的 launch。如果 CPU 绑定不合理,或者 numactl 没配好,GPU 的 kernel launch 跟不上,GPU 就在空转等 CPU 下发指令。后来把 CPU 绑核、设置 CUDA_LAUNCH_BLOCKING=0(默认就是异步,一般不需要改),再把 CPU 侧的 busy-loop 改成 blocking 等待,性能立刻改善。

第三个坑:序列长度对 TP 性能的放大效应。短序列时 TP 通信占比高得离谱,因为计算太小,通信延迟占主导;长序列时通信占比下降,TP 效果更好。如果生产请求大多数是短文本,TP 可能不仅没收益,还是负资产。这时候不如干脆用 DP,甚至单卡推理。

收尾:一点个人体会

装机时总有人追求“卡越多越好”,但做推理部署这几年,我最大的体会是:分布式不是灵丹妙药,它只是在你不得不跨卡时,帮你把损失降到最低的手段。TP 尤其如此——它解决了显存放不下的问题,但代价是通信和同步开销。合理评估你的模型大小、卡间互联、请求分布,再决定上不上 TP、上几卡,比盲目堆卡重要得多。

如果你正打算给推理服务加卡,我的建议是先跑一轮 nccl-tests 和单层前向基准,把通信成本和计算收益量化清楚。如果模型单卡放得下,别碰 TP;如果必须跨卡,先从 2 卡 TP 起步测试,逐步加卡找拐点,别一步到位上 8 卡。最后,所有优化都要以 P50/P99 延迟和吞吐的联合基准为准绳,任何单指标优化都可能是陷阱。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 8:41:03

开州区云计算大数据项目实施方案:架构、容量与落地

简介:《开州区云计算大数据项目实施方案》是一份面向政府信息化决策者、项目经理及云计算大数据从业者的完整项目规划文档,系统阐述了区域云计算大数据平台的建设背景、市场预测与具体实施路径,重点突出从传统终端设备向高效智能云端服务转型…

作者头像 李华
网站建设 2026/9/18 8:39:22

PDF补丁丁批量合并重命名一次搞定

PDF补丁丁批量合并重命名一次搞定 【免费下载链接】PDFPatcher PDF补丁丁——PDF工具箱,可以编辑书签、剪裁旋转页面、解除限制、提取或合并文档,探查文档结构,提取图片、转成图片等等 项目地址: https://gitcode.com/GitHub_Trending/pd/P…

作者头像 李华
网站建设 2026/9/18 8:37:41

SPSS分段回归实操:从折线原理到变量构造与结果解读

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 8:37:00

AI生成代码占八成,如何守住代码评审与生产验收?

1. "80%的代码是AI写的"这句话,拆开看每个字周五晚上赶迭代,你在评审队列里翻到第 17 个 PR,提交信息写着feat: 补全订单状态机,diff 一千两百行,注释工整得像教科书,变量名比你自己起的还克制。…

作者头像 李华
网站建设 2026/9/18 8:36:27

特高压直流输电系统PSCAD仿真建模关键技术解析

1. 项目概述:特高压直流输电系统仿真建模在电力系统仿真领域,特高压直流输电(UHVDC)建模一直是个既关键又具有挑战性的课题。我最近刚完成一个800kV特高压直流输电系统的完整PSCAD模型搭建项目,这个模型不仅包含了换流…

作者头像 李华
网站建设 2026/9/18 8:35:44

Comsol无模型仿真在等离子体空气反应中的应用

1. 等离子体空气反应研究背景与价值等离子体与空气的相互作用是一个充满魅力的研究领域。在工业废气处理、医疗器械消毒、空气净化等场景中,等离子体技术都展现出了独特优势。与传统化学方法相比,等离子体处理具有反应速度快、无二次污染、能耗相对较低等…

作者头像 李华