大模型分布式系统
Posted 远洋之帆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大模型分布式系统相关的知识,希望对你有一定的参考价值。
背景:
模型越来越大,训练复杂度越来越高,需要训练的时间也是越来越长。那么我们该如何在现有的硬件基础上对模型做训练呢。
模型规模的扩大,对硬件(算力、内存)的发展提出要求。然而,因为 内存墙 的存在,单一设备的算力及容量,受限于物理定律,持续提高芯片的集成越来越困难,难以跟上模型扩大的需求。
为了解决算力增速不足的问题,人们考虑用多节点集群进行分布式训练,以提升算力,分布式训练势在必行。
这篇文章会跟大家分享分布式计算的几种策略:数据并行、模型并行、混合并行,以及模型并行工程上常用的两种框架ps、ring-allreduce;然后会给大家介绍显存都消耗在哪些地方了;接着跟大家介绍如何针对显存消耗多的地方优化。
文章引用比较多的oneflow公司和清华大学的课程内容。
常见的并行策略¶
简单的机器堆叠并不一定会带来算力的增长。因为神经网络的训练并不是单纯的“把原来一个设备做的事情,现在分给多个设备各自做”,它不仅需要多个设备进行计算,还涉及到设备之间的数据传输,只有协调好集群中的计算与通信,才能做高效的分布式训练。
我们将以矩阵乘法的例子,解释数据并行、模型并行的区别。
先了解以下逻辑上的矩阵乘法例子:
假设神经网络中某一层是做矩阵乘法,其中的输入 x 的形状为 4×5,模型参数 w 的形状为 5×8,那么,矩阵乘法输出形状为 4×8。示意图如下:
单机单卡的训练中,以上矩阵乘法,先计算得到 out,并将 out传递给下一层,并最终计算得到 loss,然后在反向传播过程中,得到 aloss/aw,用于更新 w。
分布式训练中,依据是切分 x 还是 w的不同,分为“数据并行”和“模型并行”策略。接下来,我们介绍常见的并行策略。
数据并行¶
所谓的数据并行,就是将数据 x 进行切分,而每个设备上的模型 w是完整的、一致的。如下图所示,x被按照第0维度平均切分到2个设备上,两个设备上都有完整的 w。
这样,在两台设备上,分别得到的输出,都只是逻辑上输出的一半(形状为 2×8),将两个设备上的输出拼接到一起,才能得到逻辑上完整的输出。
注意,因为数据被分发到了2个设备上,因此反向传播过程,各自设备上得到的 会不一样,如果直接使用各个设备上的梯度更新各自的模型,会造成2个设备上的 模型不一致,训练就失去了意义(到底用哪个模型好呢?)。
因此,数据并行策略下,在反向传播过程中,需要对各个设备上的梯度进行 AllReduce,以确保各个设备上的模型始终保持一致。
当数据集较大,模型较小时,由于反向过程中为同步梯度产生的通信代价较小,此时选择数据并行一般比较有优势,常见的视觉分类模型,如 ResNet50,比较适合采用数据并行。
模型并行¶
当神经网络非常巨大,数据并行同步梯度的代价就会很大,甚至网络可能巨大到无法存放到单一计算设备中,这时候,可以采用模型并行策略解决问题。
所谓的模型并行,就是每个设备上的数据是完整的、一致的,而模型 � 被切分到了各个设备上,每个设备只拥有模型的一部分,所有计算设备上的模型拼在一起,才是完整的模型。
如下图所示,� 被按照第1维度平均切分到2个设备上,两个设备上都有完整的 �。两个设备上的输出也需要通过拼接才能得到逻辑上的输出。
模型并行的好处是,省去了多个设备之间的梯度 AllReduce;但是,由于每个设备都需要完整的数据输入,因此,数据会在多个设备之间进行广播,产生通信代价。比如,上图中的最终得到的 ��� (4×8) ,如果它作为下一层网络的输入,那么它就需要被广播发送到两个设备上。
语言模型,如 BERT,常采用模型并行。
流水并行¶
当神经网络过于巨大,无法在一个设备上存放时,除了上述的模型并行的策略外,还可以选择流水并行。 流水并行指将网络切为多个阶段,并分发到不同的计算设备上,各个计算设备之间以“接力”的方式完成训练。
如下图,展示了一个逻辑上的4层网络(T1 至 T4)是如何做流水并行的。
4层网络被切分到2个计算设备上,其中 GPU0 上进行 T1 与 T2 的运算,GPU1 上进行 T3 与 T4 的计算。
GPU0 上完成前两层的计算后,它的输出被当作 GPU1 的输入,继续进行后两层的计算。
混合并行¶
网络的训练中,也可以将多种并行策略混用,以 GPT-3 为例,以下是它训练时的设备并行方案:
它首先被分为 64 个阶段,进行流水并行。每个阶段都运行在 6 台 DGX-A100 主机上。在6台主机之间,进行的是数据并行训练;每台主机有 8 张 GPU 显卡,同一台机器上的8张 GPU 显卡之间是进行模型并行训练。
并行策略的选择影响着训练效率,框架对并行训练的接口支持程度,决定了算法工程师的开发效率。OneFlow 针对分布式训练所做的系统级设计和创新,为用户轻松上手分布式训练做足了铺垫。我们将在本专题的其它文章中看到相关示例。
分布式训练系统架构
分布式训练系统架构主要有两种:
Parameter Server Architecture(就是常见的PS架构,参数服务器)
Ring-allreduce Architecture
Parameter Server架构
在Parameter Server架构(PS架构)中,集群中的节点被分为两类:parameter server和worker。其中parameter server存放模型的参数,而worker负责计算参数的梯度。在每个迭代过程,worker从parameter sever中获得参数,然后将计算的梯度返回给parameter server,parameter server聚合从worker传回的梯度,然后更新参数,并将新的参数广播给worker。见下图的左边部分。
Ring-allreduce架构
在Ring-allreduce架构中,各个设备都是worker,并且形成一个环,如上图所示,没有中心节点来聚合所有worker计算的梯度。在一个迭代过程,每个worker完成自己的mini-batch训练,计算出梯度,并将梯度传递给环中的下一个worker,同时它也接收从上一个worker的梯度。对于一个包含N个worker的环,各个worker需要收到其它N-1个worker的梯度后就可以更新模型参数。其实这个过程需要两个部分:scatter-reduce和allgather,百度开发了自己的allreduce框架,并将其用在了深度学习的分布式训练中。
相比PS架构,Ring-allreduce架构有如下优点:
带宽优化,因为集群中每个节点的带宽都被充分利用。而PS架构,所有的worker计算节点都需要聚合给parameter server,这会造成一种通信瓶颈。parameter server的带宽瓶颈会影响整个系统性能,随着worker数量的增加,其加速比会迅速的恶化。
此外,在深度学习训练过程中,计算梯度采用BP算法,其特点是后面层的梯度先被计算,而前面层的梯度慢于前面层,Ring-allreduce架构可以充分利用这个特点,在前面层梯度计算的同时进行后面层梯度的传递,从而进一步减少训练时间。在百度的实验中,他们发现训练速度基本上线性正比于GPUs数目(worker数)。
显存消耗分析
cpu拥有更少的核数,更强大的core,适合来做复杂的逻辑处理、流程控制,通用性更强。
gpu拥有更多的核数,但是每个core的能力是相对弱的,适合来做简单的单一的事情,比如计算。
模型训练时候显卡主要花在哪些地方:
1.网络参数如上的绿色线指示W
2.网络训练用到的回传梯度蓝色线指示的deltaW
3.优化器的各种正则器比如Adam有两倍参数的数据
4.计算回传梯度的中间deltaY,这个和训练数据量、数据特征长度直接相关
数据并行显存消耗分析
前向计算
1.参数复制到每一个设备
2.每个设备利用部分数据计算参数
后向计算
1.梯度从每个分片回传计算均值
2.均值梯度更新参数
把数据广播到每个设备,每个GPU计算梯度要消耗显存,有网络开销
把每台设备的梯度回传到一台计算平均梯度,计算平均梯度设备有显存消耗
把计算完平均梯度传给每台设备,接受设备在更新参数时有显存消耗
计算平均梯度,其实还可以每台设备计算一部分参数的梯度,optimizer参数变成全量参数计算1/n
每部分梯度计算完后,在进行参数广播给其他设备(这种每天计算部分参数,在广播给其他设备,并行性会更好,但是网络开销更大,每台设备的峰值显存消耗会稍微小些)
数据并行,每台设备上计算的数据batch尺寸减小了,所以显卡内存intermediate消耗会减少。
模型并行显卡消耗分析
1.把参数矩阵分块,分发给每块设备
2.每块设备处理全样数据计算
模型并行计算:
1.参数变小了,分成多少块,参数量就是全有参数的1/n
2.梯度参数变成全部参数的1/n
3.优化参数变成全部参数的1/n
4.因为要对全量数据计算,所以每个batch参数是不变的,intermediate数据量不变
显存优化
ZERO参数优化策略
Zero-Stage1策略优化:
1.采用数据并行,intermediate参数变成全量数据1/n
2.梯度汇总的时候采用reduce scatter策略,每台设备计算一部分参数,optimizer参数变成全量参数计算1/n
3.需要更新全局参数时候在进行All Gather,对所有参数更新
显存消耗较多,适用于参数不大模型计算。
Zero-Stage2策略优化:
1.采用数据并行,intermediate参数变成全量数据1/n
2.每台设备计算梯度回传的时候采用reduce scatter策略,每台设备计算一部分参数,Gradient、optimizer参数变成全量参数计算1/n
3.需要更新全局参数时候在进行All Gather,对所有参数更新
Zero-Stage2策略优化:
1.采用模型并行+数据并行混合,参数变为全量1/n
2.采用数据并行,intermediate参数变成全量数据1/n
3.每台设备计算梯度回传的时候采用reduce scatter策略,每台设备计算一部分参数,Gradient、optimizer参数变成全量参数计算1/n
小结
1.Zero-1stage在静态链路上看,intermediate、optimizer显存减少为全量1/n
2.zero-2stage在静态链路上看,intermediate、optimizer、gradient显存减少为全量1/n
3.zero-3stage在静态链路上看,intermediate、optimizer、gradient、parameter显存减少为全量1/n
流水线并行策略
模型是一层一层的,所谓流水线并行就是:
1.每层模型分到不同的GPU上做计算
2.数据并行的计算
3.intermediate、optimizer、gradient、parameter显存减少为全量1/n
动态优化
同样是选择了zero策略+流水线策略,为什么deepspeed的框架和megatron、BMtrain、ColossalAI框架在Runtime时候显存消耗会出现很大的差异。这里主要原因是zero策略虽然是规定了大的规范,但是在实现时候计算流程从前到后传递参数,保留多久、何时丢弃、丢弃什么,各家的理解和实现都是有差异的。所以导致虽然都是zero策略、流水线策略用起来Runtime的显存消耗和计算速度差异很大。
实际运算中,一块Gpu配置多块cpu(一般是6-12块,看参数大小),在计算时候可以把optimizer参数部分卸载到cpu。
1.把梯度计算参数从gpu卸载部分到cpu减少显存
2.optimizer早cpu上处理用(openmp+SMID)
3.更新参数时候再把参数从cpu传给gpu
流水线并行,不用等到所有层都算完,再反过来计算每一层参数。可以异步每算完一层就把前面一层的参数修改,这样就只要记住上一次上一层的参数就可以。
重新计算释放的中间体,并在获得梯度状态后再次释放。减少显卡内存,以时间换空间。
利用异构的内存系统,在Runtime流程中各种工程技巧极限压缩显存使用。
大数据的那些事儿
资源列表:
- 关系数据库管理系统(RDBMS)
- 框架
- 分布式编程
- 分布式文件系统
- 文件数据模型
- Key -Map 数据模型
- 键-值数据模型
- 图形数据模型
- NewSQL数据库
- 列式数据库
- 时间序列数据库
- 类SQL处理
- 数据摄取
- 服务编程
- 调度
- 机器学习
- 基准测试
- 安全性
- 系统部署
- 应用程序
- 搜索引擎与框架
- MySQL的分支和演化
- PostgreSQL的分支和演化
- Memcached的分支和演化
- 嵌入式数据库
- 商业智能
- 数据可视化
- 物联网和传感器
- 文章
- 论文
- 视频
关系数据库管理系统(RDBMS)
- MySQL:世界最流行的开源数据库;
- PostgreSQL:世界最先进的开源数据库;
- Oracle 数据库:对象-关系型数据库管理系统。
框架
- Apache Hadoop:分布式处理架构,结合了 MapReduce(并行处理)、YARN(作业调度)和HDFS(分布式文件系统);
- Tigon:高吞吐量实时流处理框架。
分布式编程
- AddThis Hydra :最初在AddThis上开发的分布式数据处理和存储系统;
- AMPLab SIMR:用在Hadoop MapReduce v1上运行Spark;
- Apache Beam:为统一的模型以及一套用于定义和执行数据处理工作流的特定SDK语言;
- Apache Crunch:一个简单的Java API,用于执行在普通的MapReduce实现时比较单调的连接、数据聚合等任务;
- Apache DataFu:由LinkedIn开发的针对Hadoop and 和Pig的用户定义的函数集合;
- Apache Flink:具有高性能的执行时间和自动程序优化;
- Apache Gora:内存中的数据模型和持久性框架;
- Apache Hama:BSP(整体同步并行)计算框架;
- Apache MapReduce :在集群上使用并行、分布式算法处理大数据集的编程模型;
- Apache Pig :Hadoop中,用于处理数据分析程序的高级查询语言;
- Apache REEF :用来简化和统一低层大数据系统的保留性评估执行框架;
- Apache S4 :S4中流处理与实现的框架;
- Apache Spark :内存集群计算框架;
- Apache Spark Streaming :流处理框架,同时是Spark的一部分;
- Apache Storm :Twitter流处理框架,也可用于YARN;
- Apache Samza :基于Kafka和YARN的流处理框架;
- Apache Tez :基于YARN,用于执行任务中的复杂DAG(有向无环图);
- Apache Twill :基于YARN的抽象概念,用于减少开发分布式应用程序的复杂度;
- Cascalog:数据处理和查询库;
- Cheetah :在MapReduce之上的高性能、自定义数据仓库;
- Concurrent Cascading :在Hadoop上的数据管理/分析框架;
- Damballa Parkour :用于Clojure的MapReduce库;
- Datasalt Pangool :可选择的MapReduce范例;
- DataTorrent StrAM :为实时引擎,用于以尽可能畅通的方式、最小的开支和对性能最小的影响,实现分布式、异步、实时的内存大数据计算;
- Facebook Corona :为Hadoop做优化处理,从而消除单点故障;
- Facebook Peregrine :MapReduce框架;
- Facebook Scuba :分布式内存数据存储;
- Google Dataflow :创建数据管道,以帮助其分析框架;
- Netflix PigPen :为MapReduce,用于编译成Apache Pig;
- Nokia Disco :由Nokia开发的MapReduc获取、转换和分析数据;
- Google MapReduce :MapReduce框架;
- Google MillWheel :容错流处理框架;
- JAQL :用于处理结构化、半结构化和非结构化数据工作的声明性编程语言;
- Kite :为一组库、工具、实例和文档集,用于使在Hadoop的生态系统上建立系统更加容易;
- Metamarkets Druid :用于大数据集的实时e框架;
- Onyx :分布式云计算;
- Pinterest Pinlater :异步任务执行系统;
- Pydoop :用于Hadoop的Python MapReduce和HDFS API;
- Rackerlabs Blueflood :多租户分布式测度处理系统;
- Stratosphere :通用集群计算框架;
- Streamdrill :用于计算基于不同时间窗口的事件流的活动,并找到最活跃的一个;
- Tuktu :易于使用的用于分批处理和流计算的平台,通过Scala、 Akka和Play所建;
- Twitter Scalding:基于Cascading,用于Map Reduce工作的Scala库;
- Twitter Summingbird :在Twitter上使用Scalding和Storm串流MapReduce;
- Twitter TSAR :Twitter上的时间序列聚合器。
分布式文件系统
- Apache HDFS:在多台机器上存储大型文件的方式;
- BeeGFS:以前是FhGFS,并行分布式文件系统;
- Ceph Filesystem:设计的软件存储平台;
- Disco DDFS:分布式文件系统;
- Facebook Haystack:对象存储系统;
- Google Colossus:分布式文件系统(GFS2);
- Google GFS:分布式文件系统;
- Google Megastore:可扩展的、高度可用的存储;
- GridGain:兼容GGFS、Hadoop内存的文件系统;
- Lustre file system:高性能分布式文件系统;
- Quantcast File System QFS:开源分布式文件系统;
- Red Hat GlusterFS:向外扩展的附网存储(Network-attached Storage)文件系统;
- Seaweed-FS:简单的、高度可扩展的分布式文件系统;
- Alluxio:以可靠的存储速率在跨集群框架上文件共享;
- Tahoe-LAFS:分布式云存储系统;
文件数据模型
- Actian Versant:商用的面向对象数据库管理系统;
- Crate Data:是一个开源的大规模可扩展的数据存储,需要零管理模式;
- Facebook Apollo:Facebook的Paxos算法,类似于NoSQL数据库;
- jumboDB:基于Hadoop的面向文档的数据存储;
- LinkedIn Espresso:可横向扩展的面向文档的NoSQL数据存储;
- MarkLogic:模式不可知的企业版NoSQL数据库技术;
- MongoDB:面向文档的数据库系统;
- RavenDB:一个事务性的,开源文档数据库;
- RethinkDB:支持连接查询和群组依据等查询的文档型数据库。
Key Map 数据模型
注意:业内存在一些术语混乱,有两个不同的东西都叫做“列式数据库”。这里列出的有一些是围绕“key-map”数据模型而建的分布式、持续型数据库,其中所有的数据都有(可能综合了)键,并与映射中的键-值对相关联。在一些系统中,多个这样的值映射可以与键相关联,并且这些映射被称为“列族”(具有映射值的键被称为“列”)。
另一组也可称为“列式数据库”的技术因其存储数据的方式而有别于前一组,它在磁盘上或在存储器中——而不是以传统方式,即所有既定键的键值都相邻着、逐行存储。这些系统也彼此相邻来存储所有列值,但是要得到给定列的所有值却不需要以前那么繁复的工作。
前一组在这里被称为“key map数据模型”,这两者和Key-value 数据模型之间的界限是相当模糊的。后者对数据模型有更多的存储格式,可在列式数据库中列出。若想了解更多关于这两种模型的区分,可阅读Daniel Abadi的博客:Distinguishing two major types of Column Stores。
- Apache Accumulo:内置在Hadoop上的分布式键/值存储;
- Apache Cassandra:由BigTable授权,面向列的分布式数据存储;
- Apache HBase:由BigTable授权,面向列的分布式数据存储;
- Facebook HydraBase:Facebook所开发的HBase的衍化品;
- Google BigTable:面向列的分布式数据存储;
- Google Cloud Datastore:为完全管理型的无模式数据库,用于存储在BigTable上非关系型数据;
- Hypertable:由BigTable授权,面向列的分布式数据存储;
- InfiniDB:通过MySQL的接口访问,并使用大规模并行处理进行并行查询;
- Tephra:用于HBase处理;
- Twitter Manhattan:Twitter的实时、多租户分布式数据库。
键-值数据模型
- Aerospike:支持NoSQL的闪存优化,数据存储在内存。开源,“’C’(不是Java或Erlang)中的服务器代码可精确地调整从而避免上下文切换和内存拷贝”。
- Amazon DynamoDB:分布式键/值存储,Dynamo论文的实现;
- Edis:为替代Redis的协议兼容的服务器;
- ElephantDB:专门研究Hadoop中数据导出的分布式数据库;
- EventStore:分布式时间序列数据库;
- GridDB:适用于存储在时间序列中的传感器数据;
- LinkedIn Krati:简单的持久性数据存储,拥有低延迟和高吞吐量;
- Linkedin Voldemort:分布式键/值存储系统;
- Oracle NoSQL Database:Oracle公司开发的分布式键值数据库;
- Redis:内存中的键值数据存储;
- Riak:分散式数据存储;
- Storehaus:Twitter开发的异步键值存储的库;
- Tarantool:一个高效的NoSQL数据库和Lua应用服务器;
- TiKV:由Google Spanner和HBase授权,Rust提供技术支持的分布式键值数据库;
- TreodeDB:可复制、共享的键-值存储,能提供多行原子写入。
图形数据模型
- Apache Giraph:基于Hadoop的Pregel实现;
- Apache Spark Bagel:可实现Pregel,为Spark的一部分;
- ArangoDB:多层模型分布式数据库;
- DGraph:一个可扩展的、分布式、低时延、高吞吐量的图形数据库,旨在为Google生产水平规模和吞吐量提供足够的低延迟,用于TB级的结构化数据的实时用户查询;
- Facebook TAO:TAO是facebook广泛用来存储和服务于社交图形的分布式数据存储;
- GCHQ Gaffer:GCHQ中的Gaffer是一个易于存储大规模图形的框架,其中节点和边缘都有统计数据;
- Google Cayley:开源图形数据库;
- Google Pregel :图形处理框架;
- GraphLab PowerGraph:核心C ++ GraphLab API和建立在GraphLab API之上的高性能机器学习和数据挖掘工具包的集合;
- GraphX:Spark中的弹性分布式图形系统;
- Gremlin:图形追踪语言;
- Infovore:以RDF为中心的Map / Reduce框架;
- Intel GraphBuilder:在Hadoop上构建大规模图形的工具;
- MapGraph:用于在GPU上大规模并行图形处理;
- Neo4j:完全用Java写入的图形数据库;
- OrientDB:文档和图形数据库;
- Phoebus:大型图形处理框架;
- Titan:建于Cassandra的分布式图形数据库;
- Twitter FlockDB:分布式图形数据库。
NewSQL数据库
- Actian Ingres:由商业支持,开源的SQL关系数据库管理系统;
- Amazon RedShift:基于PostgreSQL的数据仓库服务;
- BayesDB:面向统计数值的SQL数据库;
- CitusDB:通过分区和复制横向扩展PostgreSQL;
- Cockroach:可扩展、地址可复制、交易型的数据库;
- Datomic:旨在产生可扩展、灵活的智能应用的分布式数据库;
- FoundationDB:由F1授意的分布式数据库;
- Google F1:建立在Spanner上的分布式SQL数据库;
- Google Spanner:全球性的分布式半关系型数据库;
- H-Store:是一个实验性主存并行数据库管理系统,用于联机事务处理(OLTP)应用的优化;
- Haeinsa:基于Percolator,HBase的线性可扩展多行多表交易库;
- HandlerSocket:MySQL/MariaDB的NoSQL插件;
- InfiniSQL:无限可扩展的RDBMS;
- MemSQL:内存中的SQL数据库,其中有优化的闪存列存储;
- NuoDB:SQL / ACID兼容的分布式数据库;
- Oracle TimesTen in-Memory Database:内存中具有持久性和可恢复性的关系型数据库管理系统;
- Pivotal GemFire XD:内存中低延时的分布式SQL数据存储,可为内存列表数据提供SQL接口,在HDFS中较持久化;
- SAP HANA:是在内存中面向列的关系型数据库管理系统;
- SenseiDB:分布式实时半结构化的数据库;
- Sky:用于行为数据的灵活、高性能分析的数据库;
- SymmetricDS:用于文件和数据库同步的开源软件;
- Map-D:为GPU内存数据库,也为大数据分析和可视化平台;
- TiDB:TiDB是分布式SQL数据库,基于谷歌F1的设计灵感;
- VoltDB:自称为最快的内存数据库。
列式数据库
注意:请在键-值数据模型 阅读相关注释。