<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>

          工程Tricks | PyTorch有什么節(jié)省顯存的小技巧?

          共 3130字,需瀏覽 7分鐘

           ·

          2021-11-27 00:15

          來源 | 知乎問答

          地址?|?https://www.zhihu.com/question/274635237

          本文僅作學(xué)術(shù)分享,若侵權(quán)請聯(lián)系后臺刪文處理


          01

          回答一:作者-朱小霖

          節(jié)省顯存方面,歡迎關(guān)注我們團(tuán)隊最近開源的工作:https://github.com/Tencent/PatrickStar

          個人認(rèn)為這個工作把單卡訓(xùn)練,或者是數(shù)據(jù)并行下的顯存節(jié)省做到極致了~

          這里主要介紹一下單機(jī)訓(xùn)練上的思路。

          隨著模型越來越大,GPU 逐漸從一個計算單元變成一個存儲單元了,顯存的大小限制了能夠訓(xùn)練的模型大小。微軟的 DeepSpeed 團(tuán)隊提出我們其實可以把優(yōu)化器狀態(tài)(Adam 的 momentum 和 variance)放在 CPU 上,用一個實現(xiàn)的比較快的 CPU Adam 來做更新,這樣既不會變慢很多,也可以明顯省出來很多空間。我們把這個思想再往前推一步,我們是不是可以只把需要計算的模型參數(shù)放在 GPU 上,其余的模型參數(shù),優(yōu)化器狀態(tài)都放在 CPU 上,這樣就可以盡最大能力降低對顯存的需求,讓 GPU 回歸它計算單元的本色。

          為了達(dá)成這樣的效果,我們就需要一個動態(tài)的顯存調(diào)度——相對于 DeepSpeed 在訓(xùn)練前就規(guī)定好哪些放在 CPU 上,哪些放在 GPU 上,我們需要在訓(xùn)練過程中實時把下一步需要的模型參數(shù)拿到 GPU 上來。利用 pytorch 的 module hook 可以讓我們在每個 nn.Module 前后調(diào)用回調(diào)函數(shù),從而動態(tài)把參數(shù)從 CPU 拿到 GPU,或者放回去。

          但是,相信大家能夠想象到,如果每次都運(yùn)行到一個 submodule 前,再現(xiàn)把參數(shù)傳上來,肯定就很慢,因為計算得等著 CPU-GPU 的傳輸。為了解決計算效率的問題,我們提出了 chunk-based management。這是什么意思呢?就是我們把參數(shù)按照調(diào)用的順序存儲在了固定大小的 chunk 里(一般是 64M 左右),讓內(nèi)存/顯存的調(diào)度以 chunk 為單位,第一次想把某個 chunk 中的參數(shù)放到 GPU 來的時候,就會直接把整個 chunk 搬到 GPU,這意味著雖然這一次的傳輸可能需要等待,但是在計算下一個 submodule 的時候,因為連著的 module 的參數(shù)都是存在一個 chunk 里的,這些參數(shù)已經(jīng)被傳到 GPU 上來了,從而實現(xiàn)了 prefetch,明顯提升了計算效率。同時,因為 torch 的 allocator 會緩存之前分配的顯存,固定大小的 chunk 可以更高效利用這一機(jī)制,提升顯存利用效率。

          在 chunk 的幫助下,我們的模型可以做到,CPU 內(nèi)存加 GPU 顯存有多大,模型就能訓(xùn)多大。和 DeepSpeed 相比,在同等環(huán)境下模型規(guī)??梢蕴嵘?50%,計算效率(Tflops)也更高。

          448cdda9d27f60adc776e1737ea71659.webp對于多卡的數(shù)據(jù)并行場景,我們擴(kuò)展了上述方法,可以做到多卡中只有 1 整份模型,1 整份優(yōu)化器狀態(tài),同時具備了數(shù)據(jù)并行的易用性和模型并行的顯存使用效率。如果想了解多卡訓(xùn)練的方案,以及更詳細(xì)的一些優(yōu)化,也歡迎來看看我們的論文:https://arxiv.org/abs/2108.05818

          02

          回答二:作者-鄭哲東

          在不修改網(wǎng)絡(luò)結(jié)構(gòu)的情況下, 有如下操作:

          1.同意@Jiaming, ?盡可能使用inplace操作, 比如relu 可以使用 inplace=True 。一個簡單的使用方法,如下:

          def?inplace_relu(m):
          ????classname?=?m.__class__.__name__
          ????if?classname.find('ReLU')?!=?-1:
          ????????m.inplace=True

          model.apply(inplace_relu)

          2.進(jìn)一步,比如ResNet 和 DenseNet 可以將 batchnorm 和relu打包成inplace,在bp時再重新計算。使用到了pytorch新的checkpoint特性,有以下兩個代碼。由于需要重新計算bn后的結(jié)果,所以會慢一些。

          • https://github.com/gpleiss/efficient_densenet_pytorch

          • https://github.com/mapillary/inplace_abn

          ae2a16ef39b564033260f196dd9d7547.webp

          3. 每次循環(huán)結(jié)束時 刪除 loss,可以節(jié)約很少顯存,但聊勝于無??梢娙缦耰ssue

          https://discuss.pytorch.org/t/tensor-to-variable-and-memory-freeing-best-practices/6000/2

          4. 使用float16精度混合計算。我用過NVIDIA的apex,很好用,可以節(jié)約將近50%的顯存,但是要小心一些不安全的操作如 mean和sum,溢出fp16。

          https://github.com/NVIDIA/apex

          81c1ccb1e0688ef730252a8bcbb5befa.webp

          補(bǔ)充:最近我也嘗試在我CVPR19的GAN模型中加入fp16的訓(xùn)練,可以從15G的顯存需求降到約10G,這樣大多數(shù)1080Ti等較為常見的顯卡就可以訓(xùn)練了。歡迎大家star一波 https://github.com/NVlabs/DG-Net

          5. 對于不需要bp的forward,如validation 請使用 torch.no_grad , ?注意model.eval() 不等于 torch.no_grad() 請看如下討論。

          https://discuss.pytorch.org/t/model-eval-vs-with-torch-no-grad/19615

          6. torch.cuda.empty_cache() 這是del的進(jìn)階版,使用nvidia-smi 會發(fā)現(xiàn)顯存有明顯的變化。但是訓(xùn)練時最大的顯存占用似乎沒變。大家可以試試。

          https://discuss.pytorch.org/t/how-can-we-release-gpu-memory-cache/14530

          另外,會影響精度的騷操作還有:

          把一個batchsize=64分為兩個32的batch,兩次forward以后,backward一次。但會影響 batchnorm等和batchsize相關(guān)的層。

          相關(guān)鏈接:老外寫的提高pytorch效率的方法,包含data prefetch等

          https://sagivtech.com/2017/09/19/optimizing-pytorch-training-code/

          03

          回答三:作者-Lyken

          咦,大家都沒看過陳天奇的 Training Deep Nets with Sublinear Memory Cost 嗎?

          訓(xùn)練 CNN 時,Memory 主要的開銷來自于儲存用于計算 backward 的 activation,一般的 workflow 是這樣的

          03baba04f84e022e01a5c206bc37f341.webp

          Vanilla backprop

          對于一個長度為 N 的 CNN,需要 O(N) 的內(nèi)存。這篇論文給出了一個思路,每隔 sqrt(N) 個 node 存一個 activation,中需要的時候再算,這樣顯存就從 O(N) 降到了 O(sqrt(N))。

          232186ccad82c5ffbc6f87cbf2d56859.webp

          Checkpointed backprop

          對于越深的模型,這個方法省的顯存就越多,且速度不會明顯變慢。

          3dda1af4fef955244308d58337316b95.webp

          PyTorch 我實現(xiàn)了一版,有興趣的同學(xué)可以來試試 https://github.com/Lyken17/pytorch-memonger


          往期精彩:

          ?時隔一年!深度學(xué)習(xí)語義分割理論與代碼實踐指南.pdf第二版來了!

          ?新書預(yù)告 | 《機(jī)器學(xué)習(xí)公式推導(dǎo)與代碼實現(xiàn)》出版在即!

          瀏覽 110
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <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>
                  欧美性爱网址在线观看 | 亚洲国产日韩在线一区 | 亚洲www色 | 麻豆91精品人妻成人无码 | 黄片免费观看 |