<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【NLP】大模型訓(xùn)練之難,難于上青天?預(yù)訓(xùn)練易用、效率超群的「李白」模型庫(kù)來(lái)了!

          共 14781字,需瀏覽 30分鐘

           ·

          2022-07-09 07:12

          機(jī)器之心發(fā)布

          機(jī)器之心編輯部

          LiBai(李白)模型庫(kù)覆蓋了 Hugging Face、Megatron-LM、DeepSpeed、FairSeq 這些所有主流 Transformer 庫(kù)的優(yōu)點(diǎn),讓大模型訓(xùn)練飛入尋常百姓家。
          大模型多了去了,告訴我怎么加速?自 2018 年 BERT 誕生,到 GPT-3、ViT 等擁有數(shù)以億計(jì)的參數(shù)規(guī)模的模型不斷涌現(xiàn),AI 模型參數(shù)量的爆發(fā)式增長(zhǎng)已不足為奇,讓煉丹師無(wú)暇顧及甚至感到麻木。


          與此同時(shí),大模型對(duì)計(jì)算和內(nèi)存資源提出了巨大的挑戰(zhàn)。訓(xùn)練成本急劇上升,比如用一塊非常先進(jìn)的 NVIDIA A100 GPU 訓(xùn)練千億參數(shù)模型的 GPT-3,需要用時(shí) 100 多年。

          大模型對(duì)顯存的需求增長(zhǎng)遠(yuǎn)超過(guò) GPU 顯存增長(zhǎng)的速度,根據(jù) OpenAI 的報(bào)告,模型大小的增長(zhǎng)速度是每 3.5 月翻一倍,而 GPU 顯存則需要 18 個(gè)月才能翻倍。受限于 GPU 顯存,單個(gè) GPU 無(wú)法再容納大規(guī)模模型參數(shù)。

          因此,業(yè)內(nèi)不得不將計(jì)算擴(kuò)展到多個(gè) GPU 設(shè)備上,分布式訓(xùn)練則成為廣大開(kāi)發(fā)者的必然選擇。

          但是分布式訓(xùn)練的門(mén)檻太高,即便擁有充足的計(jì)算資源,也可能因?yàn)楦悴欢ǚ植际接?xùn)練而望洋興嘆。分布式并行編程通常需要工程師了解計(jì)算機(jī)系統(tǒng)和架構(gòu)的專業(yè)知識(shí),再加上相關(guān)的實(shí)踐經(jīng)驗(yàn),這進(jìn)一步增加了探索前沿算法和新模型的難度。凡此種種,使得大模型成為部分科技巨頭的特權(quán)。如何加速模型訓(xùn)練效率,讓更多工程師可以使用、研究大模型成為當(dāng)務(wù)之急。

          問(wèn)題是,市面上那么多支持分布式訓(xùn)練的模型庫(kù),選哪個(gè)最合適?

          近期,由一流科技團(tuán)隊(duì)研發(fā)的以高效性起家的國(guó)產(chǎn)開(kāi)源深度學(xué)習(xí)框架 OneFlow 上線了 LiBai(李白)模型庫(kù),這個(gè)新生代模型庫(kù)覆蓋了 Hugging Face、Megatron-LM、DeepSpeed、FairSeq 這些所有主流 Transformer 庫(kù)的優(yōu)點(diǎn),分布式訓(xùn)練性能一如既往地力壓群雄,更重要的是,全局視角編程最大程度降低了分布式使用門(mén)檻,讓大模型訓(xùn)練飛入尋常百姓家。

          LiBai 模型庫(kù)地址:https://github.com/Oneflow-Inc/libai

          那么,它具體是怎么做到的?以下還將從訓(xùn)練性能、易用性等方面對(duì)上述分布式訓(xùn)練工具做對(duì)比,為你在下一次做分布式訓(xùn)練時(shí)的工具選擇提供參考指南。

          一鍵自動(dòng)分布式訓(xùn)練,性能超越 Megatron-LM 和 DeepSpeed

          作為一個(gè)簡(jiǎn)單高效的分布式模型訓(xùn)練工具箱,具體而言,LiBai 有如下六大特點(diǎn):

          • 支持單卡代碼平滑地?cái)U(kuò)展到分布式。LiBai 內(nèi)置的模型與 PyTorch 保持一致風(fēng)格,大大降低學(xué)習(xí)和使用成本,只需要簡(jiǎn)單配置,就可以便捷地?cái)U(kuò)展至任意規(guī)模的并行。這意味著,你可以在單卡上增加新功能,進(jìn)行模型調(diào)試,跑通代碼后再絲滑地遷移到分布式上進(jìn)行訓(xùn)練。如果完全不想配置分布式訓(xùn)練,或是覺(jué)得手動(dòng)配置的分布式訓(xùn)練太慢,那可以試用分布式托管特性,只需安裝自動(dòng)并行的包(https://libai.readthedocs.io/en/latest/tutorials/basics/Auto_Parallel.html),并在 LiBai 里配置一行 graph.auto_parallel=True,就可以專注于模型本身,在完全不用操心分布式的同時(shí)獲得較快的訓(xùn)練速度。

          • 兼容 Hugging Face。OneFlow 和 PyTorch 在 API 層次高度兼容,可以通過(guò)簡(jiǎn)單的代碼修改就可以導(dǎo)入 Hugging Face 模型,只須 import oneflow as torch ,基于 LiBai 的數(shù)據(jù)并行、自動(dòng)混合精度、Activation Checkpoint、ZeRO 等機(jī)制進(jìn)行一個(gè)大規(guī)模模型的訓(xùn)練。如果把模型的個(gè)別層次替換為 LiBai 內(nèi)置的 layers ,就可以使用 3D 并行來(lái)訓(xùn)練一個(gè)大模型。

          • 模塊化設(shè)計(jì)。在 LiBai 的實(shí)現(xiàn)中,不僅為模型構(gòu)建提供可復(fù)用的基礎(chǔ)計(jì)算模塊,也針對(duì)數(shù)據(jù)加載、訓(xùn)練邏輯、指標(biāo)計(jì)算等做了抽象和模塊化處理,方便用戶根據(jù)自己的需求重寫(xiě),然后作為插件集成到 LiBai 的訓(xùn)練系統(tǒng)中進(jìn)行訓(xùn)練。

          • 開(kāi)箱即用。大模型訓(xùn)練通常需要依賴一些技術(shù),LiBai 提供了混合精度訓(xùn)練、梯度重計(jì)算、梯度累加、ZeRO 等特性,可以輕松與數(shù)據(jù)并行、模型并行、流水并行組合使用。
           
          • 快速?gòu)?fù)現(xiàn)實(shí)驗(yàn)。OneFlow 團(tuán)隊(duì)參考了 Detectron2 LazyConfig(https://github.com/facebookresearch/detectron2/blob/main/docs/tutorials/lazyconfigs.md) 來(lái)構(gòu)建 LiBai 的配置系統(tǒng),相比于傳統(tǒng)的 argparse 和 yacs-based 配置方式,LiBai 的配置系統(tǒng)更加靈活,使用 Python 語(yǔ)法完成整體構(gòu)建,所以添加新的參數(shù)和模塊非常方便,只需要 import 對(duì)應(yīng)的模塊即可完成新模塊的添加。同時(shí),訓(xùn)練配置還可以序列化成 yaml 文件進(jìn)行保存,方便直接在文件中進(jìn)行關(guān)鍵字搜索來(lái)查找配置項(xiàng),如果用戶想要復(fù)現(xiàn)之前的實(shí)驗(yàn)的結(jié)果,也直接傳入保存的 config.yaml 作為訓(xùn)練配置,保留非常多腳本的文件既不利于查看有效修改,在復(fù)現(xiàn)實(shí)驗(yàn)的同時(shí)也容易弄混實(shí)驗(yàn)配置。

          • 高效性能。通過(guò)和 Megatron-LM 進(jìn)行嚴(yán)格的 kernel 對(duì)齊,實(shí)現(xiàn)了多種 kernel fusion 操作,同時(shí)得益于 OneFlow 靜態(tài)圖的設(shè)計(jì),不管是單卡性能還是各種組合并行的效率,LiBai 都優(yōu)于英偉達(dá)深度優(yōu)化的 Megatron-LM 和微軟的 DeepSpeed。

          得益于 OneFlow SBP 原生支持各種并行技術(shù),LiBai 實(shí)現(xiàn)了算法描述和并行系統(tǒng)的解耦,僅用 3 萬(wàn)多行代碼,它就實(shí)現(xiàn)了英偉達(dá) Megatron-LM 和微軟 DeepSpeed 兩大流行方案共計(jì) 10 萬(wàn)行代碼才能涵蓋的功能 。

          數(shù)據(jù)最具說(shuō)服力,以下的所有實(shí)驗(yàn)數(shù)據(jù)均在相同的硬件環(huán)境、相同的第三方依賴(CUDA、 cuDNN 等)、使用相同的參數(shù)和網(wǎng)絡(luò)結(jié)構(gòu)下,全面對(duì)比了 LiBai 和 Megatron-LM 在不同模型下的性能表現(xiàn)(所有性能結(jié)果均公開(kāi)且可復(fù)現(xiàn),https://libai.readthedocs.io/en/latest/tutorials/get_started/Benchmark.html)。未來(lái),OneFlow 團(tuán)隊(duì)會(huì)公布更大規(guī)模集群上 LiBai 的表現(xiàn)。

          • Megatron-LM 固定 commit:https://github.com/NVIDIA/Megatron-LM/commit/e156d2fea7fc5c98e645f7742eb86b643956d840 
          • LiBai commit: https://github.com/Oneflow-Inc/libai/commit/9fc504c457da4fd1e92d854c60b7271c89a55222 
          • OneFlow commit: https://github.com/Oneflow-Inc/oneflow/commit/55b822e4d3c88757d11077d7546981309125c73f 

          數(shù)據(jù)并行

          注:以下每組參數(shù)的含義:

          DP 數(shù)據(jù)并行、MP 模型并行、PP 流水并行、2D 并行、3D 并行

          fp16:打開(kāi)混合精度訓(xùn)練 (amp) 
          nl: num layers  (當(dāng) Pipeline parallel size = 8 時(shí),為了讓每個(gè) stage 有相對(duì)數(shù)量的 layer 進(jìn)行計(jì)算,我們將 num layers 從 24 調(diào)整為 48) 
          ac: enable activation checkpointing 
          mb: micro-batch size per gpu 
          gb: global batch size total 
          dxmxp,其中:  
          d = 數(shù)據(jù)并行度(data-parallel-size)  
          m = 模型并行度(tensor-model-parallel-size)  
          p = 流水并行度(pipeline-model-parallel-size)  
          1n1g 表示單機(jī)單卡,1n8g 表示單機(jī) 8 卡, 2n8g 表示 2 機(jī)每機(jī) 8 卡共 16 卡, 4n8g 表示 4 機(jī)共 32 卡 
          grad_acc_num_step = global_batch_size / (micro_batch_size * data_parallel_size) 展示的結(jié)果為 Throughout



          (注:本組 num layers = 24,開(kāi)啟 amp,1n1g micro-batch size = 24, 其余組 micro-batch size = 16)


          (注:本組 num layers = 24,開(kāi)啟 amp,1n1g micro-batch size = 6, 其余組 micro-batch size = 4)



          模型并行

          (注:本組 num layers = 24,開(kāi)啟 amp, 開(kāi)啟 activation checkpointing,

          micro-batch size = 128, global batch size = 1024, grad acc step = 8)



          (注:本組 num layers = 24,開(kāi)啟 amp)



          流水并行

          (注:前兩組 num layers = 24,grad acc step = 8, 最后一組 num layers = 48, grad acc step = 16,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing)



          (注:前兩組 num layers = 24,grad acc step = 8, 最后一組 num layers = 48, grad acc step = 16,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing)


          2-D 并行

          數(shù)據(jù) + 模型并行

          (注:本組均為 num layers = 24,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing, micro-batch size = 128,grad acc step = 8)


          (注:本組均為 num layers = 24,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing, micro-batch size = 32,grad acc step = 8)


          數(shù)據(jù) + 流水并行

          (注:本組均為 num layers = 24,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing, micro-batch size = 128,grad acc step = 8)



          (注:本組均為 num layers = 24,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing, micro-batch size = 32,grad acc step = 8)



          3-D 并行

          (注:本組均為 num layers = 24,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing,grad acc step = 8)


          (注:本組均為 num layers = 24,均開(kāi)啟 amp,開(kāi)啟 activation checkpointing,grad acc step = 8)


          從上述性能對(duì)比數(shù)據(jù)可以看到,在嚴(yán)格對(duì)齊的實(shí)驗(yàn)環(huán)境下,在 Bert、GPT-2 模型上,LiBai 的訓(xùn)練速度全方位超過(guò) Megatron-LM。

          人有我優(yōu),人無(wú)我有:LiBai vs 其他訓(xùn)練方案

          如前所述,為了解決大模型訓(xùn)練的難題,業(yè)內(nèi)已經(jīng)有 Hugging Face、DeepSpeed 和 Megatron-LM、FairSeq 等流行方案,OneFlow 是否還有必要再研發(fā)一個(gè) LiBai 模型庫(kù)?

          接下來(lái),讓我們具體比較下上述模型庫(kù)的優(yōu)勢(shì)和不足,也許你就會(huì)做出判斷。


          HuggingFace:提供了全面的 SOTA Transformer 模型 ,便于使用預(yù)訓(xùn)練好的模型進(jìn)行微調(diào),提供強(qiáng)大的社區(qū)和生態(tài),方便開(kāi)發(fā)者使用預(yù)訓(xùn)練好的模型。但它只支持?jǐn)?shù)據(jù)并行的方式,如果模型超過(guò)單個(gè) GPU 顯存容量就不適用了,而且想用它做從零開(kāi)始訓(xùn)練速度也比較受限。

          FairSeq:主要針對(duì)序列模型,在 NLP 和 CV 大一統(tǒng)的趨勢(shì)下,缺少對(duì) CV 模型的支持。

          Megatron-LM:基于 PyTorch 實(shí)現(xiàn)了數(shù)據(jù)并行、模型并行和流水并行,性能高,可以用來(lái)真正地訓(xùn)練超大規(guī)模模型。

          不過(guò)它做了大量的定制化,對(duì)于不熟悉分布式訓(xùn)練的算法工程師而言學(xué)習(xí)和使用門(mén)檻太高,基本上只能被分布式專家所復(fù)用。另外,Megatron-LM 提供的模型也遠(yuǎn)遠(yuǎn)少于 Hugging Face,使得想使用 PyTorch 復(fù)現(xiàn)大模型的工程師都必須要等待其他分布式高手基于 Megatron-LM 實(shí)現(xiàn)了自己想用的模型才行。

          DeepSpeed:基于 PyTorch 的模型顯存優(yōu)化相關(guān)的深度定制庫(kù),提供分布式訓(xùn)練、混合精度訓(xùn)練、ZeRO 等技術(shù),可以有效節(jié)約內(nèi)存的開(kāi)銷(xiāo),使得在數(shù)據(jù)并行下也可以有效地訓(xùn)練大模型。但是,DeepSpeed 還不支持模型并行,當(dāng)模型某些層的參數(shù)大到超過(guò)了單個(gè) GPU 的顯存,或是使用 DeepSpeed 的切分方式導(dǎo)致的通信效率不是最優(yōu)時(shí),最好還是使用模型并行(Tensor 并行、流水并行),此時(shí),只能結(jié)合 Megetron-LM 加上侵入原代碼的改造來(lái)滿足需求。

          除了作為 PyTorch 生態(tài)中實(shí)現(xiàn)大模型訓(xùn)練之鼻祖的 Megatron-LM 和 DeepSpeed ,來(lái)自國(guó)內(nèi)外的多家知名機(jī)構(gòu)也研發(fā)和推出了如 FairSeq 等若干大模型訓(xùn)練庫(kù),需要特別指出的是,這些庫(kù)的分布式核心功能無(wú)一例外都是基于 Megatron-LM、DeepSpeed 完成的。

          LiBai 模型庫(kù)的與眾不同之處在于,它不是以上任一分布式訓(xùn)練工具的簡(jiǎn)單升級(jí)或包裝,而是基于 OneFlow 的分布式和圖編譯器能力構(gòu)建的大規(guī)模預(yù)訓(xùn)練模型開(kāi)發(fā)套件。唯有如此,LiBai 不僅在性能上無(wú)出其右,在分布式易用性上更是不遑多讓:

          • 兼容性。可以有效和目前基于 PyTorch 實(shí)現(xiàn)的 SOTA 模型兼容,方便用戶快速遷移模型。
          • 高效性。無(wú)論是單卡還是多卡,用戶使用 LiBai 都可以提高訓(xùn)練效率。
          • 易用性。LiBai 具有優(yōu)秀的擴(kuò)展性,可以很方便地根據(jù)需求修改模型,增加新功能,更快地完成原型功能的開(kāi)發(fā)。以幾乎無(wú)感知、零學(xué)習(xí)成本的方式幫助用戶大幅降低分布式深度學(xué)習(xí)訓(xùn)練的門(mén)檻,用戶在使用 LiBai 開(kāi)發(fā)新模型和新功能時(shí),只要會(huì)單張 GPU 編程就能自動(dòng)擴(kuò)展到大規(guī)模 GPU 的集群,無(wú)須為分布式訓(xùn)練重寫(xiě)代碼,從而提高開(kāi)發(fā)的效率。

          看完上述對(duì)比,相信 LiBai 也會(huì)成為 AI 工程師做分布式訓(xùn)練的絕佳選擇,你覺(jué)得呢?

          LiBai 支持所有常見(jiàn)并行訓(xùn)練策略

          分布式訓(xùn)練大模型是個(gè)復(fù)雜問(wèn)題,涉及到數(shù)據(jù)并行(data parallel),模型并行(tensor/model parallel),流水并行(pipeline parallel)等多種并行策略,LiBai 模型庫(kù)支持這三種常見(jiàn)的并行策略以及這些并行策略的任意組合(并行策略的基本概念:https://docs.oneflow.org/master/parallelism/01_introduction.html)。

          自行實(shí)現(xiàn)這些并行策略讓人十分頭疼,比如以前為了使用自動(dòng)混合精度訓(xùn)練,需要學(xué)習(xí)配置 Apex;為了支持?jǐn)?shù)據(jù)加載流水線,需要學(xué)習(xí)配置 DALI;為了使用 ZeRO 減少顯存占用,需要學(xué)習(xí)配置 DeepSpeed …… 但用 LiBai 就完全不用擔(dān)心這類(lèi)問(wèn)題,它內(nèi)置了多種并行策略且具備良好的可擴(kuò)展性。

          以下是 LiBai 中各類(lèi)并行方法的實(shí)例。

          萬(wàn)能并行的實(shí)現(xiàn)方式

          借助 OneFlow 的 SBP 接口,用戶可以很方便地根據(jù)自身的需求,依照 GPU 的分組排布情況對(duì)網(wǎng)絡(luò)中的輸入或者權(quán)重進(jìn)行切分,以實(shí)現(xiàn)數(shù)據(jù)或張量并行。

          在 LiBai 的 layers 模塊(libai.layers)下,已內(nèi)置一系列可自適應(yīng)不同并行策略的網(wǎng)絡(luò)層,包括常用的 Linear、MLP、Transformer 模塊等,使用 LiBai 的 layers 搭建的神經(jīng)網(wǎng)絡(luò), 只需調(diào)整配置文件中關(guān)于分布式配置的超參,就可以輕松實(shí)現(xiàn)純數(shù)據(jù)并行、純張量并行以及數(shù)據(jù) & 張量混合并行的訓(xùn)練策略。

          關(guān)于分布式配置的格式如下:

          # configs/common/train.py# Distributed argumentsdist=dict(        data_parallel_size=1,        tensor_parallel_size=1,        pipeline_parallel_size=1,)

          通過(guò) data_parallel_size 與 tensor_parallel_size 來(lái)控制輸入數(shù)據(jù)與模型權(quán)重在不同 GPU 組上的切分方式,當(dāng)用戶使用 LiBai 的內(nèi)置 layers 模塊搭建好神經(jīng)網(wǎng)絡(luò)后,可以在自己的訓(xùn)練配置文件中修改分布式超參, 以實(shí)現(xiàn)不同的并行訓(xùn)練策略,上圖所有值都取為 1 表示在單卡上運(yùn)行。假設(shè)用戶擁有一臺(tái) 8 卡機(jī)器,下面介紹一下如何通過(guò)修改此配置文件實(shí)現(xiàn)數(shù)據(jù)并行、張量并行以及流水并行訓(xùn)練。

          具體操作可參考 LiBai 分布式配置文檔:https://libai.readthedocs.io/en/latest/tutorials/basics/Distributed_Configuration.html

          純數(shù)據(jù)并行 & 純模型并行

          當(dāng)用戶要在 8 卡上進(jìn)行純數(shù)據(jù)(或模型)并行訓(xùn)練, 只需要在訓(xùn)練配置文件中對(duì)分布式超參進(jìn)行覆寫(xiě)即可:

          • 純數(shù)據(jù)并行

          # your config.pyfrom libai.config import get_configtrain = get_config("common/train.py").train
          train.dist.data_parallel_size = 8

          訓(xùn)練時(shí),在不同的 rank 上會(huì)復(fù)制一份相同的模型,每個(gè) rank 會(huì)分別處理一部分的輸入數(shù)據(jù), 以實(shí)現(xiàn)數(shù)據(jù)并行訓(xùn)練。

          • 純模型并行

          # your config.pyfrom libai.config import get_configtrain = get_config("common/train.py").train
          train.dist.tensor_parallel_size = 8

          在這種情況下, 模型會(huì)自動(dòng)在 8 個(gè) GPU 上進(jìn)行切分, 每個(gè) GPU 僅包含整體模型結(jié)構(gòu)的一部分, 以實(shí)現(xiàn)模型并行訓(xùn)練。

          數(shù)據(jù) & 模型混合并行訓(xùn)練

          當(dāng)用戶要在 8 卡上進(jìn)行數(shù)據(jù)與模型混合并行訓(xùn)練, 只需要在訓(xùn)練配置文件中對(duì)分布式超參進(jìn)行以下簡(jiǎn)單改動(dòng):

          # your config.pyfrom libai.config import get_configtrain = get_config("common/train.py").train
          train.dist.data_parallel_size = 2train.dist.tensor_parallel_size = 4

          這種情況下,  LiBai 會(huì)自動(dòng)對(duì) GPU 進(jìn)行分組, 我們以 [0, 1, 2, 3, 4, 5, 6, 7] 對(duì) 8 個(gè) GPU 進(jìn)行編號(hào),當(dāng)設(shè)置了 data_parallel_size=2 以及 tensor_parallel_size=4 后,在執(zhí)行時(shí),會(huì)自動(dòng)將 8 個(gè) GPU 進(jìn)行分組,可以表示為 [[0, 1, 2, 3], [4, 5, 6, 7]], 其中[0, 1, 2, 3] 為一組,[4, 5, 6, 7]為一組,執(zhí)行時(shí),會(huì)在組之間進(jìn)行數(shù)據(jù)并行訓(xùn)練,在組內(nèi)進(jìn)行模型并行訓(xùn)練。

          流水并行的配置

          流水并行的核心概念可以簡(jiǎn)單總結(jié)為:將網(wǎng)絡(luò)分為多個(gè)階段(stage), 不同的 stage 被分發(fā)到不同的 GPU 上, 每個(gè) stage 的計(jì)算結(jié)果傳遞給下一個(gè) stage 進(jìn)行計(jì)算,最終按接力的方式完成訓(xùn)練。關(guān)于流水并行的具體內(nèi)容可參考:https://docs.oneflow.org/master/parallelism/01_introduction.html#_6。

          樸素流水并行配置

          在 LiBai 下可以通過(guò)設(shè)置 placement 參數(shù),將網(wǎng)絡(luò)的不同層分配到不同的 GPU 上,placement 參數(shù)的值可以通過(guò) libai.utils.distributed 下的 get_layer_placement()接口輕松配置,LiBai 會(huì)自動(dòng)根據(jù)配置文件(config)中的分布式配置,來(lái)做 stage 的切分,將不同的 placement 自動(dòng)分配到不同的 stage 上,所以只需要為網(wǎng)絡(luò)的每一層配置好 placement,再結(jié)合分布式配置,便可以輕松實(shí)現(xiàn)流水并行配置。

          在大部分網(wǎng)絡(luò)中,往往用一層 Linear 層作為網(wǎng)絡(luò)的頭部(head), 產(chǎn)生網(wǎng)絡(luò)的最終結(jié)果用作分類(lèi)或者其他任務(wù), 所以以 Linear 層為例, 簡(jiǎn)要介紹 LiBai 中最簡(jiǎn)單的流水并行配置方法:

          from libai.layers import Linear
          self.head = Linear(hidden_size, num_classes)

          配置網(wǎng)絡(luò)模塊(module)的 placement

          在 LiBai 中可以通過(guò)兩種方式將一層網(wǎng)絡(luò)分配到對(duì)應(yīng)的 placement 上:

          1、通過(guò) to_global 接口結(jié)合 get_layer_placement()來(lái)手動(dòng)指定 placement, 這里通過(guò)設(shè)置 get_layer_placement(-1)來(lái)將 head 層配置到最后一組接力的 placement 上。

          from libai.layers import Linearimport libai.utils.distributed as dist
          self.head = Linear(hidden_size, num_classes).to_global(placement=dist.get_layer_placement(-1))

          2、(Recommended) 在 libai.layers 中實(shí)現(xiàn)的 module 自帶 layer_idx 參數(shù), 可以直接設(shè)置 layer_idx 參數(shù)來(lái)指定這一層的 placement

          from libai.layers import Linear
          self.head = Linear(hidden_size, num_classes, layer_idx=-1)

          配置輸入數(shù)據(jù)的 placement

          在配置好了網(wǎng)絡(luò)中模塊的 placement 后, 還需要指定輸入數(shù)據(jù)的 placement, 因?yàn)橹挥挟?dāng)輸入和網(wǎng)絡(luò)在同一個(gè) stage 的時(shí)候才可以進(jìn)行計(jì)算, 最直觀的方式就是為輸入和網(wǎng)絡(luò)配置相同的 placement, 可以結(jié)合 to_global 與 get_layer_placement()實(shí)現(xiàn):

          class MyModule(nn.Module):    def __init__(self, ... *, layer_idx):        ...        self.layer_idx = layer_idx        ...
          def forward(self, input_data): input_data = input_data.to_global(placement=dist.get_layer_placement(self.layer_idx)) ...

          結(jié)合配置文件輕松實(shí)現(xiàn)樸素流水并行

          在配置好網(wǎng)絡(luò)中不同層的 placement 以及輸入的 placement 后,在執(zhí)行流水并行前,用戶只需要調(diào)整配置文件(config)即可,需要提前知道網(wǎng)絡(luò)中的層數(shù),并且調(diào)整配置文件中的 pipeline_num_layers:

          # set the number of pipeline stages to be 2train.dist.pipeline_parallel_size = 2
          # set model layers for pipelinetrain.dist.pipeline_num_layers = hidden_layers

          1F1B 是在 PipeDream(https://arxiv.org/pdf/1806.03377.pdf)中介紹的一種新的流水并行訓(xùn)練方式,可以更好地節(jié)省顯存與利用資源。LiBai 也可以比較容易地支持這種 1F1B 的策略(https://github.com/Oneflow-Inc/libai/blob/main/docs/source/tutorials/advanced_tutorials/customize_dataloader.md)

          3D 并行的實(shí)現(xiàn)

          掌握了數(shù)據(jù) & 模型混合并行,以及流水并行以后,配置數(shù)據(jù) + 模型 + 流水并行也只是綜合一下上述各種并行的改動(dòng)即可。

          # your config.pyfrom libai.config import get_configtrain = get_config("common/train.py").train
          train.dist.data_parallel_size = 2train.dist.tensor_parallel_size = 2train.dist.pipeline_parallel_size = 2
          hidden_layers = 8 #網(wǎng)絡(luò)的層數(shù)train.dist.pipeline_num_layers = hidden_layers

          還是以 8 卡作為例子,在設(shè)置 data_parallel_size,tensor_parallel_size, pipeline_parallel_size 都為 2 以后,在執(zhí)行時(shí),模型將根據(jù)用戶設(shè)置的 pinepine_num_layers 在 GPU 上自動(dòng)進(jìn)行劃分。 

          以上述配置為例,模型將在 [0, 1, 2, 3] 和[4, 5, 6, 7]號(hào) GPU 上拆分為 2 個(gè) stage。其中,stage0 會(huì)在 [0, 2] 和[1, 3]號(hào) GPU 上數(shù)據(jù)并行;在 [0, 1] 和[2, 3]號(hào) GPU 上模型并行;stage1 會(huì)在 [4, 6] 和[5, 7]號(hào) GPU 上數(shù)據(jù)并行;在 [4, 5] 和[6, 7]號(hào) GPU 上模型并行。

          自定義并行訓(xùn)練

          根據(jù)上文的介紹,LiBai 在 libai/layers / 下提供了封裝好的模塊供用戶調(diào)用。通過(guò)這些模塊的組合,用戶可以拼湊出自己的并行網(wǎng)絡(luò)。

          當(dāng) LiBai 中的模塊無(wú)法滿足用戶需求時(shí),用戶也可以非常方便地自定義并行策略。不同于 PyTorch 下需要手工插入 scatter -> forward -> reduce 等一系列復(fù)雜的通信操作,在 LiBai 中,用戶只需在初始化 tensor 時(shí)定義 sbp 和 placement,便可像寫(xiě)單機(jī)運(yùn)行的代碼一樣跑起來(lái)自己的并行代碼。(sbp 和 placement 的詳情可參考:https://docs.oneflow.org/master/parallelism/04_2d-sbp.html)。

          舉例來(lái)說(shuō),在用戶進(jìn)行 4 卡訓(xùn)練時(shí),網(wǎng)絡(luò)的中間結(jié)果有一個(gè) shape 為 (16, 8) 的 2D Parallel 的 tensor 在 GPU 上的劃分方式為如下圖, 在 LiBai 中。該 tensor 的 placement 分布為 ranks=[[0, 1],[2, 3]],SBP 為 (S[0], S[1]) 或(S[1], S[0])。

          [            |       X00 gpu0 |  X01 gpu1--------------------------    X10 gpu2 |  X11 gpu3             |           ]

          其中, Xij 的 shape 都為 (8, 4) 均勻的分布在每張卡上, 如果你想對(duì)這個(gè) tensor 加入一些隨機(jī)噪聲,那么在 LiBai 中可以非常方便地加上如下代碼:

          LiBai 中封裝 dist.get_nd_sbp()是為了兼容 1D parallel 的需求,同時(shí) dist.get_layer_placement()是為了方便配置 pipeline parallel。大多數(shù)情況下,用戶可以直接參照以下代碼:


          # test.pyimport oneflow as flowfrom omegaconf import DictConfigfrom oneflow import nn
          from libai.utils import distributed as dist
          cfg = DictConfig( dict(data_parallel_size=2, tensor_parallel_size=2, pipeline_parallel_size=1))dist.setup_dist_util(cfg)

          class Noise(nn.Module): def __init__(self): super().__init__() self.noise_tensor = flow.randn( 16, 8, sbp=dist.get_nd_sbp([flow.sbp.split(0), flow.sbp.split(1)]), placement=dist.get_layer_placement(layer_idx=0) ) # 也可以換成以下的寫(xiě)法 # self.noise_tensor = flow.randn( # 16, 8, # sbp=(flow.sbp.split(0), flow.sbp.split(1)), # placement=flow.placement("cuda", ranks=[[0, 1],[2, 3]]) # )
          def forward(self, x): return x + self.noise_tensor

          Noise = Noise()
          x = flow.zeros( 16, 8, sbp=(flow.sbp.split(0), flow.sbp.split(1)), placement=flow.placement("cuda", ranks=[[0, 1],[2, 3]]))y = Noise(x)
          print(f"rank: {flow.env.get_rank()}, global tensor: shape {y.shape} sbp {y.sbp} placement {y.placement}, local tensor shape: {y.to_local().shape}")


          運(yùn)行指令:

          python3 -m oneflow.distributed.launch --nproc_per_node 4 test.py

          以下顯示輸出,根據(jù) shape 可以看到每個(gè) rank 下 tensor 的分布,以及在 global 視角下該 tensor 的信息。

          rank: 2, global tensor: shape oneflow.Size([16, 8]) sbp (oneflow.sbp.split(axis=0), oneflow.sbp.split(axis=1)) placement oneflow.placement(type="cuda", ranks=[[0, 1], [2, 3]]), local tensor shape: oneflow.Size([8, 4])rank: 3, global tensor: shape oneflow.Size([16, 8]) sbp (oneflow.sbp.split(axis=0), oneflow.sbp.split(axis=1)) placement oneflow.placement(type="cuda", ranks=[[0, 1], [2, 3]]), local tensor shape: oneflow.Size([8, 4])rank: 1, global tensor: shape oneflow.Size([16, 8]) sbp (oneflow.sbp.split(axis=0), oneflow.sbp.split(axis=1)) placement oneflow.placement(type="cuda", ranks=[[0, 1], [2, 3]]), local tensor shape: oneflow.Size([8, 4])rank: 0, global tensor: shape oneflow.Size([168]) sbp (oneflow.sbp.split(axis=0), oneflow.sbp.split(axis=1)) placement oneflow.placement(type="cuda", ranks=[[01], [23]]), local tensor shape: oneflow.Size([84])

          未來(lái)計(jì)劃


          LiBai 目前已支持 BERT、GPT、ViT、Swin-Transformer、T5 等常見(jiàn)模型,以及 MoCoV3、MAE 等最新研究,開(kāi)箱即用,并且可以很方便地在下游任務(wù)上進(jìn)行微調(diào)。

          此外,OneFlow 也會(huì)更好地兼容 Hugging Face 的模型,接入其生態(tài),同時(shí)再利用 OneFlow 自動(dòng)并行功能,幫助用戶享受只寫(xiě)單卡代碼即自動(dòng)擴(kuò)展到分布式系統(tǒng)的一勞永逸的激爽體驗(yàn)。

          未來(lái),在支持更多模型訓(xùn)練的基礎(chǔ)上,OneFlow 也會(huì)持續(xù)完善推理和 Serving 相關(guān)的功能,從而打通訓(xùn)練和部署的全流程,讓 OneFlow 成為用戶的一站式開(kāi)發(fā)平臺(tái)。

          • LiBai 模型庫(kù)地址:https://github.com/Oneflow-Inc/libai
          • LiBai 文檔地址:https://libai.readthedocs.io/en/latest
          • OneFlow 項(xiàng)目地址:https://github.com/Oneflow-Inc/oneflow

          ? THE END 

          轉(zhuǎn)載請(qǐng)聯(lián)系本公眾號(hào)獲得授權(quán)

          投稿或?qū)で髨?bào)道:[email protected]

          往期精彩回顧




          瀏覽 80
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲视频中文字幕在线观看 | 亚洲最色网站 | 欧美日韩黄色片 | 成人娱乐中文字幕 | 久久久久少妇 |