自從 nVIDIA CUDA 推出後,把顯示卡的繪圖晶片拿來做通用計算的 GPGPU 算是用來越普及了~目前除了 CUDA 外,AMD 也有自己的 Stream SDK(目前以改名為 AMD APP),同時也更有跨硬體的標準 OpenCL 以及微軟 DirectX 裡的 DirectCompute(MSDN)。
而微軟在這幾天 AMD Fusion Developer Summit 上,也發表了一個用於 C++ 的 GPU 大量平行化的開發技術,命名為「C++ Accelerated Massive Parallelism」。目前似乎還沒有能找到詳細資料,不過就現在看到的資料,重點是在於:
- STL-Like、C++ 的語法,只要會用 STL 就會用。也就是他的學習門檻會更低~
- 會整合在下一版的 Visual C++ 中,不需要額外的編譯器也不需要其他的語法。
- 基於微軟的 DirectCompute(這代表了他應該只能用在 Windows Vista / Windows 7)。
- 將可以使用在 GPU,以及 APU 等適合大量平行計算(massively parallel)的硬體上。
詳細的資料可以參考《C++ Accelerated Massive Parallelism》和《Introducing C++ Accelerated Massive Parallelism (C++ AMP)》,不過說實話細節也不多。另外,在 Channel 9 上可以找到展示的影片(網頁、簡報投影片),裡面有簡單的矩陣相乘範例程式碼;而在《Microsoft brings GPU computing to C++ with C++ AMP》一文中,也有一些簡單的說明。
其中,在《Microsoft brings GPU computing to C++ with C++ AMP》一文中可以看到,C++ AMP 主要是在 C++ 裡加上了一些必要的新的 class,包括了:array<T, N>、array_view<T, N>、index<N>、grid<N>、tiled_grid<Z, Y, X> 等等。
另外,也針對平行化處理的需求,加上了 parallel_for_each() 的函式,以及額外的 restrict(direct3d, cpu) 指令。
在投影片中所提供的「Hello World」範例,則是簡單的矩陣相加~如果直接用 C++ 寫的話,會是:
void AddArrays( int n, int* pA, int* pB, int* pC ) { for( int i = 0; i < n; ++ i ) { pC[i] = pA[i] + pB[i]; } }
如果將這段程式用 C++ AMP 改寫的話,則會變成:
#include <amp.h> using namespace concurrency; void AddArrays( int n, int* pA, int* pB, int* pC ) { array_view< int, 1 > a( n, pA ); array_view< int, 1 > b( n, pB ); array_view< int, 1 > sum( n, pC ); parallel_for_each( sum.grid,[=]( index<1> idx ) restrict(direct3d) { sum[idx] = a[idx] + b[idx]; }); }
而在影片(網頁)裡面的範例程式碼,則是提供了另一個、稍微複雜一點的矩陣相乘的程式碼當作例子。用 C++ 寫的話,會是:
void MatrixMult( float* C, const vector<float>& A, const vector<float>& B, int M, int N, int W) { for( int y = 0; y < M; y++ ) for( int x = 0; x < N; x++ ) { float sum = 0; for( int i = 0; i < W; i++ ) sum += A[y*W+i] * B[i*N+x]; C[y*N+x] = sum; } }
改使用 C++ AMP 則會變成(還要加上 #include <amp.h>、且部分的型別的 namespace 是 concurrency):
void MatrixMult( float* C, const vector<float>& A, const vector<float>& B, int M, int N, int W) { array_view<const float, 2> a(M,W,A), b(W,N,B); array_view<writeonly<float>, 2> c(M,N,C); parallel_for_each( c.grid, [=](index<2> idx) restrict(direct3d){ float sum = 0; for( int i = 0; i < a.x; i++ ) sum += a(idx.y,i)*b(I,idx.x); c[idx] = sum; } ); }
以上面兩個範例看來,C++ AMP 的平行計算方法,目前似乎只有一個 parallel_for_each()?而在使用上,的確真的很接近 STL 的用法~要使用時,應該就是:
- 加上 <amp.h> 這個 header 檔、並指定 namespace(concurrency 現在是微軟 PPL 的 namespace)。
- 將資料轉換為 C++ AMP 的特定型別(這邊都是用 array_view)
- 將實際要執行的程式以 function object 的形式,和資料一起丟給 parallel_for_each(),做平行化的處理。
在這兩個範例裡,都是使用 C++0x 的 lambda expression(參考)的形式來建構所需要的 function object;而其中比較特別的是,對於這個 function object 他還加上了 restrict(direct3d) 這樣的程式碼。雖然以目前的資料還說還不是很確定,不過 restrict() 這個指令應該是用來指定這個 function object 丟到 parallel_for_each() 後,是要在 CPU 還是 GPU 上執行了~
在 Heresy 來看,這樣的語法如果和 nVIDIA CUDA 或是 OpenCL 來比的話,確實是又再進一步簡化不少了!基本上要做的,就是轉換成 C++ AMP 特定的資料型態、然後呼叫 parallel_for_each() 就好了~資料到底在 CPU 還是在 GPU 上,應該也是由 C++ AMP 自己負責處理掉了(可以在轉換成 array_view 時,以 const 和 writeonly 來做一定程度的控制);而就像範例裡面一樣,再搭配 lambda expression 的話,更是連 kernel function 都不用額外定義了~如此一來,就真的很像在寫一般的 C++ STL algorithm 的迴圈程式,雖然比不上 OpenMP,但是也是相當地簡單了!
不過如此一來,也代表大部分的 GPU 配置動作都是交給編譯器自動決定、處理了,所以接下來要擔心的,可能就是編譯器在自動最佳化方面的效率(包括了記憶體在 CPU / GPU 間的複製、以及平行化的工作配置)了~
另外,由於這項功能是基於微軟 DirectX 11 中的 DirectCompute 來實作的,所以這也代表了 C++ AMP 這項技術也會被綁在 Windows Vista / Windows 7 以後的作業系統上,而不像 CUDA、OpenCL 可以跨平台了…這點對於要開發跨平台程式的人來說,就覺得比較悲哀了。
不過由於微軟是把 C++AMP 當作一個開放規格(open specification),所以理論上其他編譯器應該也可以自己支援 C++ AMP 的語法。而如果 restrict() 可以有 direct3d 和 cpu 以外的選項的話,那其他編譯器應該也可以用 DirectCompute 以外的方法來實作(例如 OpenCL),這樣應該就可以跨平台支援了。不過這樣一來,重點就是有多少編譯器願意支援了。
而由於這項功能是會整合在下一版的 Visual Studio 裡,所以看來短時間內應該都還沒有辦法玩到了。現在,也就只能慢慢期待,微軟趕快推出有這項功能的產品囉~
[…] CPU 來做計算,後者則是透過 C++ AMP、用顯示卡來做加速計算。由於 Kinect Fusion […]
讚讚
[…] Detail analysis article https://kheresy.wordpress.com/2011/06/16/c-accelerated-massive-parallelism/ […]
讚讚
[…] Detail analysis article https://kheresy.wordpress.com/2011/06/16/c-accelerated-massive-parallelism/ […]
讚讚
最近有點想投貴實驗室的職缺
但顧慮自己非資工背景
讚讚
說實話…Heresy 這邊上頭不給人已經很久了…
讚讚
如果不是用於windows8 或server2012 有一些限制
http://blogs.msdn.com/b/nativeconcurrency/archive/2012/02/07/double-precision-support-in-c-amp.aspx
我都寫個千行程式了 一整個快porting完了才發現
不能做除法(除非重灌win8)
一整個很悲情-.-
—只好默默的把cuda打開來作
讚讚
這麼糟?你沒講 Heresy 還真沒注意到。
看來微軟為了推 Windows 8 還真是無所不用其極…
讚讚
[…] Visual C++ 來說,除了針對平行化的加強(包含偵錯工具)、以及 GPGPU(C++ AMP)的支援外,MSVC11 另外也針對 C++11 […]
讚讚
[…] 的系統上、針對 CUDA 做 debug 就是一個相當好的改進~而同時,好像還有支援微軟的 C++AMP(參考)!?不過很可惜的,對於 graphics 的部分,主要還是以 Direct3D […]
讚讚