自動パラレライザ (Auto-Parallelizer) (VC++2012)

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;
}

実行結果は以下の通り。


~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日 追記、木下英俊