目录

Chunked Pipeline Parallelism

记录一个优雅的大模型 prefill 超长上下文部署方案 Chunked Pipeline Parallelism,这个方案是 SGLang 博客 (opens new window) 中的一部分。

这篇文章偏随笔,不做完整介绍,细节请自行展开或结合 AI 食用。

# 1. Chunked Prefill

Chunked Prefill 就是把 prefill 的序列进行分块,分多次完成推理。

Original: Iter0 [ABCDEFGHIJKLMNOPQRSTUVWXYZ]

Chunked Prefill: Iter0 [ABCDEFGH] Iter1 [IJKLMNOP] Iter2 [QRSTUVWX] Iter3 [YZ]

# 2. Sequence Parallelism

我们有很多个节点,面对超长上下文推理,该怎么发挥多节点的优势呢?一个容易想到的做法是序列并行 Sequence Parallelism。

将 prefill 的序列进行分块,发给各个节点同时进行推理。

Original: rank0 [ABCDEFGHIJKLMNOPQRSTUVWXYZ]

Sequence Parallelism: rank0 [ABCDEFGH] rank1 [IJKLMNOP] rank2 [QRSTUVWX] rank3 [YZ]

但是我们知道 Attention 要在 Sequence Length 维度进行 reduce 操作,导致 Sequence Parallelism 会有通信代价。

# 3. Pipeline Parallelism

流水线并行 (Pipeline Parallelism) 是将大模型的 transformers 部署到多个节点上,激活值就会在多个节点上流动。

Original: rank0 [layer0 -> layer1 -> layer2 -> layer3]

PP: rank0 [layer0] -> rank1 [layer1] -> rank2 [layer2] -> rank3 [layer3]

当然在 rank1 推理时,rank0 也不能让它闲着,它可以同时进行下一批数据的推理。这样每个节点就会像工厂流水线一样运作起来。

l = layer, b = batch
rank0 [l0×b0 -> l0×b1 -> l0×b2 -> l0×b3]
rank1 [         l1×b0 -> l1×b1 -> l1×b2 -> l1×b3]
rank2 [                  l2×b0 -> l2×b1 -> l2×b2 -> l2×b3]
rank3 [                           l3×b0 -> l3×b1 -> l3×b2 -> l3×b3]

流水线并行虽然能保证吞吐,但是对延迟没有优化效果。

# 4. Chunked Pipeline Parallelism

将上面的三个方案结合一下,我们得到了 Chunked Pipeline Parallelism 方案。

像 Pipeline Parallelism 那样将 layers 分散在多个节点上;像 Chunked Prefill 那样对序列分块,作为 Pipeline Parallelism 的多个 batch。

l = layer, b = batch

Original Sequence: [ABCDEFGHIJKLMNOPQRSTUVWXYZ]

Chunked Sequence: b0 [ABCDEFGH] b1 [IJKLMNOP] b2 [QRSTUVWX] b3 [YZ]

rank0 [l0×b0 -> l0×b1 -> l0×b2 -> l0×b3]
rank1 [         l1×b0 -> l1×b1 -> l1×b2 -> l1×b3]
rank2 [                  l2×b0 -> l2×b1 -> l2×b2 -> l2×b3]
rank3 [                           l3×b0 -> l3×b1 -> l3×b2 -> l3×b3]

看起来就是很自然的方案,但是它能利用多节点的性能,同时避免了 Sequence Parallelism 的 Attention 通信开销。

可以说是非常优雅地解决了时延问题。