大模型推理部署里的并行方式,经常可以先用一句话区分:

  • DP:复制模型,拆请求;
  • TP:拆一层里的矩阵;
  • PP:拆模型的层;
  • EP:拆 MoE 专家;
  • SP:拆序列长度。

这些并行策略解决的问题并不相同。有的主要提升吞吐,有的解决单卡放不下模型的问题,有的降低 activation memory,有的则是 MoE 架构天然需要的专家分布方式。

DP:Data Parallelism,数据并行

DP 是最简单的并行方式。它的做法是让每张 GPU 都保存一份完整模型,然后把不同请求分配给不同 GPU:

GPU0:完整模型
GPU1:完整模型
GPU2:完整模型
GPU3:完整模型

请求分发时可以理解为:

请求 A -> GPU0
请求 B -> GPU1
请求 C -> GPU2
请求 D -> GPU3

所以 DP 的核心是:模型不拆,数据拆

比如部署一个 7B 模型,一张 A100 就能放下。现在同时来了 100 个请求,可以启动 4 份模型:

┌─ GPU0:Model -> 一部分请求
Requests ──┼─ GPU1:Model -> 一部分请求
├─ GPU2:Model -> 一部分请求
└─ GPU3:Model -> 一部分请求

每张 GPU 都有完整权重,这就是 DP。

DP 主要提升的是吞吐量。例如:

1 GPU:1000 token/s

4 GPU DP:
理论上接近 4000 token/s

但单个请求不会因为 DP=4 就快 4 倍,因为一个请求仍然只在一张 GPU 上执行。

DP 最大的问题是:它需要每张卡都保存完整模型。例如模型权重是 70 GB,那么:

GPU0:70 GB
GPU1:70 GB
GPU2:70 GB
GPU3:70 GB

总共需要:280 GB

所以如果模型单卡根本放不下,纯 DP 没法解决。

TP:Tensor Parallelism,张量并行

TP 是大模型推理中最核心的并行方式之一。它把一个大矩阵拆到多张 GPU 上。

为什么叫 Tensor Parallel?因为 Transformer 里大量计算本质上都是矩阵乘法:

$$ Y=XW $$

比如:

X: [B, S, 8192]
W: [8192, 32768]

如果 $W$ 很大,可以把它拆开。例如 TP=4

W = [ W0 | W1 | W2 | W3 ]

分别放在:

GPU0 -> W0
GPU1 -> W1
GPU2 -> W2
GPU3 -> W3

于是每张 GPU 计算自己那部分矩阵乘法:

GPU0: X x W0
GPU1: X x W1
GPU2: X x W2
GPU3: X x W3

最后把结果拼起来,以实现一个 Layer 内部多张 GPU 一起算。在切割过程中,本质上是在做向量的并行计算,所以叫 TP。

TP 会带来大量卡间通信。计算和通信高度耦合,是 TP 的特点。TP 通常要求 GPU 间有高速互联,比如:

NVLink
NVSwitch

跨机器 TP 往往代价比较高。

PP:Pipeline Parallelism,流水线并行

PP 的思路和 TP 完全不同。一句话解释:TP 是横着切模型,PP 是竖着切模型

假设模型有 80 层,PP=4

GPU0:Layer 0~19
GPU1:Layer 20~39
GPU2:Layer 40~59
GPU3:Layer 60~79

一个请求的流动过程是:

Input
GPU0
Layer 0~19
GPU1
Layer 20~39
GPU2
Layer 40~59
GPU3
Layer 60~79
Output

这就是 Pipeline。这种实现可以让多个请求像流水线一样工作。

例如:

时间 T1:
GPU0 -> Request A

时间 T2:
GPU0 -> Request B
GPU1 -> Request A

时间 T3:
GPU0 -> Request C
GPU1 -> Request B
GPU2 -> Request A

时间 T4:
GPU0 -> Request D
GPU1 -> Request C
GPU2 -> Request B
GPU3 -> Request A

它就像工厂流水线:

工位1 -> 工位2 -> 工位3 -> 工位4

PP 最大的问题:Pipeline Bubble

PP 的最大问题是流水线气泡。

假设刚开始:

GPU0:工作
GPU1:等
GPU2:等
GPU3:等

结束阶段:

GPU0:等
GPU1:等
GPU2:等
GPU3:工作

这些空闲时间叫 Pipeline Bubble,也就是流水线气泡。

所以 PP 想提高利用率,通常要多个 batch、多个请求或 micro batch,让流水线填满。

TP 和 PP 的区别

假设有一个 80 层模型。

TP=4 时,每一层都拆成 4 份:

Layer 0 -> GPU0 GPU1 GPU2 GPU3
Layer 1 -> GPU0 GPU1 GPU2 GPU3
Layer 2 -> GPU0 GPU1 GPU2 GPU3
...

四张 GPU 在每一层都一起工作。

PP=4 时:

GPU0 -> Layer 0~19
GPU1 -> Layer 20~39
GPU2 -> Layer 40~59
GPU3 -> Layer 60~79

不同 GPU 负责不同的层。

EP:Expert Parallelism,专家并行

EP 是把不同 MoE Expert 放到不同 GPU 上。

假设一个 MoE 模型有 256 个 experts,有 8 张 GPU,EP=8,那么每张 GPU 大约保存:

256 / 8 = 32

个 Expert。例如:

GPU0:Expert 0~31
GPU1:Expert 32~63
GPU2:Expert 64~95
...
GPU7:Expert 224~255

MoE 特别适合 EP 这种排布方式。

普通 FFN 的路径是:

token
FFN
output

MoE 的路径是:

token
Router
选择 Top-K experts
Expert
output

比如一个 token:

Token A

Router 选择:

Expert 7
Expert 123

假设:

Expert 7   在 GPU0
Expert 123 在 GPU3

那么这个 token 的数据就需要发送到 GPU0 和 GPU3,算完再发送回来。

EP 最核心的通信:All-to-All

例如,GPU0 当前有:

token A -> Expert 70
token B -> Expert 130
token C -> Expert 2

但是:

Expert 70  在 GPU2
Expert 130 在 GPU4
Expert 2   在 GPU0

那么就需要:

GPU0 --token A--> GPU2
GPU0 --token B--> GPU4

其他 GPU 同样也在互相发送,于是形成:

GPU0 <-> GPU1
GPU0 <-> GPU2
GPU0 <-> GPU3
...
GPU7 <-> GPU6

这种通信就是 All-to-All。

所以 MoE 推理里面经常看到:

dispatch
all_to_all
expert compute
all_to_all
combine

完整流程可以理解成:

token
Router
TopK expert
Dispatch
All-to-All
Expert GEMM
All-to-All
Combine

TP 和 EP 的区别

TP 和 EP 非常容易混淆。

假设 Expert 0 是一个 FFN。

EP 拆的是 Expert,例如:

GPU0:Expert 0~31
GPU1:Expert 32~63

TP 拆的是 Expert 里面的矩阵:

Expert 0:

W1
拆成 4 块

GPU0 -> W1_0
GPU1 -> W1_1
GPU2 -> W1_2
GPU3 -> W1_3

所以:

EP = 专家之间拆
TP = 一个专家内部再拆

它们甚至可以一起用。

SP:Sequence Parallelism,序列并行

SP 是指沿着 sequence 或 token 维度拆 hidden states。用户输入的 token 数就是 sequence length。SP=10,可以理解为对 sequence length / 10 进行拆分。

假设:

Sequence Length = 8192

有 4 张 GPU,SP=4

GPU0:token 0~2047
GPU1:token 2048~4095
GPU2:token 4096~6143
GPU3:token 6144~8191

Transformer 内经常看到:

[B, S, H]

例如:

[1, 8192, 4096]

其中:

B = Batch Size
S = Sequence Length
H = Hidden Size

SP 拆的是 S

原始 hidden states:

[1, 8192, 4096]

SP=4 后,每张卡可能保存:

GPU0: [1, 2048, 4096]
GPU1: [1, 2048, 4096]
GPU2: [1, 2048, 4096]
GPU3: [1, 2048, 4096]

这样拆分的主要目的是减少 activation memory,特别是 Prefill 阶段。

比如:

Sequence = 128K
Hidden = 8192

hidden states 很大。如果所有 GPU 都保存完整 sequence:

每卡:[128K, 8192]

会非常占内存。如果 SP=8

每卡:[16K, 8192]

内存压力会明显下降。

SP 不能粗暴切开 Attention

对于 SP 来说,如果只是粗暴地把序列切成几段,然后每张 GPU 独立做 Attention,结果就是错的,因为 Attention 本来要求一个 token 能看到它应该看到的所有历史 token。

所以真正的 SP 并不是“每张卡只看自己的 token 然后各算各的”,而是:

在某些阶段按 Sequence 维度分片来节省 activation memory,但到了需要跨 token 交互的算子,尤其 Attention 时,通过通信把必要的信息补齐。

比方说做 LayerNorm。这些部分不需要 token-token interaction,因此非常容易沿 sequence 分:

GPU0:
token 0~2047

GPU1:
token 2048~4095

每张卡单独做:

LayerNorm

完全没有问题,因为 LayerNorm 一般是在 hidden dimension $H$ 上做:

token0 -> 自己的 4096 个 hidden 做 norm
token1 -> 自己的 4096 个 hidden 做 norm

token0 不需要知道 token1,所以这里 SP 很自然。

CP:Context Parallelism,面向长上下文的序列拆分

在涉及注意力机制的计算时,现在更多会指 Context Parallelism,也就是 CP。

例如 128K context:

GPU0: token 0~31K
GPU1: token 32K~63K
GPU2: token 64K~95K
GPU3: token 96K~127K

Attention 又必须是全局 Attention,那么就需要:

AllGather K/V

或者:

Ring Attention

或者其他 distributed attention algorithm。

可以这样理解 SP 和 CP 的对比:

Sequence Parallelism

主要目标:
拆 activation

常见场景:
LayerNorm / Residual / Dropout
和 TP 配合
Context Parallelism

主要目标:
拆超长 sequence

尤其解决:
Attention 本身的 sequence 分片

总结

DP、TP、PP、EP、SP/CP 的区别可以收束成五种拆分维度:

并行方式拆什么典型作用
DP请求 / 数据多副本提升吞吐
TP一层里的矩阵多卡共同计算一个 Layer
PP模型层把不同层放到不同 GPU
EPMoE Expert把不同 Expert 放到不同 GPU
SPSequence / token 维度降低 activation memory
CP长上下文的 sequence 分片处理 Attention 本身的序列拆分

其中 DP 不拆模型,所以单个请求不会因为 DP 增大而直接变快;TP 拆矩阵,计算和通信高度耦合;PP 拆层,会遇到 Pipeline Bubble;EP 拆专家,核心通信是 All-to-All;SP/CP 则围绕 sequence 维度,分别服务于 activation memory 和长上下文 Attention 分片。