GPU編程的IO瓶頸如何解決?

我最近在學習GPU編程,已經了解到了GPU的強大的並行能力可以極大地加快數據處理的過程,但是也了解到了兩個問題:GPU的存儲有限,所以數據需要從外部導入;導入的過程帶來IO的問題,使得IO的時間遠大於GPU處理的時間,請問現在常用的GPU編程架構,如CUDA是否已經解決了這個問題?


--------2017-03-01更新--------(聽說要這樣弄?)

歪個樓,知彼知己百戰不殆,要解決IO瓶頸,必先學習了解它!

最近在探究雙核8卡拓撲結構下的帶寬瓶頸,做了各種實驗,最後發現白忙活一通,有一篇企業博客(貌似有打廣告的嫌疑)很好的總結了多GPU間數據傳輸瓶頸這個問題。

博客英文原版: Exploring the Complexities of PCIe Connectivity and P2P Communication

中文半翻譯版:[翻譯]Exploring the Complexities of PCIe Connectivity and Peer-to-Peer Communication

(自己翻譯到一半發現已經有別人翻譯過了……這個教訓教育我們做事之前要先調研啊!!)

-----原文------

gpu的io問題一直是比較嚴重的瓶頸,我自己總結有三種解決方案。

1.優化演算法,選擇更有效的存儲方式,減少顯存的使用。只拷貝必要數據,優化數據結構等等。

2.使用cuda內存優化技巧。比如顯存整塊申請和拷貝,使用pinned memory,shared memory,constant memory,使用流來掩蓋內存延遲等等。

3.硬體解決方案,放棄pci-e,使用ibm的power架構和p100,直接用nv-link進行內存傳輸。這個方案是一勞永逸的,但是要準備好money,一整套下來很貴的。

第三個方案一般整不起,前兩個方案是演算法和語言技巧方面,與演算法本身有很大的關係。個人經驗上來講方案1提升的潛力比較大。

使用cuda對演算法加速是一個很複雜的過程,io是一個比較大的問題,還有條件分支,共享內存bank conflick問題,指令優化等等,這些在優化時都要考慮。

祝題主跳坑愉快。


首先,這個「瓶頸」(暫且這麼稱呼它)因為物理極限而無法解決。目前NVLink (40GB雙向per link)和PCIe (32GB雙向per gen3 16x link),都比GPU內部的內存帶寬(300--700GB)要小得多。這個物理極限可能會在下一代硬體得到突破。

其次,這個問題到底是不是「瓶頸」?一次從CPU移入GPU的數據,通常會被重用多次,這使得較慢的移入的代價,仍然是值得的。例如深度學習里的dense gemm A(m*f)×B(f*n),矩陣A的每一行要被重用f次--當f很大的時候,緩慢的移入就很值得了。如果你的應用只把數據讀一次,那麼你要考慮移入GPU是否值得 -- 可能在CPU上做SIMD,而避免傳輸到GPU會有更好的效果。

另外, @謝小龍 提到了,很多時候你可以邊計算邊傳輸下一步計算需要的數據 -- 在深度學習的mini-batch training中這是標準方式,這樣這種「瓶頸」就被隱藏了。


頂 @叛逆者 的答案。如果IO出現了問題,很大可能是你現在的演算法並不適用GPU加速。

請問現在常用的GPU編程架構,如CUDA是否已經解決了這個問題?

額,在考慮是否有更好的用法之前還是不要考慮底層架構的事情,除非你有足夠的證據。

你可以嘗試一下下面幾個方法:

1. 是否用滿了GPU的運算能力?

答案可以通過你的數據和GPU計算能力比較得到。

2. 是否IO次數過多?

每次IO都會消耗一定的時間,IO次數越多,消耗時間越多。

3. 演算法中是否包含了過多的if/else等邏輯跳轉?

GPU適用於並行計算,而不適用於邏輯判斷。


如果PCIE上的IO時間遠大於GPU處理的時間,說明你的演算法有錯。跟CUDA沒關係,所以不需要CUDA來解決。


不是CUDA的問題,是硬體的問題,受限於PCI-E帶寬。

CUDA這邊的一個解決辦法如下,不知道題主注意到沒有:

CUDA涉及的主機端存儲主要有分頁內存(pageable memory)和鎖頁內存(pinned memory)。分頁內存使用malloc()和free()分配釋放(通常情況),內存頁可能被換出磁碟,無法使用DMA傳輸。而鎖頁內存將一直存在於內存空間中,支持DMA訪問和與GPU非同步通信,通過cudaHostAlloc()和cudaFreeHost()分配釋放。在主機端使用鎖頁內存比使用分頁內存的PCI-E傳輸速度快一倍左右,效果明顯。

在考慮用GPU加速演算法時,可以先做benchmark,估計整套演算法的訪存時間,再看是不是需要更多的時間來計算。計算時間=訪存時間的話,可以相互掩蓋,計算時間&>訪存時間的話,就是受限於計算能力的演算法,更適合用GPU來做(根據演算法數值計算過程不同,不一定都適合,一些演算法還要深度優化才行)。

儘可能跑一套演算法,而不是只簡單計算。數據傳過來以後進行多次運算,再傳出去。


看到大家說了Nvidia的技術,我來說一下AMD的吧。

AMD的SSG技術可以緩解這一問題

以下數據來源於AMD官網以及說明文檔

GPU 專為處理龐大的數據量而設計。但是上升至系統級,大型數據集無法瞬間供 GPU 使用。Radeon? Pro SSG(固態顯卡)解決方案旨在進一步實現大型數據集的瞬間訪問。

Figure 1: Traditional system architecture for mass storage.

傳統大量存儲的系統架構

Figure 2: Data path fortypical graphics transaction necessitates many copy transactions that
are expensive to process.

典型的IO密集型計算

Figure 3: The system storage architecture with Radeon? Pro SSG.

採用Radeon? Pro SSG技術時的存儲系統結構

可以看到在SSG技術中,GPU與NVMe儲存系統(在圖中為TBs)可以直接建立聯繫。在此時CPU就不需要參與到數據傳輸之中了,於是速度就可以大幅提升。在此時,所有的數據都是在GPU中處理的。

SSG的另外一個好處是它可以解放CPU。

Once the path between the GPU and NVMe is established, an additional benefit of the
Radeon Pro SSG solution is revealed. Because the CPU is removed from the path of the
data being transferred, it is free to service other tasks,thus helping improve the overall
efficiency of the system.

當GPU和NVMe的通道建立之後,另外一個Radeon Pro SSG的優勢就顯現了。因為CPU不再參與數據傳輸,所以CPU就可以自由執行其他任務,這樣就可以幫助提升整個系統的運行效率

參考資料:

Radeon-Pro-SSG-Technical-Brief.pdf

AMD Radeon? Pro SSG Set to Transform Workstation PC Architecture, and to Shatter Real-Time Visual Computing Barriers


對於CUDA來說,解決的方法就是shared memory,盡量減少對 global memory部分的訪問,把每一個block需要的數據一次載入存儲到block內,利用cache,其實IO性能瓶頸的解決無論CPU還是GPU思路是都是接近的就是不斷增加緩存,因為離計算單元越遠性能越差,還有合理的控制分配數據的讀寫,前者是硬體架構只要你的環境支持就可以利用,後者就需要你考慮如何你的數據讀寫了,這些都是可以計算出來能夠提升多少性能的,也是可以利用不同點策略改進的,還是拿CUDA舉例,你可以使用TILE來把要處理的圖像或者其他數據來分割開來,每一個小塊載入他們所需要的數據,這樣他們就可以各干各的了,不需要大家都跑去global那裡討要數據,畢竟global的帶寬提升幅度是有限的。


I/O問題一直就是nvidia這樣的discrete GPU的短板,但是AMD的APU那種CPU和GPU共享DRAM的GPU的計算能力又太弱。

首先如果你的數據大量存在磁碟(包括SSD)上,GPU沒有處理磁碟I/O的能力,即使有,SSD的帶寬也遠遠比不上GPU device memory的帶寬。

如果你的數據已經緩存在host的DRAM上,需要在host和GPU之間做data transfer,16 lane PCIe 3.0的帶寬可以達到16GB/s,但是也還是遠低於 device memory的帶寬。

可行的解決辦法就是看你的應用input能不能被分成小塊(chunking),如果可以的話,就可以用多個streams來overlap data transfers和compute。或者就是看你的input能不能被什麼解壓速度特別的快的壓縮演算法壓縮,減少data transfer的量,然後在GPU上解壓,用計算換I/O。

機器學習的話,一般training的data set都不是很大吧,主要還是train model的計算量比較大。如果是test的話,我記得有個文章分析過,通過overlap data transfer和compute,即使是普通的硬碟的帶寬(只要&>65MB)應該就足夠撐滿K20了。


我沒opencl與cuda的編程經驗.所以不對還請多多指點(在知乎上回答問題總很忐忑)。

首先實際gpu是沒有能力去控制文件io的.所以都是cpu讀取發送到gpu,而cpu到gpu這條傳輸數據的道路pci-e是足夠寬的.問題就出在gpu與cpu同步上.

顯存現在都1G最低了吧?在部分應用場景夠用了.所以存儲空間還算夠用的.但是顯存易丟失.不像內存那樣自己不刪除.不關機.不被emp不會丟失數據


注意有一個前提是,用GPU是要干計算密集型應用,數據量很大而不怎麼需要計算的事用GPU不合適,用專用晶元更合適,比如有種應用叫萬兆網卡。


看你這描述應該是io次數太多了,盡量把task以及輸入輸出合併到一個kernel里


實際中遇到過類似問題

用批量高斯模糊舉例

首先,看看是不是有數據拷貝是不必要的。比如你做卷積沒必要每次卷積的時候都把卷積核從主存拷貝到顯存一份

其次,看看能不能嘗試將計算和數據傳輸並發,即GPU滿負載的同時通過PCIE匯流排在內存和顯存之間交換數據。比如你做卷積計算的同時,可以把上卷積結果傳回主存,同時預載入下一張圖片。


了解opencl並行計算,cuda只看過代碼具體的 細節不是很清楚,不過從opencl 處理流程和模型來看,cuda應該是類似(用的是 nvdia顯卡和opencl編程)。你說的這種情況是存在的,但是 有一個前提,就是你 計算的數據量是非常大的,假設和 顯卡顯存接近,而且每次計算都需要這麼大的數據,這個時候才出現你說的情況,每次載入數據和輸出數據 要等 pcie 講數據 完全送完才能進行。估計這種計算 你我都遇不到的。


gpu編程用什麼軟體啊?


你需要用intel的超算架構


io絕對不是瓶頸。 我做手機顯示晶元的1080p視頻數據的io沒有任何明顯延遲。 一般處理瓶頸就兩個, 1.視頻, 圖像的解碼 2. 演算法。 IO這個延遲我一直無視。。


推薦閱讀:

CPU 和 GPU 的溫度是怎麼計算的?
買Mac Pro 或 iMac?
這個是色階嗎?有時候電腦也出現這種情況,跟顯卡的64bit/128bit有什麼區別?小米2,魅族mx以及mx2手機對應的GPU呢?
不斷擴充的 SIMD 指令集會不會讓 CPU 從 GPU 手中奪回失去的並行計算市場?
GPU如此之強能否替代CPU?

TAG:編程 | 圖形處理器GPU | GPU通用計算 | CUDA | 大數據處理 |