1. 程式人生 > >史上最全面的深度學習硬體指南

史上最全面的深度學習硬體指南

轉載自:

http://it.sohu.com/20160204/n436921549.shtml

英語原文來自: 

http://timdettmers.com/2015/03/09/deep-learning-hardware-guide/

選自timdettmers

  機器之心翻譯出品

  參與:chenxiaoqing,微胖,Ben ,20e,柒柒,wei

深度學習計算密集,所以你需要一個快速多核CPU,對吧?還是說買一個快速CPU可能是種浪費?搭建一個深度學習系統時,最糟糕的事情之一就是把錢浪費在並非必需的硬體上。本文中,我將一步步帶你瞭解一個高效能經濟系統所需的硬體。

研究並行化深度學習過程中,我搭建了一個GPU叢集,為此,我需要仔細挑選硬體。儘管經過了仔細的研究和邏輯推理,但是,挑選硬體時,我還是會犯相當多的錯誤,當我在實踐中應用叢集時,錯誤就會顯現出來。下面就是我想分享的東西,希望你們可以不要再掉入同樣的陷阱。

  GPU

  在這篇博文中,我們假設你會利用GPU來進行深度學習。如果你正在構建或升級你的深度學習系統,忽視GPU是不理智的。GPU正是深度學習應用的核心要素——計算效能提升上,收穫巨大,不可忽視。

我在以前的部落格中詳細談到過GPU的選擇,GPU的選擇也許是深度學習系統中最關鍵的選擇。當前市場上的GPU:通常來說,如果你缺錢,我推薦到eBay上購買GTX 680,或者GTX Titan X(如果你很有錢,用來做卷積),或者GTX 980(非常有價效比,但對於大型卷積神經網路有點侷限),另外如果你需要一個低成本的儲存則可以選擇GTX Titan。我之前支援過GTX 580,但是由於cnDNN庫的新升級大幅增加了卷積的速度,所有不支援cuDNN的GPU都得淘汰了——GTX 580就是這樣的一個GPU。如果你完全不使用卷積神經網路,那麼GTX 580仍然是一個可靠的選擇。

Suspect line-up嫌疑人清單:你能夠識別哪個硬體是糟糕表現的罪魁禍首嗎?這些GPU之一?或者還是CPU的錯?

  CPU

為了能夠明智地選擇CPU我們首先需要理解CPU,以及它是如何與深度學習相關聯的,CPU能為深度學習做什麼呢?當你在GPU上跑深度網路時,CPU進行的計算很少,但是CPU仍然需要處理以下事情:

在程式碼中寫入並讀取變數

執行指令,如函式呼叫

啟動在GPU上函式呼叫

建立小批量資料

啟動到GPU的資料傳輸

所需CPU核的數量

當我用三個不同的庫訓練深度學習網路時,我經常觀察到一個CPU執行緒顯示100%(並且有時候另一個執行緒會在0-100%之間浮動),你會立刻知道大部分深度學習庫——以及實際上大部分通用軟體應用——僅僅只利用一個執行緒。這意味著多核CPU非常無用。但如果你執行多GPU,並使用像MPI一樣的並行化框架,那麼你就同時運行了多個程式,你也會需要多個執行緒。每個GPU跑一個執行緒還不錯,但是每個GPU跑兩個執行緒對於大部分深度學習庫來說能夠帶來更好的表現;這些庫在單核上執行,但是某些時候呼叫非同步函式則會用到第二個CPU執行緒。記住許多CPU能夠在每一個核上執行多個執行緒(尤其對於Intel的CPU來說),因此每個GPU對應一個CPU核通常就夠了。

CPU與PCI-Express

這裡是個陷阱!一些新型號Haswell CPU並不支援全部40個PCIe通道,而舊的CPU則可以——避免這些CPU,如果你希望建立一個多GPU的系統。並且確保你的處理器確定能夠支援PCIe3.0,如果你的主機板採用PCIe 3.0。

CPU快取大小

正如我們之後會看到的,CPU快取大小與CPU-GPU下游管道運算沒有關聯,但是我會用一個簡短的部分來說明,這樣我們就可以確定計算管道上每個可能的瓶頸都被考慮在內,從而全面理解整個過程。

人們購買CPU時經常會忽視快取這個問題,但是通常來說,它在整個效能問題中是非常重要的一部分。CPU快取是容量非常小的直接位於CPU晶片上的儲存,物理位置非常接近CPU,能夠用來進行高速計算和操作。CPU通常有快取分級,從小型快取記憶體(L1,L2)到低速大型快取(L3,L4)。作為一個程式設計師,你可以將它想成一個雜湊表,每條資料都是一個鍵值對(key-value-pair),可以高速的基於特定鍵進行查詢:如果找到,就可以在快取得值中進行快速讀取和寫入操作;如果沒有找到(被稱為快取未命中),CPU需要等待RAM趕上,之後再從記憶體進行讀值——一個非常緩慢的過程。重複的快取未命中會導致效能的大幅下降。有效的CPU快取方案與架構對於CPU效能來說非常關鍵。

CPU是如何決定它的快取方案是一個複雜的話題,但是通常來說,重複使用的變數、指令和記憶體RAM地址會儲存在快取中,而不經常出現的則不會。

在深度學習中,對於每一個小批量資料單元相同的記憶體範圍會重複進行讀取直至送至GPU(同時這塊記憶體範圍會被新資料覆蓋),但是記憶體資料是否能夠被儲存在快取中則取決於小批量單元大小。對於128的小批量單元的大小,我們會有相對應的0.4MB的MNIST資料與1.5MB的CIFAR資料,能夠放入大部分CPU快取。對於ImageNet來說,我們每個小批量單元有超過85MB的資料,這即使對於最大的快取(L3快取僅僅有幾個MB)來說也實在太大了。

由於通常資料集對於快取太過巨大,每一批新的小批量處理單元資料都需要從記憶體RAM中進行讀取——因此對記憶體RAM的訪問是持續在進行。

記憶體RAM記憶地址儲存於快取中(CPU能夠在快取中迅速查詢,指出資料在RAM中的確切地址),但是這隻在整個資料集都儲存於RAM的時候才能如此,否則記憶地址會改變,快取也不會加速(你可能會想利用固定保留地址避免這種情況,但是就像你之後會看到的,其實這也沒有意義)。

深度學習程式碼的其他部分——例如變數與函式呼叫——則會從快取中受益,但是這些通常都數量很少,並且很容易就儲存於幾乎所有CPU的小型快速L1快取中。

從這些推論中可以總結一下,CPU快取大小並不是很重要,下一部分的深層分析則會繼續闡述這個結論。

尋找合適的CPU時鐘頻率(頻率)

當人們想到快速的CPU時,他們一般最先想到其時鐘頻率(clock rate)。4GHz比3.5GHz快,是這樣嗎?在比較具有相同架構的處理器時,這一般是對的,例如「第三代酷睿處理器」(Ivy Bridge)。但在比較不同架構的處理器時,這個想法卻不那麼正確。而且這也不總是對於效能的最好測量指標。

在深度學習中,只有很少一部分的計算會用CPU來執行:增值幾個變數、評估幾個布林表示式、在GPU或在程式設計裡面呼叫幾個函式——所有這些會取決於CPU核的頻率。

這種推理似乎是合理的,但當我執行深度學習程式設計的時候,CPU會有100%的使用率,那這是怎麼回事兒?為了找出原因,我做了一些CPU核頻率降頻的實驗。

  CPU降頻後在MNIST及ImageNet的表現:使用不同的CPU核頻率,將MNIST資料集執行200遍或遍歷1/4的ImageNet資料集執行作為測量時間,我們測量CPU的效能,其中我們將每個CPU的最高頻率定位參照線。對於比較:在效能上,GTX Titan比GTX 680提升了15%;GTX 980比GTX Titan提升了20%;GPU超頻比任何GPU提升了5%。

問題是:為什麼當CPU核頻率是無關緊要的的時候,它會用上100%的使用率?答案可能是CPU的快取記憶體未命中:一般情況下,CPU會不斷忙於訪問RAM,與此同時,它需要一直等待頻率較慢的RAM跟上步伐,因此這可能導致了即忙碌著等待中的矛盾狀態。如果真是這樣,將CPU核降頻將不會導致其效能的大幅降低——正如你在上面看到的結果。

CPU也執行其他一些操作,如將資料抄到微型批次裡,並將資料準備好以便複製到GPU,但這些操作其實只取決於記憶體頻率,而不是CPU核頻率。所以我們現在來看看記憶體。

尋找合適的RAM頻率

CPU-RAM以及其他裝置與RAM的互動都式非常複雜的。我在這兒會給出該互動過程的一個簡化版。為了得到一個更為全面的理解,讓我們潛入其中並剖析從CPU RAM 到 GPU RAM的這一過程。

CPU的記憶體頻率與RAM是相互交織的。CPU的記憶體頻率決定了RAM的最大頻率,並且這兩個東西結合起來構成了CPU整體記憶體的頻寬。但通常RAM本身決定了整體可使用的頻寬,因為它可以比CPU的記憶體頻率更慢。你可以如此決定頻寬,其中64是64位的CPU結構。而我的處理器及RAM模組的頻寬是51.2GB/s。

那麼這與深度學習程式有什麼關係?我剛剛說頻寬有可能是重要的,但在下一個步驟中,它還不是那麼重要。RAM的頻寬決定了小批次資料對應記憶體被覆蓋並被分配來啟動一次到GPU資料傳輸上有多快,但在下一個步驟,從 CPU-RAM到GPU-RAM,才真正是瓶頸了,此步驟利用了直接儲存器存取(DMA)。正如上面所引述的,我的RAM模組的記憶體頻寬是51.2GB/s,但DMA頻寬卻只有12GB/s!

DMA頻寬與一般的頻寬相關,但細節是不太需要知道的,你可以看看這個維基百科條目(http://en.wikipedia.org/wiki/DDR3_SDRAM#JEDEC_standard_modules),你能在此查閱RAM模組的DMA頻寬(峰值傳輸限制)。但先讓我們看看DMA是如何工作的。

直接儲存存取(DMA)

CPU和其對應的RAM只能透過DMA與GPU通訊。第一步,一個特定的DMA傳輸緩衝器在CPU RAM 及 GPU RAM裡被保留;第二步,CPU將所請求的資料寫入CPU那邊的DMA緩衝器裡;第三步,受保留的緩衝器在沒有CPU的幫助下被轉移到GPU RAM裡。你的PCIe的頻寬是8GB/s (PCIe 2.0) 或是 15.75GB/s (PCIe 3.0),所以你需要買一個像上面所說的,具有良好峰值傳輸限制的RAM嗎?

未必。軟體在這裡起著很大的作用。如果你用聰明的方法來做一些傳輸的話,你將可以能利用更便宜更慢的記憶體來完成任務。

非同步的微批次分配

一旦你的GPU在當前的微批次中完成計算,它希望馬上計算下一微批次。現在你當然可以初始化一個DMA傳輸,然後等待傳輸完成以使你的GPU可以繼續運算。但有一個更有效的方法:提前準備好下一批微批次以便讓你的GPU完全不再需要等待。這可以輕易並非同步地完成來確保發揮出GPU的效能。

  非同步迷你批次分配的CUDA程式碼:當GPU開始處理當前批次時,頭兩個呼叫被執行;當GPU處理完當前批次以後,最後兩個呼叫被執行。資料傳輸早在資料流在第二步被同步的時候完成了,所以GPU可以無延遲的開始處理下一個批次。

在ImageNet 2012,對於Alex Krishevsky的卷積網路,一個大小為128的迷你批次只用了0.35秒就進行了一次完整的反向傳播。我們能在這麼短的時間裡分配下一個批次嗎?

如果我們採用大小為128的批次及維度為244x244x3的資料,大概總量為0.085 GB。採用超慢記憶體,我們也有6.4GB/s的速度,或換句話說,每秒75迷你批次!所以有了非同步迷你批次分配,即使是最慢的RAM對於應付深度學習也是綽綽有餘了。只要採用了非同步迷你批次分配,買較快的RAM模組將沒有任何好處。

這個過程還間接意味著CPU快取是不相關的。對於DMA傳輸來說,CPU可以多快改寫(在快取記憶體中)及準備(將快取寫入RAM)一個迷你批次是無關緊要的,因為整個傳輸早在GPU要求下一個迷你批次前就完成了——所以大型快取真的不是那麼重要。

因此底線是RAM的頻率是不相關的。買那些便宜的吧——故事完結。

但你需要購買多少呢?

  記憶體大小

你應該擁有至少和你的GPU記憶體大小相同的記憶體。你能用更小的記憶體工作,但是,你或許需要一步步轉移資料。不過,就我個人經驗而言,記憶體越大,工作起來越舒服。

心理學家告訴我們,專注力這種資源會隨著時間的推移而逐漸耗盡。記憶體就是為數不多的,讓你儲存注意力資源,以解決更困難程式設計問題的硬體之一。與其在記憶體瓶頸上兜轉,浪費時間,不如把注意力放在更加緊迫的問題上,如果你有更多的記憶體。有了這一前提條件,你可以避免那些瓶頸,節約時間,在更緊迫問題上投入更多的生產力。特別是在Kaggle競賽中,我發現,額外的記憶體對特徵工程非常有用。所以,如果你有錢而且需要做很多預處理工作,那麼,額外記憶體將會是不錯的選擇。

  硬碟驅動器/SSD

在一些深度學習案例中,硬驅會成為明顯的瓶頸。如果你的資料組很大,通常會在硬驅上放一些資料,記憶體中也放一些,GPU記憶體中也放兩mini-batch。為了持續供給GPU,我們需要以GPU能夠跑完這些資料的速度提供新的mini-batch。

為此,我們需要採用和非同步mini-batch分配一樣的思路。用多重mini-batch非同步讀取檔案 ——這真的很重要!如果不非同步處理,結果表現會被削弱很多(5-10%),而且讓你認真打造的硬體優勢蕩然無存 ——在GTX680上,好的深度學習軟體跑起來會快得多,勝過GTX980上的糟糕的深度學習軟體。

出於這種考慮,如果我們將資料儲存為32位元浮點資料,我們會遇到Alex參加ImageNet 所使用的卷積網路遇到的資料傳輸速率問題,大約每0.3秒0.085GB,計算如下:

或每秒290MB。

不過,如果我們將它儲存為jpeg資料,我們就能將它壓縮5-15倍,將所需讀取頻寬降低到大約30MB每秒。

類似,一個人能夠使用mp3或者其他壓縮技巧來處理聲音檔案,但是,對於其他處理原始32位元浮點資料的資料組來說,不可能很好地壓縮資料:我們只能壓縮32位元的浮點資料的10-15%。因此,如果你有大的32位元資料組,那麼,你肯定需要SSD,因為100-150MB/S的硬驅會很慢,不足以跟上你的GPU——因此,如果你的工作需要處理這樣的資料,買個SSD吧,否則的話,普通硬驅就夠了。

許多人買一個SSD是為了舒服:程式開始和響應都快多了,大檔案預處理也快很多,但是,對於深度學習來說,僅當你的輸入維數很高,不能充分壓縮資料時,這才是必須的。

如果你買了SSD,你應該選擇能夠存下和你通常要處理的資料集大小相當的儲存容量,也額外留出數十GB的空間。另外用普通硬驅儲存你尚未使用的資料集的主意也不錯。

  電源供應裝置(PSU)

一般說來,你需要一個給你未來所有GPU充足供應的PSU。隨著時間的推移,GPU通常會更加高效節能;因此,儘管其他元件會需要更換,PSU會用很久,一個好的PSU是一個好的投資。

CPU加上GPU所需瓦特,再加上其他元件額外所需以及作為電力峰值緩衝的100-300瓦特,你就能計算出所需瓦特。

一個需要注意的重要部分就是,你的PSU的PCIe接頭是否支援帶有一條連線線的8pin+6pin接頭。我買過一個PSU,有6x PCIe埠,但是,僅適用於8pin或者6pin的接頭,所以,我沒法用那個PSU跑4個GPU。

另一個重要的事情就是買一個能效等級高的PSU,——特別是,如果你跑很多GPU而且還要跑比較久。

在全功率(1000-1500瓦特)上跑一個4 GPU系統,訓練一個卷積網路兩個禮拜,耗能300-500kWh,在德國——電力成本更高,每kWh多出20美分——會花60到100歐元(66到111美元)。如果這是百分百高效節能的價格,那麼,用80%的電源供應來訓練這樣一個網路,成本將額外增加18到26歐元。對於1個GPU來說,花費就少很多,但是,仍要抓住要點 ——將更多的錢花在高效電源供應上,很有意義。

  散熱

散熱十分重要,這更有可能成為一個大瓶頸,比糟糕的硬體選擇更能降低系統表現。你可能會滿足於給CPU配一個標準的散熱片,但是,要給你的GPU配些什麼東西,需要特別的考量。

當現代的GPU執行一個演算法時,它會一直加速至最大極限,同時加速的還有能量消耗,但當到達它的溫度壁壘,通常是80攝氏度,它就會降低執行速度來避免打破臨界溫度。在保護GPU避免過熱、情況安全的同時,也讓GPU達到最佳狀態。

但是,典型的電扇速度設定是被預程式設計的,完全不是為執行深度學習專案而設計的,所以,在開始深度學習程式後的幾秒內就會達到其溫度壁壘。結果,GPU的執行效果下降(幾個百分比),如果有好幾個GPU,由於GPU之間會相互加熱,那麼,整體效果的下降幅度就會非常明顯(10-25%)。

由於NVIDIA GPU是首屈一指的電競GPU,它們非常適應Windows系統的運作。Windows系統中,你可以通過幾個簡單的按鍵改變風扇的設定,但在Linux系統中不行,不過,多數深度學習庫都是在Linux環境下執行的,所以,這會導致問題出現。

最容易且價效比最高的變通方案就是,用一個有更合理風扇設定的BIOS程式更新GPU以提升速度,這樣就能保持GPU涼爽的同時,噪聲也不至於不可接受(如果你用伺服器解決這個問題,那麼,為了避免難以忍受的噪聲,你很可能會在風扇執行速度上打折)。也可能超速執行GPU的儲存器,這會有一些噪聲(30-50兆赫),這也是相對可行的方法。更新BIO的軟體是一個在Windows系統下設計的程式,但可以用wine作業系統從Linux/Unix OS中呼叫這個程式。

另一個選擇是為你的Xorg 伺服器(Ubuntu作業系統)設定配置(set a configuration),在這個Xorg 伺服器中,設定「coolbits」選項。在只有一臺GPU的時候這個方法非常有效,但如果對多臺GPU,也就是說有「無頭(headless)」GPU,比如這些「無頭」GPU沒有連顯示器,那麼,就必須模擬一臺顯示器,但模擬顯示器難度非常之高。我曾試了很久,無比沮喪的花了數個小時,用實時(live)啟動光碟恢復我的圖形設定,始終沒法讓這個程式在「無頭」GPU上正常運轉。

還有一個方法花費較高也較為複雜,就是用水冷卻。應用於單GPU時,即使是最大功率的情況,也幾乎可以將溫度減半,所以永遠不會達到溫度壁壘。就算是面對空氣降溫無法應對的多GPU情況,也可以很好的降溫。用水降溫的另一個好處是,它執行時產生的噪音較少,如果你處在一個與他們共同工作的環境下,這將帶來極大的方便。水冷卻法花費大約為每GPU100美元左右,前期大概要額外投入50美元。水冷卻法還需要另花一些精力組裝電腦,對於這方面可以找到很多詳盡實用的指南手冊,且花不了幾個小時。維護期間就會簡單方便許多了。

從我的經驗來看,這些是比較對症下藥的方法。我為我的深度學習組團買過大型的塔型機箱,因為他們在GPU的區域有另加的風扇,但我發現,這並沒有太大的作用,大約只降低了2-5攝氏度,不值得為此花這麼多錢還得忍受笨重的機箱。最重要的還是直接作用於GPU的降溫措施:更新BIOS,水冷法或忍受打了一定折扣的執行效果,在某些場合下,這些都是非常有效的應對方式,你可以根據自己需要找到合適的應對方式。

  主機板和電腦機箱

你的主機板要有足夠的PCIe介面,來支援你希望同時執行的GPU(通常侷限於4臺GPU,即使主機板上有很多PCIe槽。記住,多數GPU都需要佔2個PCIe槽的寬度,例如,你會需要7個槽口來連結4臺GPU。PCIe2.0介面也是可以接受的,但PCIe3.0介面更加經濟,即使只對單GPU價效比也很高,如果對多GPU,通常都會使用PCIe3.0介面,這會對多GPU運作帶來很大的好處,因為PCIe的連線口多數情況下是個瓶頸所在。

主機板的選擇策略十分直接:就選那款可以支援你想要的硬體配置的就行。

當你選擇機箱時,要確保它能滿足你GPU的長度要求,這樣它才能在主機板上放穩。多數機箱都能滿足要求,但如果你選的是一個小機箱,就需要多加留心。要核查它的面積和規格,你也可以嘗試用google的圖片搜尋引擎,看看能不能找到GPU放在上面的圖片。

  顯示器

我剛開始也覺得寫顯示器是件很滑稽的事,但他們確實會造成很大的影響,非常重要,不能忽視。

我在我的3'27英寸顯示器上付出了可能是我從未有過的大代價,買了幾個顯示器後,效率提高了很多。如果我只能用一臺顯示器,那我的效率肯定會大打折扣。別在這上面和自己過不去,如果你不能有效的運轉一個快速的深度學習系統,那它又有什麼好處?

我進行深度學習系統工作時,顯示器的典型佈置一般是:Papers、Google搜尋、gmail、stackoverflow網在左,中間是程式設計介面,右邊是輸出視窗、R、資料夾、系統顯示器、GPU顯示器、待辦事項以及一些其他小的應用。

  組裝電腦的其他感言

很多人都會被組裝電腦這個主意嚇到,硬體很貴,誰都不想花冤枉錢。但道理其實很簡單,本就不該裝在一起的硬體沒法湊合。手動主機板上的每個元件都有特定的位置,如果你沒有經驗也可以找到很多指南、手把手的教程視訊教你。

關於組裝電腦有一個很大的好處就是,只要你組裝過一次,你就會知道各個元件的位置,因為電腦都是以非常相似的方法組建起來的——所以組裝電腦可以成為一個重複應用相伴一生的技能。還有什麼理由不試一下呢!

  結論 / TL;DR

  GPU

  GTX 680 或者GTX 960 (窮); GTX 980 (表現最佳); GTX Titan (如果你需要儲存器的話); GTX 970 (no convolutional nets)。

  CPU

  每個GPU 2個執行緒; 全套40 PCIe 線路和合適的PCIe 配件(和主機板配套); > 2GHz; 快速緩衝儲存區不用太在意。

  記憶體

  使用非同步mini-batch分配; 時鐘頻率和記憶體時序無關緊要;購買至少像GPU記憶體一樣多的CPU記憶體。

  硬驅

  硬驅動/SSD:使用非同步batch-file讀取和壓縮資料,如果你有影象或聲音資料;除非你處理的是帶有高輸入維度的32位元浮點資料組,否則,普通硬驅就可以了。

  PSU

  GPU+CPU+(100-300)就是你所需的電源供應量;如果你採用的是大的卷積網路,那麼,就買個能效級別高的;確保有足夠PCIe接頭(6+8pin),並足以支援你未來可能買入的GPU的執行。

  散熱

  如果執行單個GPU,在你的設定中設定「coolbits」flag;否則,更新BIOS和加快風扇轉速就是最便宜最簡單的辦法;需要降低噪音(與其他共處一室)時,用水來為你的多GPU散熱。

  主機板

  選擇PCIe 3.0,帶有和你以後所需GPU數量一樣多的槽口(一個GPU需要兩個槽口;每個系統最多4個GPU)

  顯示器

  如果你想升級系統,讓它生產力更高,較之升級GPU,再買一臺顯示器會有意義得多。

  (注:文章於2015年4月22日更新:去除了對GTX580的推薦。)