昇腾社区首页
中文
注册

DataParallelism数据并行

概述

AscendSpeed提供两种数据并行方式,分别是Local Distributed Data Parallel(以下简称为LocalDDP)和torch Distributed Data Parallel(以下简称torchDDP)。

  • LocalDDP:LocalDDP定义使用了连续缓存空间来存储fp32的累积梯度,如此操作是可以减少碎片空间的。此外还包含缓存清零,all-reduce梯度数据功能。
    class DistributedDataParallel(DistributedDataParallelBase):
        """DDP with contiguous buffers options to storre and accumulate gradients.
        def __init__(self, module,
                     accumulate_allreduce_grads_in_fp32,
                     use_contiguous_buffers):

    参数说明:

    • module:输入的模型
    • accumulate_allreduce_grads_in_fp32:设置为true则使得梯度累积与all-reduce过程均使用fp32
    • use_contiguous_buffers:若上述参数置为true则该参数也置为true来表示使用连续的空间存储梯度
  • torchDDP:torchDDP即PyTorch框架自带的DDP功能,使用torch.nn.parallel.distributed.DistributedDataParallel进行调用,实际使用RingALLReduce实现AllReduce算法。此外torchDDP设计最核心的机制就是Gradient Bucketing。梯度分桶的做法将模型的Model的参数逆序插入每个Bucket中,当一个Bucket的参数的梯度都已经更新时,开启Allreduce,向另一个节点的对应Bucket传递梯度,这样也同时实现了异步AllReduce。

两者都存在hook机制,保证原有的训练过程不受影响:程序提供hook接口,用户可以写一个hook函数,然后钩在hook接口,即程序的主体上从而可以插入到中间执行。DDP使用hook技术把自己的逻辑插入到module的训练过程中去。parameter在反向梯度计算结束后提供了一个hook接口。DDP把Ring-Reduce的代码写成一个hook函数,插入到这里。每次parameter的反向梯度计算结束后,程序就会调用这个hook函数,从而开启Ring-Reduce流程。

功能使用

训练脚本参数配置示例,加粗部分为DDP功能配置参数示例:

python pretrain_gpt.py \
   --DDP-impl local \
   --num-layers 30 \
   --hidden-size 4096 \
   --num-attention-heads 32 \
   --micro-batch-size 4 \
   --global-batch-size 8 \
   --seq-length 2048 \

通过修改输入参数--DDP-impl的值来确定使用何种类型的DDP,可选值“torch”和“local”.其中与localDDP相关的输入参数--no-contigous-buffers-in-local-ddp若设置了则表示在local DDP中不使用连续存储空间。

定义使用DDP时,在ascendspeed/utils.py文件下,构造定义模型
def unwrap_model(model, module_instances=(torchDDP)):
    return_list = True
    if not isinstance(model, list):
        model = [model]
        return_list = False
    unwrapped_model = []
    for model_module in model:
        while isinstance(model_module, module_instances):
            model_module = model_module.module
        unwrapped_model.append(model_module)
    if not return_list:
        return unwrapped_model[0]
    return unwrapped_model