顾名思义,分布式并行计算就是在单台机器多个GPU(单机多卡) 上,或者多台机器多个GPU(多机多卡) 上进行并行计算。
分布式计算带来了两个好处:
- 降低了 GPU 的显存压力。一块普通的 GPU 显存只有16个G,好一点的 3090Ti, 4090Ti 也就24个G。再计算下参数占的内存:如果以32位浮点数存储参数的话,一个参数占 4 Bytes;一百万参数大约占 4 MB。实际运行模型时,不光需要存储参数,还有梯度、中间值、优化器的状态需要存储,一百万参数的模型实际需要占用约 12 MB。现在的神经网络参数动辄上亿。根据以上的计算,一个10亿参数的模型大约需要 12G 显存,这还没有算数据占的空间。
- 利用多个 GPU 的算力,加速计算。以 CLIP 模型举例,训练包含最大 Vision Transformer 的模型需要在 256 块 V100 GPU 上跑 12 天。如果要在单块 GPU 上跑,就算显存允许,也要跑到地老天荒了。
ps: 为了节约显存,还可以使用 Pytorch AMP:Pytorch AMP——自动混合精度训练
可以把分布式计算分为数据并行和模型并行。模型并行又可以分为张量并行和流水线并行。
- 数据并行(Data Parallelism):在不同 GPU 上运行不同的 batch data
- 张量并行(Tensor Parallelism):将单个数学运算(如矩阵乘法)拆分到不同的 GPU 上运行
- 流水线并行(Pipeline Parallelism):在不同 GPU 上运行模型的不同层
以数据并行为例。以现在庞大的训练数据,单张 GPU 的显存大概率放不下,那么 GPU 要经常与 CPU 进行数据交换(CPU 进一步要与硬盘进行数据交换),数据传输成本很高。
如果把数据切分成 1000 份部署在 1000 张 GPU 上,假设此时的数据量允许在单张 GPU 上训练模型。那么这将大大加速模型训练——不止是 GPU 并行计算带来的加速,还有节省的数据传输所需的时间——很有可能带来一万倍的加速。
Pytorch 中,数据并行可以通过 DataParallel
和 DistributedDataParallel
两种方式实现。前者是单进程、多线程的并行训练方式,多个 GPU 共享同一个 Python 进程,会受到 Python 解释器的 GIL 的限制。后者属于多进程,每一个 GPU 上都运行一个 Python 进程,不受 GIL 的限制。
并且单进程的方式,限制了 DataParallel
在多台机器上的运行,因此它只能在单台机器上运行。但即使在单机情况下,Pytorch 官方依然推荐使用 DistributedDataParallel
进行多 GPU 训练。
It is recommended to use
DistributedDataParallel
, instead ofDataParallel
to do multi-GPU training, even if there is only a single node.
The difference betweenDistributedDataParallel
andDataParallel
is:DistributedDataParallel
uses multiprocessing where a process is created for each GPU, whileDataParallel
uses multithreading. By using multiprocessing, each GPU has its dedicated process, this avoids the performance overhead caused by GIL of Python interpreter.
在之后的文章里,会进一步详细讲讲 DataParallel
与 DistributedDataParallel
,以及它们之间的异同。