当前位置: 首页 > news >正文

深度学习:MindSpore自动并行

随着模型规模的逐渐增大,需要的算力逐渐增强,但是算力需求增长速度远高于芯片算力增长速度。现在唯一的解决方案只有通过超大规模集群训练大模型。

大集群训练大模型的挑战

内存墙

200B参数量的模型,参数内存占用745GB内存,训练过程需要3500GB内存(参数+激活+梯度+优化器状态),一个模型需要128张卡才能放下。

性能墙

大模型切分到集群后,通信成为了主要的性能瓶颈。模型训练时,主要有几种并行策略:

  • 模型并行:模型的不同层或不同部分被分布在不同设备
  • Pipeline并行:不同部分的前向计算和反向计算被分配到不同设备
  • 数据并行:不同设备处理同一个模型的不同批次

设备通讯主要发生在激活函数或者梯度需要在不同集群间传递(模型、管道并行),参数在GPU间需要同步(数据并行)。

大模型数千亿的参数导致了巨大的激活值和梯度值。受有限带宽的影响,在不同的设备间转移这些数据成为瓶颈。同时,即使带宽足够,小信息间初始化通信的延迟也会显著增加。

效率墙

算法的分布式并行开发一直是一道难题。如何让用户高效编写分布式代码,超大规模AI训练需要怎样的编程范式?

调优墙

在数千节点集群上,要保证计算的正确性、性能、可用性,手工难以全面兼顾。

大集群快速故障恢复

千卡大集群训练时间长,故障不可避免,跨苏故障恢复可减少等待时间。MindSpore解决方法如下:

  1. 定期保存CKPT(CheckPoint)文件
  2. 故障检测隔离
  3. 资源重条度
  4. 加载故障时刻CKPT
  5. 恢复训练任务

基于HCCL集合通信库实现分布式训练

HCCL(Huawei Collective Communication Library)基于Ascend芯片的高性能集合通信库,提供单机多卡、多机多卡集合通信原语。 

数据并行

左右表示两个Ascend卡各自运行一个进程,每张卡上运行同一个模型、参数、优化器状态,复制n份,每张卡输入不同数据,进行一次反向传播后获得梯度, 随后进行一次allreduce,把每一张卡上得到的梯度聚合至一起,取平均后分发回各张卡。

存在问题:

要求单卡能放下整个模型

多卡训练时内存冗余(多存了n-1份模型参数)

MindSpore中以BERT与训练为例的数据并行

from mindspore.parallel._utils import _get_device_num, _get_gradients_mean# 6. Pretrain
mean = _get_gradients_mean()
degree = _get_device_num()
grad_reducer = nn.DistributedGradReducer(optimizer.parameters, mean, degree)def train_step(input_ids, input_mask, masked_lm_ids, masked_lm_positions, masked_lm_weghts, next_sentence_label, segment_ids):status = init_register()input_ids = ops.depend(input_ids, status)(total_loss, masked_lm_loss, next_sentence_loss), grads = grad_fn(input_ids, input_mask, segment_ids, masked_lm_ids, masked_lm_positions, masked_lm_weights, next_sentence_label)grads = clip_by_global_norm(grads, clip_norm=1.0)# 进行allreduce操作,分发梯度grads = grad_reducer(grads)status = all_finite(grads, status)if status:total_loss = loss_scaler.unscale(total_loss)grads = loss_scaler.unscale(grads)total_loss = ops.depend(total_loss, optimizer(grads))total_loss = ops.depend(total_loss, loss_scaler.adjust(status))return total_loss, masked_lm_loss, next_sentence_loss, status

模型并行

 模型并行是算子层面的并行,他利用某些算子的特性将算子拆分到多个设备上进行计算。因此不是网络中的所有算子都可以拆分计算。可以产分的算子需满足如下特性:

  • 可以并行计算的算子
  • 算子其中一个输入来自parameter

矩阵乘法(全连接层、attention核心)

左侧为一张卡进行矩阵乘法的示意图。

右侧为模型并行在两张卡上的示意图:X保持一样,W参数矩阵分为两份,分别和X进行矩阵乘法。最后将两张卡乘法的输出结果合并到一起。

即X.shape为(m, k),W1.shape为(k, n),拆分后,W1'.shape为(k, n/2),W1''.shape为(k, n/2),相乘输出为(m, n/2),合并后仍为(m, n) 。

但不是所有算子都适合这样的模型并行。

MindSpore算子级并行

MindSpore屏蔽了模型并行的前置和后置工作(通信、算子排布),开发者只需关心数据如何进行切分即可。

  • MindSpore对每个算子独立建模,用户可以设置正向网络中每个算子的切分策略(对于未设置的算子,默认按数据并行进行切分)。
  • 在构图阶段,框架将遍历正向图,根据算子的切分策略对每个算子及其输入张量进行切分建模,使得该算子的计算逻辑在切分前后保持数学等价。
  • 框架内部使用Tensor Layout来表达输入输出张量在集群中的分布状态,Tensor Layout中包含了张量和设备间的映射关系,用户无需感知模型各切片在集群中如何分布,框架将自动调度分配。
  • 框架还将遍历相邻算子间张量的Tensor Layout,如果前一个算子输出张量作为下一个算子的输入张量,且前一个算子输出张量的Tensor Layout与下一个算子输入张量的TensorLayout不同,则需要在两个算子之间进行张量重排布(Tensor Redistribution)
  • 对于训练网络来说,框架处理完正向算子的分布式切分之后,依靠框架的自动微分能力即能自动完成反向算子的分布式切分。

示例

用户在4卡计算两个连续的二维矩阵乘法Z=(X * W) * V,第一个矩阵Y = X * W,用户想把X按行切4fen(数据并行),第二个矩阵Z = Y * V,用户想把V按列切4份(模型并行)

import mindspore.nn as nn
from mindspore import ops
import mindspore as msms.set_auto_parallel_context(parallel_mode="semi_autoparallel", device_num=4)class DenseMatMulNet(nn.Cell):def __init__(self):super(DenseMatMulNet, self).__init__()# 切分只需要配置shard接口即可# 对于matmul1, 接受两个输入,第一个输入,第一维切成四份,第二维不进行切割# 第二个输入,均不切割self.matmul1 = ops.MatMul.shard((4, 1), (1, 1))# 对于matmul2,第二个输入的第二个维度切成四份self.matmul2 = ops.MatMul.shard((1, 1), (1, 4))def construct(self, x, w ,v):y = self.matmul1(x, w)z = self.matmul2(y, v)return z

# a simple example to demenstarte auto data parallel and model parallel on Mindspore
import sys
import numpy as np
import mindspore.nn as nn
import mindspore as ms
from mindspore.nn import Cell, Momentum
from mindspore.ops import operations as ops
from mindspore.nn import SoftmaxCrossEntropyWithLogits
from mindspore import train
import mindspore.dataset as ds
import mindspore.communication as D
from mindspore.common.initializer import initializer# generate fake dataset
step_per_epoch = 4def get_dataset(*inputs):def generate():for _ in range(step_per_epoch):yield inputsreturn generate# define a simple net which will cut data into pieces for multi-npu training
class Net(Cell):def __init__(self):super().__init__()self.matmul = ops.MatMul().shard(((1, 2), (2, 1)))self.weight = ms.Parameter(initializer("normal", [32, 16]), "w1")self.relu = ops.ReLU().shard(((2, 1),))def construct(self, x):out = self.matmul(x, self.weight)out = self.relu(out)return out# 设置运行环境的context。
# 在运行程序之前,应配置context。如果没有配置,默认情况下将根据设备目标进行自动设置。
# Compile the graph once and execute it multiple times.
ms.set_context(mode=ms.GRAPH_MODE, device_target="Ascend")# Initialize distributed training environment
D.init()
# get rank of current device in the whole distributed computation
rank = D.get_rank()
# set semi-auto-parallel
ms.set_auto_parallel_context(parallel_mode="semi_auto_parallel", device_num=2, full_batch=True)np.random.seed(1)input_data = np.random.rand(16, 32).astype(np.float32)
label_data = np.random.rand(16, 16).astype(np.float32)
fake_dataset = get_dataset(input_data, label_data)net = Net()# define callback function while traing, including loss monitor and checkpoint file save path
callback = [train.LossMonitor(), train.ModelCheckpoint(directory="{}".format(rank))]
# generate dataset and define data column
dataset = ds.GeneratorDataset(fake_dataset, ["input", "label"])
# define loss function
loss = nn.SoftmaxCrossEntropyWithLogits()lr = 1e-3
momentum=0.1
num_epochs = 5optimizer = nn.Momentum(net.trainable_params(), lr, momentum)model = ms.Model(net, loss_fn=loss, optimizer=optimizer)model.train(num_epochs, dataset, callbacks=callback, dataset_sink_mode=False)

Pipeline并行

受Server间通信带宽低的影响,传统数据并行叠加模型并行的混合模式性能表现欠佳,需要引入流水线并行。流水线并行是将神经网络中的算子切分为多个阶段,再把阶段映射到不同设备上,使得不同设备去计算神经网络的不同部分。相当于每张卡上只放模型的其中基层或一层

如果Pipeline并行每次都知计算一批数据,不能充分利用多卡优势,因为总有卡处于空闲在等待数据。

wile提升效率,流水线并行进一步把mini-barch划分为micro-batch,在微批次中采用流水线式的执行序列,从而提升效率。

1F1B

一次个micro-batch进行正向后,立即进行一次反向计算。使得内存可以更早释放,进而确保内存使用峰值更低。1F1B是现在的主流方式。 

示例

MindSpore中,Pipeline的实现方式非常简单。通过调用pipeline_stage接口来指定每个layer要在哪个stage上去执行。pipeline接口的洗礼度微Cell,即只要继承了nn.Cell的实例,就要配置pipeline_stage,并且需要按照网络执行的先后顺序,从小到大进行配置。

...class ResNet(nn.Cell):"""ResNet"""def __init__(self, block, num_classes=100, batch_size=32):"""init"""super(ResNet, self).__init__()self.batch_size = batch_sizeself.num_classes = num_classesself.head = Head()self.layer1 = MakeLayer0(block, in_channels=64, out_channels=256, stride=1)self.layer2 = MakeLayer1(block, in_channels=256, out_channels=512, stride=2)self.layer3 = MakeLayer2(block, in_channels=512, out_channels=1024, stride=2)self.layer4 = MakeLayer3(block, in_channels=1024, out_channels=2048, stride=2)self.pool = ops.ReduceMean(keep_dims=True)self.squeeze = ops.Squeeze(axis=(2, 3))self.fc = fc_with_initialize(512 * block.expansion, num_classes)# pipeline parallel configself.head.pipeline_stage = 0self.layer1.pipeline_stage = 0self.layer2.pipeline_stage = 0self.layer3.pipeline_stage = 1self.layer4.pipeline_stage = 1self.fc.pipeline_stage = 1...

 Pipeline并行的结果,只会在一张卡上输出loss,因为loss是集合到最后一张卡上进行输出的,故其他卡没有loss。

内存优化

重计算

计算某些反向算子时,需要一些正向算子的计算结果,导致这些正向算子结果需要驻留在内存中,知道依赖他们的反向算子计算完,这些正向算子的计算结果占用的内存才会被复用。

重计算是一种时间换空间的方法。为了降低内存峰值,重计算技术可以不保存正向计算结果,在反向计算时,重新计算一遍正向结果,使得内存可以被重复利用。

虽然运算速度慢了,但是可以有更多可利用的内存,可以增大batch_size大小。

MindSpore中,重计算接口可以针对单个算子和Cell进行设置。当用户调用Cell的重计算接口时,整个Cell中的所有正向算子都会被设置为重计算。 

优化器并行(ZeRO)

进行数据并行训练时,模型的参数更新部份在各个卡之间存在冗余,优化器并行通过将优化器的计算量分散到数据并行维度的卡上,在大规模网络上可以有效减少内存消耗并提升网络性能。

Baseline为传统的数据并行,即每个一卡都存一份参数、梯度和优化器状态。优化器并行就是在每张卡上分发一份需要维护的optimizer status。

MindSpore的优化器并行,全局配置即可

ms.set_auto_parallel_context(parallel_mode=ms.ParallelMode.SEMI_AUTO_PARALLEL, enable_parallel_optimizer=True)

 MindSpore分布式并行模式

半自动:如数据并行配置shard,Pipeline并行需要配置Pipeline_config仍需要用户自己指定参数配置,所以这是半自动的。

(全)自动并行:框架自动配置一个并行配置策略,适合想要并行训练但是不知道如何配置策略的用户。只需配置ms.set_auto_parallel_context(parallel_mode=ms.ParallelMode.AUTO_PARALELL)即可

相关文章:

深度学习:MindSpore自动并行

随着模型规模的逐渐增大,需要的算力逐渐增强,但是算力需求增长速度远高于芯片算力增长速度。现在唯一的解决方案只有通过超大规模集群训练大模型。 大集群训练大模型的挑战 内存墙 200B参数量的模型,参数内存占用745GB内存,训练…...

python拆分Excel文件

按Sheet拆分Excel 或 按照某一列的不同值拆分Excel。文档样式如下: 结果:红色是按照Sheet名拆出的,蓝色和橙色是某个Sheet按照某列的不同值拆分的。 代码: # -*- coding: utf-8 -*- """ 拆分excel文件——按照…...

Python实现Excel中数据条显示

Python中要实现百分比数据条的显示,可以使用pandas库,pandas图表样式的设置与Excel中的条件格式设置比较类似,比如Excel里常用的数据条的用法,在pandas中使用代码进行高亮显示,用来突出重点数据,下面一起来…...

c#如何开发后端

1选择开发框架 在 C# 中,用于后端开发最常用的框架是ASP.NET。它提供了构建 Web 应用程序、Web API 和微服务等多种后端服务所需的功能。ASP.NET有不同的模式,如ASP.NET MVC(Model - View - Controller)和ASP.NET Web API。ASP.NE…...

6.Vue------async/await详细的讲解---知识积累

前提: 先说一下Promise解释 Promise是一种在JavaScript中处理异步操作的对象。它代表了一个尚未完成但承诺未来某个时间会完成的操作结果。Promise有三种状态:pending(等待中)、fulfilled(已成功)和reject…...

Redis面试专题-持久化

目录 前言 持久化相关知识 1.三种持久化机制 2.RDB持久化 3.深入剖析一下RDB持久化过程 4.AOF持久化 5.RDB和AOF对比​编辑 面试题 1.redis持久化机制有哪些? 2.那仔细讲讲你对他们的理解 3.你刚刚说AOF的文件很大,那AOF文件会越来越大&#xf…...

如何将快捷指令添加到启动台

如何将快捷指令添加到启动台/Finder/访达(Mac) 1. 打开快捷指令创建快捷指令 示例创建了一个文件操作测试的快捷指令。 2. 右键选择添加到程序坞 鼠标放在待添加的快捷指令上。 3. 右键添加到访达 鼠标放在待添加的快捷指令上。 之后就可以在启…...

ansible自动化运维(二)ad-hoc模式

目录 Ansible模块(ad-hoc模式) 1.command模块:远程执行命令 2.shell 模块:远程执行命令,支持管道,重定向 3.Raw模块:先登录,再执行,最后退出 4.Script模块&#xff…...

技术栈6:Docker入门 Linux入门指令

目录 1.Linux系统目录结构 2.处理目录的常用命令 3.Docker概述 4.Docker历史 5.Docker基本组成 6.Docker底层原理 7.Docker修改镜像源 8.Docker基本命令 9.Docker创建Nginx实战 10.数据卷 11.本地目录直接挂载* 12.镜像和dockerfile 13.容器互联与自定义网络 14.…...

OPStack Optimism Layer2

概述 OP Stack 是标准化、共享和开源的开发堆栈,为 Optimism 提供支持,由 Optimism Collective 维护。 Optimism Bedrock 是 OP Stack的当前版本。 Bedrock 版本提供了用于启动生产质量的 Optimistic Rollup 区块链的工具。此时,OP Stack不同层的 API 仍然与Stack的 Rollu…...

Leetcode—1498. 满足条件的子序列数目【中等】

2024每日刷题&#xff08;210&#xff09; Leetcode—1498. 满足条件的子序列数目 C实现代码 class Solution { public:int numSubseq(vector<int>& nums, int target) {const int MOD 1e9 7;int n nums.size();vector<int> pows(n, 1);for(int i 1; i &…...

生活大爆炸版石头剪刀布(洛谷P1328)

生活大爆炸版石头剪刀布(洛谷P1328) [NOIP2014 提高组] 前言&#xff1a; 由于洛谷发布题解有限制&#xff0c;所以在CSDN上发布洛谷题解。 所有题解均是Java语言, 但是思路是相同的 每篇都是刷题日常&#xff0c;尽量讲清楚算法逻辑。 希望有问题还请大佬们指导&#xff01; …...

OmniParser一种用于增强视觉语言模型与用户界面交互效果的技术

OmniParser一种用于增强视觉语言模型与用户界面交互效果的技术 OmniParser的核心功能是将用户界面截图转换为结构化元素&#xff0c;这一过程涉及几个关键步骤和技术要素&#xff0c;解决了视觉语言模型&#xff08;VLMs&#xff09;在与用户界面交互时所面临的多种挑战。 1.…...

Unity引擎UI滚动列表——滚动复用基础介绍

大家好&#xff0c;我是阿赵。 一、滚动复用的介绍 在制作游戏的过程中&#xff0c;经常会遇到一些需要显示数量比较大的数据的情况。比如说&#xff0c;一个排行榜&#xff0c;需要展示当前服务器前一千个玩家的排名。或者游戏的背包容量特别大&#xff0c;可以有几千个格子。…...

在 Windows 11 WSL (Ubuntu 24.04.1 LTS) | Python 3.12.x 下部署密码学库 charm

1. 在 Windows 11 上部署 Ubuntu (WSL) 由于作者没有高性能的 Ubuntu 服务器或个人电脑&#xff0c;且公司或学校提供的 Ubuntu 服务器虽然提供高性能 GPU 等硬件配置但通常不会提供 root 权限&#xff0c;因而作者通过在搭载了 Windows 11 的个人电脑上启动 Ubuntu (WSL) 来进…...

【六足机器人】01功能开发

包含&#xff1a;WIFI模块、GPS模块、语言模块、调试信息接口。 一、硬件连接 huart4&#xff08; PA0、 PA1 &#xff09;与GPS模块连接。 huart3&#xff08;PB10、PB11&#xff09;与ESP8266模块连接。 huart2&#xff08; PA2、 PA3 &#xff09;与语音模块连接。 hu…...

notepad++安装教程(超详细)

1.下载地址&#xff08;可以私信博主&#xff09; https://notepad-plus.en.softonic.com/download 2.解压安装...

创建简单的 PL/pgSQL 存储过程

文章目录 创建简单的 PL/pgSQL 存储过程CREATE OR REPLACE FUNCTIONadd_two_numbers(a integer, b integer)RETURNS integerAS$$ ... $$函数体LANGUAGE plpgsql 创建带有 IN 和 OUT 参数的存储过程创建修改数据的存储过程创建带有异常处理的复杂存储过程 在 PostgreSQL 中&…...

Java项目实战II基于微信小程序的无中介租房系统(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 随着城市化进程的加速&#xff0c;租房市场日益繁荣&a…...

Node.js实现WebSocket教程

Node.js实现WebSocket教程 1. WebSocket简介 WebSocket是一种在单个TCP连接上提供全双工通信的协议&#xff0c;允许服务器和客户端之间进行实时、双向通信。本教程将详细讲解如何在Node.js中实现WebSocket。 2. 技术选型 我们将使用ws库来实现WebSocket服务器&#xff0c;…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

工程地质软件市场:发展现状、趋势与策略建议

一、引言 在工程建设领域&#xff0c;准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具&#xff0c;正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...