并行计算基础:任务并行、数据并行、模型并行

聊到分布式训练,绕不开一个核心问题:到底怎么把计算拆开?

我见过不少新手,一上来就急着搭多卡环境,结果发现性能还不如单卡。为什么?说白了,就是没搞懂三种并行模式的区别。你想想看,连怎么拆都没想明白,怎么可能拆得好?

今天咱们就把这三种模式掰开揉碎,讲清楚它们的本质区别。

任务并行:各干各的,互不打扰

任务并行,是最直观的一种并行方式。它的核心思想很简单:把一个大任务拆成多个独立的小任务,每个计算单元负责一个子任务。

举个例子,假设你要训练一个模型,同时要做数据预处理、超参数搜索、模型评估。这三件事彼此独立,完全可以扔给三张卡同时跑。

核心特征:任务之间没有数据依赖,不需要频繁通信。

我在项目中遇到过一种情况:团队把数据预处理和模型训练放在同一张卡上,结果预处理占用了大量显存,模型训练反而跑不动了。后来改成任务并行,预处理单独用一张卡,问题就解决了。

任务并行的问题也很明显——负载均衡难做。有的任务跑得快,有的跑得慢,快的卡只能干等着。我曾经调试过一个推理服务,三张卡做任务并行,结果一张卡负载80%,另外两张卡只有20%。嗯,这种场景下任务并行反而不如单卡。

数据并行:一份数据,多份模型

数据并行,是目前最常用的并行模式。它的逻辑是:每个计算单元都有一份完整的模型副本,但只处理一部分数据。

怎么理解?

假设你有4张卡,训练数据有1000个样本。数据并行会把数据切成4份,每张卡分250个样本。每张卡用自己的数据跑前向和反向,算出梯度。然后所有卡的梯度做一次同步(AllReduce),更新模型参数。

# 伪代码示意
for each batch:
    data_chunk = split_data(data, num_gpus)
    for gpu_id in range(num_gpus):
        loss = model(data_chunk[gpu_id])
        grad = compute_gradient(loss)
    all_grad = all_reduce(grad)  # 梯度同步
    model.update(all_grad)

我的建议:数据并行适合模型能塞进单卡显存的情况。如果模型太大,一张卡放不下,那就别硬上数据并行。

数据并行有个坑——通信开销。每步都要同步梯度,卡越多,通信时间越长。我记得有一次用32张卡跑数据并行,结果通信占了总时间的40%。后来改用梯度累积,每累积几步再同步,才把效率提上来。

你可能会问:那数据并行和任务并行有什么区别?

区别很明显:数据并行里,所有卡跑的是同一个模型,只是数据不同;任务并行里,每张卡跑的是不同的任务。数据并行需要频繁通信(梯度同步),任务并行基本不需要通信。

模型并行:一张卡放不下,那就拆开放

模型并行,解决的是模型太大,单卡显存放不下的问题。

它的做法是:把模型的不同层或不同参数分配到不同的卡上。每张卡只负责模型的一部分计算。

举个例子,一个Transformer模型有12层。你可以把前4层放在卡0,中间4层放在卡1,后4层放在卡2。数据流从卡0进入,经过卡0的计算后,把中间结果传给卡1,再传给卡2,最后输出。

注意:模型并行有严重的串行依赖。卡2必须等卡1算完,卡1必须等卡0算完。这种流水线式的执行方式,会导致GPU利用率不高。

我曾经调试过一个GPT-3规模的模型,用模型并行把参数分散到8张卡上。结果发现,大部分时间卡都在等待数据传递,真正在计算的时间不到50%。后来我们引入了流水线并行(Pipeline Parallelism),把数据也切成微批次,让不同卡同时处理不同微批次,才把利用率提上去。

模型并行和数据并行可以混用。比如,模型太大,先用模型并行把参数分散到4张卡上;然后数据量太大,再用数据并行把数据分散到多组这样的4卡集群上。这种混合并行,是大型模型训练的标配。

三种模式的本质区别

说了这么多,咱们用一张表总结一下:

维度 任务并行 数据并行 模型并行
拆分对象 任务/功能 数据 模型参数/层
通信频率 低(几乎不通信) 高(每步同步梯度) 中(层间传递激活值)
适用场景 多任务、预处理、评估 模型可放入单卡 模型超大,单卡放不下
负载均衡 难(任务耗时不同) 易(数据均匀切分) 中(层计算量不同)
典型瓶颈 任务调度 通信带宽 串行依赖

它们的本质区别,说白了就是一句话:你拆的是什么?

  • 拆任务 → 任务并行
  • 拆数据 → 数据并行
  • 拆模型 → 模型并行

实际工程中,这三种模式很少单独使用。我建议你从数据并行入手,因为它最容易理解和实现。等遇到模型放不下的情况,再引入模型并行。至于任务并行,更多是用在训练之外的数据处理、模型评估等环节。

核心原则:先搞清楚瓶颈在哪。是数据太多?还是模型太大?还是任务太杂?对症下药,才能选对并行模式。

知识体系图

下面这张图,帮你理清三种并行模式的关系和适用场景:

并行计算三种模式 并行计算 任务并行 数据并行 模型并行 拆分对象:任务/功能 通信频率:低 适用:多任务、预处理 拆分对象:数据 通信频率:高 适用:模型可放入单卡 拆分对象:模型参数/层 通信频率:中 适用:超大模型 实际工程中,三种模式常混合使用

这张图把三种模式并列展示,方便你对比。记住,没有银弹。选哪种模式,取决于你的具体场景。

好了,三种并行模式的核心区别就讲到这里。下一节咱们会深入数据并行的实现细节,包括AllReduce的原理和优化技巧。到时候见。

可可精品资料库