开丰娱乐-开丰注册登录绿色站

0898-08980898  13876453617

网站公告
诚信为本,市场在变,诚信永远不变...

分享本站:

开丰资讯

0898-08980898
传真:0000-1234-5678
邮件:admin@youweb.com
客服:

行业新闻

您当前的位置: 首页 > 开丰资讯 > 行业新闻

基于Chunk内存管理的零冗余优化器 (ZeRO)

点击数:     更新时间:2024-05-13 09:29:26

作者: Hongxin Liu, Jiarui Fang, Zijian Ye

前置教程:

示例代码

相关论文

零冗余优化器 (ZeRO) 通过对三个模型状态(优化器状态、梯度和参数)进行划分而不是复制他们,消除了数据并行进程中的内存冗余。该方法与传统的数据并行相比,内存效率得到了极大的提高,而计算粒度和通信效率得到了保留。

  1. 分片优化器状态: 优化器状态 (如 Adam optimizer, 32位的权重, 以及一二阶动量估计) 被划分到各个进程中, 因此每个进程只更新其分区。
  1. 分片梯度: 在梯度在数据并行进程组内进行 reduction 后, 梯度张量也被划分,这样每个进程只存储与其划分的优化器状态对应的梯度。 注意, Colossal-AI 将梯度转换为 FP32 格式以参与更新参数。

  2. 分片参数: 16位的模型参数被划分到一个数据并行组的进程中。

  3. Gemini: 对于参数、梯度、优化器状态的动态异构内存空间管理器。

此外,我们还将介绍基于Chunk内存管理的零冗余优化器。

在使用零冗余优化器 (ZeRO)时,我们通过切分参数的方式对模型进行分布式存储,这种方法的优点是每个节点的内存负载是完全均衡的。但是这种方式有很多缺点。首先,通信时需要申请一块临时内存用来通信,通信完毕释放,这回导致存在内存碎片化的问题。其次,以Tensor为粒度进行通信,会导致网络带宽无法充分利用。通常来说传输的消息长度越长带宽利用率越高。

利用ColossalAI v0.1.8引入了Chunk机制,我们可以提升ZeRO的性能。我们将运算顺序上连续的一组参数存入一个Chunk中(Chunk即一段连续的内存空间),每个Chunk的大小相同。Chunk方式组织内存可以保证PCI-e和GPU-GPU之间网络带宽的高效利用,减小了通信次数,同时避免潜在的内存碎片。

在v0.1.8之前,ZeRO在进行参数聚合时通信成本较高,如果一个参数在连续的几次计算中被使用多次,即会发生多次通信,效率较低。这种情况在使用Checkpoint时非常常见,参数在计算backward时会重计算一遍forward。这种情况下,ZeRO的效率便不高。

以GPT为例,其Checkpoint会应用在每一个GPT Block上,每一个GPT Block包含一个Self-Attention层和MLP层。在计算Backward时,会依次计算Self-Attention层、MLP层的forward,然后依次计算MLP层、Self-Attention层的backward。如使用Chunk机制,我们将Self-Attention层和MLP层放在同一个Chunk中,在每个GPT Block的backward的中便无需再通信。

除此之外,由于小Tensor的通信、内存移动没法完全利用NVLINK、PCIE带宽,而且每次通信、内存移动都有kernel launch的开销。使用了Chunk之后可以把多次小Tensor的通信、内存移动变为一次大Tensor的通信、内存移动,既提高了带宽利用,也减小了kernel launch的开销。

我们提供了轻量级的Chunk搜索机制,帮助用户自动找到内存碎片最小的Chunk尺寸。

我们将运用的方式来使用基于Chunk内存管理的ZeRO。这是我们新包装的torch.Module ,它使用 ZeRO-DP 和 Gemini,其中ZeRO 用于并行,Gemini 用于内存管理。

Gemini支持惰性初始化, 它可以节省多卡初始化大模型时的显存使用.

如果你的模型有 billion 个参数,你的 GPU 内存为 GB, 当 时,我们推荐使用 LazyInitContext。否则,LazyInitContext 是可选的。

我们提供了 API,它用户友好。我们推荐你使用 API。如果您仍然想使用底层 API,您可以继续阅读本节其他内容。

使用 包装模型。

是DNN的隐藏维度。用户可以提供这个参数来加快搜索速度。如果用户在训练前不知道这个参数也可以。 我们将使用默认值 1024。是以兆(2^20)为单位的最小块大小。如果参数的总大小仍然小于最小块大小,则所有参数将被压缩为一个小块。

初始化优化器。

训练

注意:请不要使用,规范写法是。

在此例程中, 我们使用 ,并以 为例。你必须在允许该例程前安装 。

为了简单起见,我们在这里只使用随机生成的数据。

首先我们只需要引入 的 来定义我们的模型,不需要用户进行模型的定义与修改,方便用户使用。

定义GPT模型:

定义损失函数:

写一个获得随机输入的函数:

最后,使用booster注入 Gemini + ZeRO DDP 特性, 并定义训练循环。由于我们在这个例子中对GPT进行预训练,因此只使用了一个简单的语言模型损失函数:

注意:如果你使用Gemini模块的话,请不要使用我们之前提到过的梯度累加。 完整的例子代码可以在 Train GPT with Colossal-AI. 获得。

客服头部
0898-08980898
13876453617

网站二维码

平台注册入口