NVIDIA CUDA、AMD stream、C++ AMP、OpenCL等GPU計算框架各有什麼特點?

運行效率、硬體限制,跨平台性,學習曲線以及各自前途等


謝邀。

CUDA

Pros:

生態系統良好,工具、教程、第三方庫之類很容易找。經過那麼多年的發展,比較成熟,在GPGPU的API設計方面走早前面。已經被很好的探索過,被證明行之有效。效率高。

Cons:

只能NV的卡,或者x86的CPU。需要有NV的GPU知識才能用好。

OpenCL

Pros:

跨平台,大家都支持。可以很容易異構計算。

Cons:

大家都把它當作乾兒子,沒人認真寫它的驅動。以至於速度和穩定性都很受影響。根據DWave幾年前的一個報告,同個程序OpenCL的速度只有CUDA的1/3。另外OCL抽象層及比較低,以至於開發起來有點麻煩。

C++ AMP

Pros:

基於Direct compute,可以和其他C++程序完美結合。可以在各種支持D3D11的卡上執行。底層被隱藏起來了,以至於不懂GPU編程的人也可以順利使用。

Cons:

正因為底層被隱藏,甚至被過分隱藏,以至於有些事情變得不那麼直接。比較適合rapid prototype,需要性能細調的地方,還是用更底層的好。

AMD stream

沒用過,不好評論。但根據AMD的驅動秉性,穩定性好不到哪去。


用過CUDA、C++ AMP,OpenCL只稍微瞄了一眼。

跨平台,OpenCL 最廣,操作系統(Win和Linux)和GPU(AN)都不受限;CUDA 操作系統不受限,但是只能用於N卡;C++ AMP 只有 Windows ,但顯卡不受限(只要支持 DX11)。

運行效率我沒測過,但隱約記得看過別人在一些文章(MSDN上的)里寫的說 CUDA 最好,然後C++ AMP會稍微差一點(原文貌似是說達到和CUDA差不多的水平),OpenCL 不知道。

我個人覺得寫起來最方便的是 C++ AMP,包含一個頭文件(amp.h),using namespace concurrency,沒有什麼其他初始環境設置,直接聲明你需要的數據,然後直接寫parallel_for_each的代碼即可,和正常的C++代碼寫在同一個文件都沒問題。然後VS就直接可以編譯,也直接VS就能Debug了。C++ AMP 實際是用 DirectX 11 的Compute Shader實現的,所以AMP的運行環境在背後自動幫你設置 DirectX11的設備,生成Shader,然後運行。如果說有什麼不足的話,就是 C++ AMP 只支持32位長度的數據,也就是int、float這種,如果你的數據是 short ,會需要想辦法轉換成int數據傳入,然後在一個 thread 里算倆。

當然 CUDA 起步更早,庫更全,本身寫起來也挺方便,目前已經支持 C++ 11 的語法了,用Nsight也可以方便的Debug。相比C++ AMP里CPU和GPU的通信都是隱式的(聲明一個可以CPU訪問的buffer,當kernel函數退出後,數據就會到達CPU端,可以訪問。雖然也可以手動synchronize),CUDA裡面需要顯式調用cudaMemcpy在CPU和GPU之間傳送數據,略有一點不方便,但是也可以讓你自己控制時機。不過同時,CUDA可以更方便的分配存儲空間,構造複雜數據結構(至於你的演算法是不是有這種需求就另說了……)。就用cudaMalloc返回的在顯存上的指針,在CUDA代碼里就能用這些指針訪存。而C++ AMP就只有一維、二維、三維的array,雖然目測耍一些技巧也不是不行,但沒有CUDA那種更接近於C風格的數據更容易操縱。C++ AMP的array的[]甚至是重載的運算符,得往裡面放extend(也就是維度)匹配的idx對象才行。


C++ AMP 我最近調研了一下(其實是有Linux版本的,目前還在開發中):

他使用一些C++的新標準來完成HPP計算:

  1. 使用lambda或者functor來實現kernel
  2. 使用模板來控制參數類型
  3. 使用namespace控制變數作用域
  4. 使用了很多STL庫

OpenCL

更加底層,更加通用,參數設置很複雜,kernel code是當做一個字元串在HPP程序運行的時候去編譯的,是完全遵循C語言標準的,這樣的話kernel code就沒有辦法在編譯的時候進行變數檢查,我看了最簡單的vector add demo,是比cuda複雜的很多的,cuda提供的有Nsight 可以直接調試kernel code,OpenCL我覺得調試起來會很複雜

除此之外,還有一個OpenACC,這個就和OpenMP很像,直接使用#pragma指令在串列程序的code上面補充一些邏輯,完全依賴於編譯器來生成HPP代碼,效率應該不好。OpenMP是一個並行多線程框架,也是使用一些預編譯指令控制串列程序。

使用過CUDA和C++ OpenAMP(這個我搞成OpenMP了,用過OpenMP)。

其中CUDA和OpenCL的關係很類似於DirectX和OpenGL的關係,前者cuda性能好但是閉源而且只能在NVIDIA的部分GPU上面編寫代碼。後者OpenCL是開放標準,對GPU的限制比較小,但是市場份額較低。OpenAMP是提供了一組C++編譯的預編譯指令應該是OpenMP),可以在原來的C++代碼的演算法之上將循環展開,使之運行在不同的CPU之上,貌似和GPU沒有關係。

對CUDA了解比其他多一些,cuda提供C/C++語言的基礎語法擴展,API設計易於學習,而且市場份額比較高,最新的Caffe | Deep Learning Framework底層也是使用CUDA實現的並行計算。

CUDA可以把演算法分解成不同的block和thread,在GPU之上分配出一組組的warps並發執行演算法邏輯,每個線程劃分可以控制一維到三維數據。

內存顯存控制上提供global memory shared memory控制減少內存顯存交換次數,提供const memory提高GPU cache命中,基於cuda之上的矩陣運算,前綴和折半並行等等演算法都可以高效的實現,並且cuda擁有豐富的第三方庫和fortran和python的擴展。各種機器學習演算法和DNN模型的訓練都基於cuda的高效計算。再說CUDA學習起來不是很難(其他的我不太清楚,其實 OpenAMP更簡單),所以我建議題主跟我一樣學cuda。


覺得OpenCL和CUDA還可以


簡單地用過OpenCL,只能說現階段功能還不如cuda強大,比如說glm 庫在cuda中可以直接調用而CL中不行,這也許更多是glm自己的問題。不過據說webcl正在開發中,沒準可以和webgl合作體現出其跨平台的優勢。


只用過CUDA,看樓主的需求吧。CUDA專用性強,也就是只能在N卡上跑,但是效果不錯。而且有調試工具,只要模型恰當,還是很不錯的。


CUDA比較好,雖然是封閉的,但是有較為完整的生態系統。

其他方式的代碼寫出來後除錯和調優很痛苦。


請問,做過cuda.的視頻解碼嗎


推薦閱讀:

GPU計算優化的原理是什麼?
CPU與GPU之間是如何通信的?
有哪些優秀的CUDA開源代碼?

TAG:OpenCL | GPU通用計算 | C | CUDA |