2012年1月16日 星期一

C++ AMP 第一次接觸

這只是一個PPL的範例轉換為C++ AMP的嘗試,主要是了解C++ AMP語法,測試的結果或許不足以代表C++ AMP的長處。

 我是以Parallel Programming with Microsoft Visual C++的BasicParallelLoops範例修改與測試。

C++ AMP與PPL有3點不一樣的地方必需修改
1. C++ AMP不支援C array的讀寫,必需改用Concurrency::array或Concurrency::array_view。
2. C++ AMP的只有一個起點:parallel_for_each(...) restrict(direct3d)
3. 在parallel_for_each(...) restrict(direct3d)中所使用的函式也必需加上restrict(direct3d)的關鍵字。

修改原程式的Example02為:

void Example12(vector<double>& results, int workLoad)
{
 int num = results.size();

 array<double, 1> resAMPs(num, results);

 parallel_for_each(resAMPs.grid, [&resAMPs, workLoad](index<1> idx) restrict(direct3d) {
  
  resAMPs[idx] = DoWorkAMP(idx.get_x(), workLoad);
 });
}

修改原程式碼的DoWork:

float DoWorkAMP(int i, int workLoad) restrict(direct3d)
{
 float result = 0;

 for (int j = 1; j < workLoad + 1; ++j)
 {
  float j2 = (float)j;
  float i2 = (float)i;
  result += sqrt((9.0f * i2 * i2 + 16.0f * i * i) * j2 * j2);
 }

 return result;
}


DoWorkAMP有一個奇怪的地方,原程式碼中的運算是以double的資料格式進行,但在C++ AMP中,即使只是單純的做資料轉換,如:

double i2 = (double)i;

也會發生程式crash的意外。有可能是因為大多數的GPU並不提供double的原因,但不知這點未來是否能在編譯時提出警示。

最終的執行效能是很糟的,在Core2 Quad 2.66GHz + nVidia GeForce GT 2400 + Windows 7 x64系統上的結果


Parallel For Examples (workLoad=1000,NumberOfSteps=10)
Sequential for             : 0.19 ms
Simple parallel_for        : 0.87 ms
Simple parallel_for (AMP)  : 210.89 ms
Parallel For Examples (workLoad=100,NumberOfSteps=100)
Sequential for             : 0.14 ms
Simple parallel_for        : 0.08 ms
Simple parallel_for (AMP)  : 168.46 ms
Parallel For Examples (workLoad=10,NumberOfSteps=1000)
Sequential for             : 0.14 ms
Simple parallel_for        : 0.09 ms
Simple parallel_for (AMP)  : 172.68 ms

C++ AMP究竟能帶給商業運算多少的助益,他的長處在那裡(除了語法更為接近C++),我還看不太出來。