whole program optimization最適化オプション


Visual C++最適化の概要
Visual Studio .NET 2003
適用:Microsoft Visual C++NET 2003Microsoft Visual C++ Toolkit 2003Microsoft Visual Studio .NET
概要:Visual C++2003コンパイラが提供する多くのコード最適化機能のいくつかの機能を示します.(8ページ印刷ページ)
Visual C++Toolkit 2003に添付されているコードの例の一部です.以下のWebサイトからダウンロードできます.http://msdn.microsoft.com/visualc/vctoolkit2003.
このページの内容
Microsoft?Visual C++?Toolkit 2003には最適化C++コンパイラが含まれています.ほとんどのスイッチはかなり簡明で、Visual C++製品の複数のバージョンに存在していますが、まだ2つのスイッチが比較的新しく、コードを書き換える必要がなく、大幅に速度を向上させることができます.これらは/GL(Whole Program Optimization)および/G 7(Pentium 4またはAMD Athlonに最適化されたコードを生成することができる)である.SSE 2レジスタと命令に対して最適化されたコードを生成できるオプション/arch:SSE 2もあります.
サンプル・コードには、次の3つのテストがあります.
  • は、インライン候補関数としての関数を呼び出す.
  • は、多数の浮動小数点乗算および加算演算を実行する.
  • は、多数の整数乗算および加算演算を実行する.

  • 完全なプログラム最適化


    サンプルコードは、Add()とDisplayAdd()の2つの非常に類似した関数を定義します.DisplayAdd()は画面に表示されるので、接続することはできません.
    void DisplayAdd(int a, int b)
    {
       cout << a << " + " << b << " = " << a + b << endl;
       cout << "Return address from " << __FUNCTION__ 
            << " " << _ReturnAddress() << endl;
    }
    

    _ReturnAddressは内部関数で、制御がどこで返されるかをレポートします.インライン関数を識別するために使用できます.
    Add()はgl-g 7にある.cppで宣言するとともに、設定されたグローバル変数も宣言します.
    void* inlineReturnAddress; // set in Add()
    int Add(int a, int b); // implementation in module.cpp
    

    実装はmodule.cpp:
    int Add(int a, int b)
    {
       inlineReturnAddress = _ReturnAddress();
       return a+b;
    }
    

    Whole Pr gram Optimizationを使用せずにプログラムをコンパイルするには、次のコマンドラインを使用します.
    cl /O2 /ML /EHsc GL-G7.cpp module.cpp 
    

    テスト1を実行するには、次のコマンドを使用します.
    gl-g7 1
    

    次のような出力が表示されます(数値アドレスが異なります).
    1 + 2 = 3
    Return address from DisplayAdd 00401D0A
    1 + 2 = 3
    Return address from Add 00401D13
    Return address from Test1 00402125
    

    Add()の戻りアドレスはTest 1()の戻りアドレスとは異なり、Add()はインラインされていない.
    これで、/GLを使用して再コンパイル:
    cl /O2 /ML /EHsc /GL GL-G7.cpp module.cpp 
    

    テスト1を再実行すると、次のような出力が表示されます.
    1 + 2 = 3
    Return address from DisplayAdd 00401242
    1 + 2 = 3
    Return address from Add 0040179F
    Return address from Test1 0040179F
    

    現在、Add()はTest 1()の戻りアドレスと同じです.Add()は、コードが別のファイルから来てもTest 1()内部に接続されています.

    Intel Pentium 4またはAMD Athlon最適化コード


    G 7はMicrosoft?Visual Studio?.NET 2003の新しいオプション;他の場合と異なる命令を選択することによってPentium 4またはAMD Athlon最適化のためのコードが生成される.整数を乗算する(特に、コンパイル時に既知の定数に整数を乗算する)ルーチンでは、パフォーマンスの改善が最も顕著である.
    テスト2では、取得可能な速度の改善を示します.
    #define INT_ARRAY_LEN 100000
    int intarray[INT_ARRAY_LEN];
    int intCalculate()
    {
       int total = 0;
    
       for (int i = 1; i < INT_ARRAY_LEN; i++)
       {
             total += intarray[i-1]*7;
       }
    
       return total;
    }
    
    void Test2()
    {
       int var1 = 2;
       int i;
    
       for (i = 0; i < INT_ARRAY_LEN; i++)
       {
             intarray[i] = i*5;
             var1 += 2;
       }
    
       LARGE_INTEGER start, end;
       LARGE_INTEGER freq;
    
       SetThreadAffinityMask(GetCurrentThread(), 1);
       QueryPerformanceFrequency(&freq);
       QueryPerformanceCounter(&start);
       double total = 0;
    
       for (i = 0; i < 100000; i++)
       {
          total += intCalculate();
       }
    
       QueryPerformanceCounter(&end);
    
       cout << "Total = " << total << endl;
    
       cout << (end.QuadPart - start.QuadPart)/(double)freq.QuadPart << " seconds" << endl;
    }
    

    上記のコードはkernel 32にいくつか使用する.dll(Microsoft?Windows?の一部)で実装されるタイミング関数です.これらの関数とそれらが使用するデータ型はwindows.hで定義します.この例における依存性を低減するためにgl-g 7.cppでは、これらの関数のプロトタイプが提供され、対応するデータ型が定義されています.QueryPerformanceCounterは開始時間または終了時間を保存し、QueryPerformanceFrequencyは1つの値を得、除算演算により開始時間と終了時間の差を得て秒単位の運転時間を得る.SetThreadAffinityMaskの呼び出しは、マルチプロセッサコンピュータ上の人の仕事を減らす.
    このルーチンは、大量の整数乗算を実行します.プロセッサ固有のコマンドを使用せずにコンパイルするには、次のコマンドラインを使用します.
    cl /O2 /ML /EHsc GL-G7.cpp module.cpp 
    

    Pentium 4またはAMD Athlonコンピュータをコンパイルするには、次のコマンドラインを使用します.
    cl /O2 /ML /EHsc /G7 GL-G7.cpp module.cpp 
    

    テスト2を実行するには、次のコマンドラインを使用します.
    gl-g7 2
    

    Pentium 4またはAMD Athlonコンピュータでは、/G 7バージョンの稼働速度が10%以上向上しました.上記のコードは、適切なチップを持たないコンピュータ上で実行することができるが、コンパイル時に/G 7を使用していないバージョンに比べて速度がやや遅い.

    Streaming SIMD Extensions 2


    SSE 2でサポートされているコンピュータ(Pentium 4またはAMD Athlonコンピュータなど)にコードを生成すると確信している場合は、/arch:SSE 2オプションを使用します.このようにして生成されたコードは、他のチップ上で実行することはできないが、特に浮動小数点アルゴリズムが大量に含まれるルーチンでは、より高速である.
    テスト3は、テスト2と極めて類似した浮動小数点計算を実行します.
    #define ARRAY_LEN 10000
    double array[ARRAY_LEN];
    
    double Calculate()
    {
       double total = 0;
    
       for (int i = 1; i < ARRAY_LEN; i++)
       {
             total += array[i-1]*array[i];
       }
    
       return total;
    }
    
    void Test2()
    {
       double var1 = 2;
       int i;
    
       for (i = 0; i < ARRAY_LEN; i++)
       {
             array[i] = var1;
             var1 += .012;
       }
    
       LARGE_INTEGER start, end;
       LARGE_INTEGER freq;
    
       SetThreadAffinityMask(GetCurrentThread(), 1);
       QueryPerformanceFrequency(&freq);
       QueryPerformanceCounter(&start);
       double total = 0;
    
       for (i = 0; i < 100000; i++)
       {
          total += Calculate();
       }
    
       QueryPerformanceCounter(&end);
    
       cout << "Total = " << total << endl;
    
       cout << (end.QuadPart - start.QuadPart)/(double)freq.QuadPart << " seconds" << endl;
    }
    

    プロセッサ固有のコマンドを使用せずにコンパイルするには、次のコマンドラインを使用します.
    cl /O2 /ML /EHsc GL-G7.cpp module.cpp 
    

    Pentium 4またはAMD Athlonコンピュータのみをコンパイルするには、次のコマンドラインを使用します.
    cl /O2 /ML /EHsc /G7 /arch:SSE2 GL-G7.cpp module.cpp 
    

    テスト3を実行するには、次のコマンドラインを使用します.
    gl-g7 3
    

    Pentium 4またはAMD Athlonコンピュータでは、/G 7/arch:SSE 2バージョンの稼働速度が約10%向上しました.上記のコードは、適切なチップを持たないコンピュータでは動作しません.

    Visual Studioがあれば


    上記のオプションはすべて[Project Properties]ダイアログボックスで使用できます.
     
    図1.全般アイテムのプロパティ
     
    図2.C/C++最適化オプション
     
    図3.C/C++コード生成オプション
    特定のチップにカスタムバージョンを生成する場合は、さまざまな構成を作成できます.各構成には異なるオプションの組み合わせがあります.

    小結


    異なるプログラムは異なる方法で最適化に応答する.モジュールごとの最適化も悪くないが、完全なプログラム最適化を追加すると、明らかな改善が得られる.コードを変更せずに使用できるので、そうしない理由はありません.
    ほとんどのユーザーまたはパフォーマンスに敏感なすべてのユーザーがPentium 4またはAMD Athlonコンピュータを持っている場合は、/G 7オプションを使用して、これらのユーザーのためにより高速なコードを生成します.また、このようなコードは他のユーザーにとって少し遅いことを覚えておいてください.Pentium 4またはAMD Athlonコンピュータの特定の最適化バージョンを作成する場合は、/arch:SSE 2オプションを併用して最適なパフォーマンスを実現します.