91精品国产手机在线-白筒袜嫩萝双腿之间乳白液体-青青操手机在线视频观看-日本中文字幕人妻日韩-日韩精品在线观看视频网站-天堂资源中文最新版在线一区-欧美专区一区二区三区-国产综合亚洲欧美在线-国产精品久久久久久福利69堂

如何設(shè)置內(nèi)存分給顯存 顯存不足

2080Ti其實可以當V100用 , 功能有點強大 。
自深度學習浪潮興起以來 , 該模式一直在向更大、更深的方向發(fā)展 。
2012年 , 擁有五個卷積層的AlexNet首次在視覺任務上展現(xiàn)出了超強的能力 。之后 , 基礎(chǔ)模式開始“深化”:2014年 , VGG網(wǎng)達到19層;2015年的ResNet和2017年的DenseNet已經(jīng)將深度提升到了幾百層 。
模型大小的增加大大提高了性能 。因此 , ResNet、DenseNet等 。被認為是所有主要視覺任務的基本骨干 。但同時 , 機型的增加也意味著對視頻內(nèi)存的需求變得更高 。
為什么GPU內(nèi)存如此重要?
九年前 , 辛頓等人率先用兩個3GB視頻內(nèi)存的GTX 580 GPU高效訓練AlexNet 。此后 , 對視頻內(nèi)存的需求和模型的大小一直同步增長 。想要在游戲中獲得好的成績 , 想要在實驗中超越最先進的效果 , 想要在工程中契合龐大的商業(yè)數(shù)據(jù)等等 。 , 這一切都離不開記憶的加持 。
模型增加一層 , 視頻內(nèi)存會增加一個點 。
在深度學習模型中 , 占用內(nèi)存的總是那些特別大的張量 , 比如各層的權(quán)重矩陣、計算出來的張量(激活值)、反向傳播所需的張量等 。在視覺任務中 , 中間計算的張量占絕大多數(shù) 。隨著模型越來越深、越來越大 , 每一層的激活值張量都需要保存在主存中 。
以ResNet50為例 。在模型的訓練中 , 前向傳播中50層的計算結(jié)果需要存儲在視頻存儲器中 , 以便后向傳播可以使用這些張量來計算梯度 。如果您使用ResNet108 , 您需要的視頻內(nèi)存將是ResNet50的兩倍多 。視頻內(nèi)存的增加 , 當然帶來了模型效果的提升 。另一方面 , 如果沒有足夠的視頻內(nèi)存 , 很多工作將無法完成 。
記憶力不夠 , 寫論文、玩游戲反復受到約束 。
在實驗室運行模型和寫論文的過程中 , 內(nèi)存不足的情況并不少見 。一般實驗室的顯卡都是大家共享的 , 可能大家手里剩下的不多了 。甚至 , 隨著頂級模型變得越來越大 , 沒有人有足夠的計算能力和內(nèi)存來重現(xiàn)最終的實驗 , 更不用說超越它的SOTA結(jié)果了 。
在這種情況下 , 學生只有兩種選擇:向?qū)熒暾埿碌腉PU資源 , 或者縮小模型 , 做一個Mini實驗 。前者不一定成功 , 后者可能有各種不完美 。如果能在內(nèi)存有限的情況下運行頂級模型 , 做實驗和寫論文會更容易 。
此外 , 無論是在學校還是在公司 , 計算能力和內(nèi)存不足都是很常見的 。頂級競爭對手的模式結(jié)構(gòu)可能幾乎相同 。區(qū)別在于誰的模型更大 , 更能處理復雜的樣本 。更直觀的是 , 排行榜領(lǐng)跑者的模型可能只差十幾層 , 但正是因為內(nèi)存限制少于十幾層 , 一些模型才錯過了冠軍 。
內(nèi)存:算法工程的瓶頸
再舉一個常見的例子 , 企業(yè)中的算法工程師有足夠的計算能力 , 內(nèi)存就沒那么重要了 。但是 , 如果只采用并行策略來共享視頻內(nèi)存 , 可能仍然有足夠的視頻內(nèi)存 , 但是每個GPU的計算負載不足 。

如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
4 V100 , 視頻內(nèi)存滿了 , 但是GPU利用率很低 。
即使有V100強大的計算能力 , 在訓練大型機型時也很容易占用16GB的視頻內(nèi)存 。但由于批次大小不足 , 上圖中每個V100 GPU的利用率只有20%到30% 。只有不斷提高每次迭代的數(shù)據(jù)吞吐量 , 才能提高GPU的利用率 。
MegEngine:視頻內(nèi)存需要優(yōu)化 。
其實對于深度學習的從業(yè)者來說 , 日常應用中遠不止以上三種情況 。做深度學習 , 無論是研究還是工程 , 都會時不時遇到記憶問題 。然而 , 這個問題的優(yōu)化非常復雜 , 需要大量的工程實現(xiàn)來緩解 。顯然 , 這樣的優(yōu)化應該由深度學習框架來完成 。但是在實際應用中不難發(fā)現(xiàn) , TensorFlow和PyTorch似乎并沒有提供完美的官方解決方案 。
但如果我們看一下新勢力 , 情況可能就不一樣了 。在最近發(fā)布的開源深度學習框架MegEngine 1.4版本中 , 該框架首次引入了動態(tài)圖形內(nèi)存優(yōu)化技術(shù) , 大大減少了內(nèi)存占用問題 。
具體來說 , MegEngine通過復制和優(yōu)化ICLR 2021 Spotlight論文《動態(tài)張量再物質(zhì)化》(以下簡稱DTR)實現(xiàn)了“為更多視頻內(nèi)存而計算” 。有了這項技術(shù)的加持 , 模型的內(nèi)存占用大大減少 , 同樣的硬件可以訓練更大的模型 , 搭載更大的BatchSize 。這樣 , 學生的小顯卡也可以開始訓練大型號 , 工程師的服務器也可以站得更全應用 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
對于原本需要16GB視頻內(nèi)存的機型 , 優(yōu)化后使用的視頻內(nèi)存峰值降到了4GB 。
MegEngine是一項內(nèi)存優(yōu)化技術(shù) , 它使1060這樣的入門級顯卡能夠訓練只能在2080Ti之前加載的型號 。11GB視頻內(nèi)存的2080Ti可以挑戰(zhàn)原來只能32GB V100訓練的機型 。要知道 , V100的價格是2080Ti的9倍多 。
兩行代碼 , 記憶“加倍”
如果需要優(yōu)化自己的視頻內(nèi)存 , 可能99%的算法工程師都會放棄 。最好的方法是告訴深度學習框架本次訓練會分配多少視頻內(nèi)存 , 剩下的留給框架優(yōu)化 。MegEngine的動態(tài)圖形內(nèi)存優(yōu)化就是基于這個邏輯 。
通過兩行代碼 , 框架可以完全自動優(yōu)化視頻內(nèi)存 , 并在MegEngine中隱藏所有優(yōu)化邏輯和復雜的工程實現(xiàn) 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如上圖所示 , 動態(tài)計算圖中導入了DTR內(nèi)存優(yōu)化模塊 , 內(nèi)存釋放閾值配置為5GB 。在訓練過程中 , 由于視頻內(nèi)存已經(jīng)“翻倍” , 批處理大小可以在翻兩番后加載到GPU中 。
視頻內(nèi)存擴展帶來的收益
在許多情況下 , 提高視頻內(nèi)存利用率的最顯著效果是訓練更大的模型 。在一定程度上 , 參數(shù)數(shù)量越多 , 效果越好 。批量越大 , 梯度更新方向越準確 , 模型性能越好 。MegEngine開發(fā)團隊做了很多實驗 , 在提高視頻內(nèi)存利用率的同時 , 保證了訓練的高質(zhì)量 。
最簡單的驗證方法是不斷增加批處理大小 , 看看顯卡能走多遠 。以下兩個表格分別顯示了DTR技術(shù)在PyTorch和MegEngine上加載或不加載的效果 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如果不使用動態(tài)圖形內(nèi)存優(yōu)化技術(shù) , PyTorch上的模型在一次訓練迭代中最多只能處理64個樣本 , MegEngine最多可以處理100個樣本 。有了DTR , PyTorch模型可以在一次迭代中處理140個樣本 , MegEngine可以嘗試處理300個樣本 。
如果換算成模型大小 , 再加上MegEngine的動態(tài)圖形內(nèi)存優(yōu)化技術(shù) , 在相同的GPU和批處理大小下 , 它可以高效地訓練出增加近5倍的模型 。
MegEngine動態(tài)圖形內(nèi)存優(yōu)化技術(shù)
深度學習模型的內(nèi)存占用一般分為三個部分:權(quán)重矩陣、前向傳播中間張量和后向傳播梯度矩陣(Adam optimizer) 。
權(quán)重矩陣和梯度矩陣占用的內(nèi)存很難優(yōu)化 , 每個模型基本都有固定值 。前向傳播的中間計算結(jié)果不一樣:隨著Batch Size和模型層數(shù)的增加 , 視頻內(nèi)存必然會增加 。如果模型很大 , 中間的計算結(jié)果會占據(jù)最重要的內(nèi)存 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如上圖所示 , 在正向傳播中(第一行從左到右) , 藍色圓圈表示模型的中間計算結(jié)果開始占用視頻內(nèi)存 。直到前向傳播完成 , 第一行完全變成藍圈 , 之前計算占用的視頻內(nèi)存無法釋放 。
當反向傳播開始時(第二行從右向左) , 通過梯度的計算和應用 , 保留在主存儲器中的正向傳播張量可以被釋放 。
顯然 , 要想減少對視頻內(nèi)存的占用 , 就必須使用前向傳播保存的中間計算結(jié)果 , 這也是MegEngine動態(tài)圖形內(nèi)存優(yōu)化的主要方向 。
視頻內(nèi)存的交換計算
動態(tài)計算圖最直接的方法就是用計算或內(nèi)存來交換視頻內(nèi)存 。因此 , MegEngine必須首先決定使用哪種技術(shù) 。
MegEngine團隊通過實驗發(fā)現(xiàn) , 計算時間遠小于交換時間 。例如 , 它從視頻內(nèi)存中節(jié)省了612.5MB 空 , 用帶寬交換視頻內(nèi)存比用計算交換視頻內(nèi)存慢幾十倍到幾百倍 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
因此 , 很明顯 , 動態(tài)計算圖中也應該使用梯度檢查點技術(shù) , 并且應該用計算來交換視頻存儲器 。
下面是梯度檢查點的技術(shù)原理 。前向傳播的第三點是檢查點 , 它將始終存儲在視頻內(nèi)存中 。第四點可以在計算完成后釋放視頻內(nèi)存 。如果反向傳播中需要第四點的值 , 可以從第三點重新計算第四點的值 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
雖然一般原理不難理解 , 但怎么做卻相當復雜 。MegEngine團隊從論文《動態(tài)張量再物質(zhì)化》中學習 , 對其進行了優(yōu)化 , 并在MegEngine中實現(xiàn) 。
DTR , 最先進的內(nèi)存優(yōu)化技術(shù)
DTR是一個完全動態(tài)的啟發(fā)式策略 。核心思想是當視頻內(nèi)存超過一定閾值時 , 動態(tài)釋放一些合適的張量 , 直到視頻內(nèi)存降到閾值以下 。一般來說 , 釋放張量有三個標準:重新計算張量的代價越小越好;占用的視頻內(nèi)存越大越好;在視頻記憶中停留的時間越長越好 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
除了從檢查點恢復前向傳播結(jié)果張量的主要成本外 , DTR的額外成本在于找到應該釋放的最優(yōu)張量 , 即計算上圖中張量T的f(t)值 。為了減少這部分的計算量 , MegEngine還采用了兩種運行時優(yōu)化:
不要考慮小張量 , 它們不加入候選集 。
每次需要釋放一個張量時 , 都會隨機采樣并遍歷幾個張量 , 以節(jié)省計算成本 。
最難的是項目的實現(xiàn) 。
雖然DTR在原則上看起來并不復雜 , 但真正的問題在于提高可用性 , 也就是將所有細節(jié)隱藏在框架的底層 , 只為開發(fā)人員提供最簡單的界面 。
在這里 , 我們使用最簡單的計算示例再次遵循框架計算 , 看看MegEngine如何通過使用動態(tài)圖的計算歷史來恢復和釋放張量 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
現(xiàn)在 , 假設(shè)輸入中有兩個張量A和B , 你想計算a*b和a+b , 但最大內(nèi)存只能容納三個張量 。當黃框計算c=a+b時 , 視頻內(nèi)存仍然可以保留張量c , 但在下一步中 , 當綠框計算d=a*b時 , 只有c可以被釋放 , d才能被保存 。
不幸的是 , 在下一步中 , 灰色框需要得到黃色框的計算結(jié)果 。不過為了節(jié)省視頻內(nèi)存 , C已經(jīng)發(fā)布了 。因此 , MegEngine現(xiàn)在需要做的就是重新運行灰盒的計算圖 , 計算c=a+b , 并加載到視頻內(nèi)存中 。顯然 , 這將不可避免地需要釋放D的視頻內(nèi)存 。
這樣 , 鑒于內(nèi)存的限制 , MegEngine會自動選擇合適的張量釋放 , 并在必要時重新計算 。如果需要重新計算一個張量的結(jié)果 , 比如上圖中的D , 則需要具體的歷史計算信息(這里是像a+b這樣的計算路徑) , 同時需要知道兩個輸入張量A和b 。
所有這樣的歷史計算信息都是由MegEngine自動獲取保存的 , MegEngine的工程師在底層已經(jīng)用C++進行了處理 , 用戶完全不需要考慮 。
struct ComputePath {std::shared_ptr op;SmallVector inputs;SmallVector outputs;double compute_time = 0;} *producer;SmallVector users;size_t ref_cnt = 0;
以上是MegEngine底部用來跟蹤計算路徑信息的結(jié)構(gòu) 。其中op表示生成張量的算子;輸入和輸出分別表示該算子所需的輸入和輸出張量;Compute_time表示操作員的實際運行時間 。
其實在使用MegEngine的過程中 , 所有張量都是用Python接口創(chuàng)建的 , 但是框架會相應地跟蹤每個張量的具體信息 。每當需要訪問張量時 , 無論張量是否在主存中 , 沒有它都可以立即恢復 。所有這些復雜的工程操作和操作邏輯都隱藏在MegEngine C++的底層 。
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
如何設(shè)置內(nèi)存分給顯存 顯存不足

文章插圖
Python代碼將被翻譯成C++底層實現(xiàn) , C++代碼將通過指針(右邊綠色部分)管理顯卡內(nèi)存中的實張量 。
幸運的是 , 這個復雜的操作不需要由算法工程師來完成 , 而是全部留給MegEngine 。
MegEngine可以做的遠不止這些 , 但大部分都像是動態(tài)圖形內(nèi)存優(yōu)化的技術(shù) , 幫助用戶無形中解決實際問題 。2020年3月 , 開源的MegEngine以肉眼可見的速度快速成長 , 從靜態(tài)計算圖到動態(tài)計算圖 , 再到不斷提升的訓練能力、移動終端推理性能的優(yōu)化、動態(tài)內(nèi)存的優(yōu)化...這或許就是開源的魅力所在 。只有不斷的優(yōu)化和創(chuàng)新 , 才能吸引和滿足“挑剔”的開發(fā)者 。MegEngine的下一個功能會是什么?讓我們拭目以待 。
【如何設(shè)置內(nèi)存分給顯存 顯存不足】

    推薦閱讀