当前位置: 首页 > 工具软件 > DeepSpeed > 使用案例 >

DeepSpeed系列 -- 1 - 初识DeepSpeed

曹成双
2023-12-01

本文为DeepSpeed的入门介绍,通过以下维度帮助各位看官了解什么是DeepSpeed:

  • What: DeepSpeed是什么?
  • Why: DeepSpeed解决了什么痛点?
  • How: DeepSpeed是怎么解决这个痛点问题的?(这个下周更)

近年来机器学习一直是 一个很热门的话题,它在视觉,自然语言,语音等领域突不断突破,达到新的高度。之所以有不断有新的成果涌现,我理解大厂们开源的机器学习框架功不可没,例如Tensorflow,Pytorch。框架提供了完善的基础设施,例如丰富的算子,配套齐全的调试优化工具等,尽可能简化工程师搭建机器学习模型的难度,从而降低了机器学习门槛,让新人快速上手。
但这种和谐的场面正面临这严峻的挑战,原因来源于机器学习的模型大小增加急速膨胀中。以自然语言处理领域来说, Transformer网络的参数是*,然而GPT-3模型的参数已经高达173Billion,不时还有参数量高达万亿的模型刷爆头条。这级别参数量的模型所需的内存以及算力已经不是少量GPU卡能够hold住,它可能需要一个gpu集群来提供足量的算力。此时需要将参数和模型合理的分配的不同的机器上,以便充分利用各台机器的内存和算力,避免出现木桶效应。而传统的框架像tensroflow和pytorch对大规模的分布式模型的的支持不完善。DeepSpeed框架便是用于部署大规模分布式训练模型的。

初识DeepSpeed

一句话来说,DeepSpeed是微软开源的应用与大规模分布式训练的一个机器学习的框架。各位看官,如果看到这里,你注意到了上句中的大规模分布式训练机器学习的框架两个词组,你就明白了DeepSpeed是什么了。接下来我说一下这两个概念
机器学习,顾名思义,就是机器学习人类对事物的认知。这个学习的过程就是模型的训练过程。不同的模型其复杂度也是不一样的。在机器上量化模型这个复杂度主要有两个宏观的指标:占用的内存和单次迭代的时间。训练任务越复杂,模型越大,占用的内存越大和单次迭代的时间越长。
按照模型的复杂度,我将机器学习的模型训练分为三个阶段:

1: 新手玩家阶段:一人一卡一模型,一个小时来搞定!

模型不大时,一台机器上的一张卡几个小时就可以完成训练。

2: 氪金玩家阶段:多卡协作训模型,就看通信灵不灵!

随着模型增大,单次迭代时间随之增长,训练次数也可能增加,导致一张卡需要非常长的时间才能训完,例如三个月或者更长。这对于很多AIer是不能接受的,因为训练中可能需要调整超参,导致实际训练的时间更长,这时间成本对于AIer来说往往是不可接受的,因此聪明的AIer开始探索多张卡协作来加速训练过程,协作方式主要有两种:

  • 参数服务器模式(Parameter-Server, 简称PS模式):网络结构和训练参数分开。训练的参数放在单独的设备上即参数服务器(PS),从而打到减少单张卡所需的内存。训练过程中需要的参数从参数服务器拷贝到计算设备上,计算完成后再拷贝会参数服务器。
  • 环形模式(RingAllReduce):网络结构和训练参数不分开。所有设备地位等同,通过建环的方式完成参数的通信。

3: 土豪玩家阶段:超级多卡合起来,超大模型训起来。

如何在有效的时间内训练好一个复杂庞大的模型,是AIer面临的一个问题。

大规模分布式训练

大规模分布式网络的明显特征是单张卡的内存放不下整个模型(权值,梯度值,优化器的状态值,以及前向训练中的中间值),假设模型所需的内存是M,单卡的内存N, 则M >> N。这是大规模分布式训练面临的关键问题,解决方案无非就是两个思路:开源和节流。下面分别介绍开源和节流的方案:

节流

节流,即尝试减少M,是M < N, 此时模型就可以在单张卡上运行了。节流的策略有:

  • 激活重计算(Activation-Recompute): 在前向网络中标记少量的 Tensor ,前向计算就只会保留这些被标记的 Tensor, 其余前向的 activation会通过在反向传播中根据 被标记的Tensor 临时重新计算一遍。这样就使得大量的 activation 不需要一直保存到后向计算,有效减少了大量 Tensor 的生命周期。
  • 负载均衡(CPU-Offload): 在深度学习中,GPU 显存(Device Memory)的特点是昂贵、高速且容量小,而 CPU 的主存(Host Memory)的特点是便宜、相对低速和大容量; 那么将前向计算中的一些
    暂时用不到的 activation 临时换出到 CPU 主存上,等到反向计算需要时再换入到 GPU 显存里,通过这种方式也可以节省显存。

开源

开源即尝试扩大N,一个卡搞不定,用一堆卡来扩大N,此时需要切分模型到各张卡上,以便每张卡上保存一部分模型和权值,即将模型化整为零,如何划分模型呢?这是一门技术活,目前常见的策略有:

  • 流水并行(PipeLine): 将一个L层的网络切成成K个子网络,每个子网络单独的运行在一张卡上。
  • 张量的模型并行(Tensor-Model-Parallel):即将权值切分成N份,每张卡上输入和部分权值进行计算,然后通过卡间通信来获取完整的输出。
 类似资料: