VC++2012の心機能の一つである「自動パラレライザ(Auto-Parallelizer)」の動作を確認しました。
結論を先に書くと、高速化されているように見えません。そんなはずはないので追跡評価が必要です。
以下、うまく高速化できた例を示しますが、単純な int
型による四則演算では高速化の確認をとれませんでした。並列化して遅くなった、というわけでもありませんでしたが。
四苦八苦して、結果 float 型で
sin, cos の演算をやらせたら高速化を確認できた、という感じです。
#include "stdafx.h"
#include <sstream>
#include <cmath>
using namespace std;
void disp_laptime(stringstream &output, DWORD &dwStartCount, DWORD &dwLapCount)
{
DWORD dwNowCount;
dwNowCount = GetTickCount() - dwStartCount;
output << dwNowCount << "(" << dwNowCount - dwLapCount << ")" << endl;
dwLapCount = dwNowCount;
}
int _tmain(int argc, _TCHAR* argv[])
{
const size_t n=10000000;
static float a[n], b[n], c[n];
Sleep(2000);
DWORD dwStartCount = GetTickCount();
DWORD dwLapTime = 0;
stringstream output ;
// initialize
for ( int i=0; i< n; ++i){
a[i] = b[i] = c[i] = 1.0;
}
disp_laptime( output, dwStartCount, dwLapTime );
#pragma loop(no_vector)
for (int i = 0; i < n; ++i){
a[i] += sin(b[i]) * cos(c[i]);
}
output << "no_vector : ";
disp_laptime( output, dwStartCount, dwLapTime );
for (int i = 0; i < n; ++i){
a[i] += sin(b[i]) * cos(c[i]);
}
disp_laptime( output, dwStartCount, dwLapTime );
#pragma loop(no_vector)
for (int i = 0; i < n; ++i){
a[i] += sin(b[i]) * cos(c[i]);
}
output << "no_vector : ";
disp_laptime( output, dwStartCount, dwLapTime );
for (int i = 0; i < n; ++i){
a[i] += sin(b[i]) * cos(c[i]);
}
disp_laptime( output, dwStartCount, dwLapTime );
#pragma loop(hint_parallel(4))
#pragma loop(no_vector)
for (int i = 0; i < n; ++i){
a[i] += sin(b[i]) * cos(c[i]);
}
output << "loop(hint_parallen(0)), no_vector : ";
disp_laptime( output, dwStartCount, dwLapTime );
#pragma loop(hint_parallel(0))
for (int i = 0; i < n; ++i){
a[i] += sin(b[i]) * cos(c[i]);
}
output << "loop(hint_parallel(4)) : ";
disp_laptime( output, dwStartCount, dwLapTime );
cout << output.str() << endl;
/*========*/
/* 後処理 */
/*========*/
{
string str;
cout << "HIT [Enter] KEY !! " ;
getline(cin, str);
}
return EXIT_SUCCESS;
}
|
実行結果は以下の通り。
2~3分の一、ぐらいの実行時間になっているので、
Auto-Parallelizer は効いているように見えます。i5のCPUで4つの並行動作を指定しているのだから、妥当な値でしょうか。
コンパイルオプションは次の通り。
cl /Yu"stdafx.h" /GS /Qpar /GL /analyze- /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /sdl /Fd"Release\vc110.pdb" /fp:precise /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /arch:SSE2 /Gd /Oy- /Oi /MD /Fa"Release\" /EHsc /nologo /Fo"Release\" /Fp"Release\test_AutoVectorizer.pch" /Qvec-report:2 /Qpar-report:2 |
test_autovectorizer.cpp(18) : info C5002: ループはベクター化されません。理由: '1400' test_autovectorizer.cpp(23) : info C5001: ループがベクター化されています test_autovectorizer.cpp(29) : info C5002: ループはベクター化されません。理由: '1400' test_autovectorizer.cpp(34) : info C5001: ループがベクター化されています test_autovectorizer.cpp(41) : info C5002: ループはベクター化されません。理由: '1400' test_autovectorizer.cpp(47) : info C5001: ループがベクター化されています test_autovectorizer.cpp(18) : info C5012: ループは並行化されません。理由: '1008' test_autovectorizer.cpp(23) : info C5012: ループは並行化されません。理由: '1008' test_autovectorizer.cpp(29) : info C5012: ループは並行化されません。理由: '1008' test_autovectorizer.cpp(34) : info C5012: ループは並行化されません。理由: '1008' test_autovectorizer.cpp(41) : info C5011: ループが並行化されています test_autovectorizer.cpp(47) : info C5011: ループが並行化されています |
参考情報:
Visual Studio 2012 C++ Auto-Parallelizer
記載: 2012年11月15日 木下英俊
2013年7月15日 追記、木下英俊