インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス
手動プロセッサー・ディスパッチ機能を使用すると、手動でターゲット・プロセッサーを指定できます。プロセッサー・ディスパッチを制御する方法はいくつかあります。
Linux* の attribute または Windows* の __declspecs で cpu_specific および cpu_dispatch キーワードを指定することで、特定のインテル® プロセッサーでのみ実行する関数のバージョンを作成したり、ほかのインテル® プロセッサーとインテル以外のプロセッサーで実行する汎用バージョンを作成できます。ランタイムにインテル® プロセッサーの種類が検出され、対応する関数バージョンが実行されます。この機能は、IA-32 またはインテル® 64 アーキテクチャー・ベースのインテル® プロセッサーでのみ利用できます。インテル以外のプロセッサーでは利用できません。手動プロセッサー・ディスパッチ機能を使用してビルドしたアプリケーションは、互換プロセッサーよりもインテル® プロセッサーでより高度に最適化されることがあります。
詳細は、下記を参照してください。
optimization_parameter プラグマを使用します。
詳細は、下記を参照してください。
Linux* では、インテルの cpu_specific および cpu_dispatch 属性に加えて、GNU* コンパイラー・コレクション (GCC) 4.8 以上による C++ コンパイルで、target 属性を指定して複数の関数バージョンを作成することができます。
詳細は、GCC ドキュメントの複数の関数バージョンに関するトピックを参照してください。
コードで __declspec(cpu_dispatch(cpuid, cpuid,...)) 構文を使用すると、ターゲット・プロセッサーのリストと空の関数本体/関数スタブを提供できます。__declspec(cpu_specific(cpuid)) を使用すると、各関数のプロセッサー固有バージョンを宣言できます。
cpuid に設定可能な値は、cpu_specific にあるリストを参照してください。
一致するインテル® プロセッサーが検出されない場合は、generic バージョンの関数が実行されます。インテル以外のプロセッサーでプログラムを実行する場合は、generic バージョンの関数を提供する必要があります。generic バージョンの最適化の程度と想定するプロセッサー機能は制御することができます。
cpuid 属性は大文字と小文字の区別はありません。__declspec(cpu_dispatch) を宣言した関数本体は空でなければなりません。そして、これはスタブ (本体が空の関数) と呼ばれます。
次の例は、cpu_dispatch キーワードと cpu_specific キーワードを使用して、インテル® アドバンスト・ベクトル・エクステンション (インテル® AVX) をサポートする第 2 世代インテル® Core™ プロセッサー・ファミリー、インテル® Core™ プロセッサー・ファミリー、インテル® Core™2 Duo プロセッサー・ファミリー、およびその他のインテル® プロセッサーまたは互換プロセッサー向けの関数バージョンを作成する方法を示します。それぞれのプロセッサー固有関数バージョンは、プロセッサー固有の組込み関数を使用しているか、または個別のソースファイルに配置され、プロセッサー固有のコンパイラー・オプションでコンパイルされています。
例 |
---|
#include <stdio.h> // 次のプロセッサー向けに特定の関数バージョンを生成する必要がある __declspec(cpu_dispatch(core_2nd_gen_avx, core_i7_sse4_2, core_2_duo_ssse3, generic )) void dispatch_func() {}; // 適切な関数バージョンを呼び出すスタブ __declspec(cpu_specific(core_2nd_gen_avx)) void dispatch_func() { printf("\nCode for 2nd generation Intel Core processors with support for Intel AVX goes here\n"); } __declspec(cpu_specific(core_i7_sse4_2)) void dispatch_func() { printf("\nCode for Intel Core processors with support for SSE4.2 goes here\n"); } __declspec(cpu_specific(core_2_duo_ssse3)) void dispatch_func() { printf("\nCode for Intel Core 2 Duo processors with support for SSSE3 goes here\n"); } __declspec(cpu_specific(generic)) void dispatch_func() { printf("\nCode for non-Intel processors and generic Intel processors goes here\n"); } int main() { dispatch_func(); printf("Return from dispatch_func\n"); return 0; } |
手動ディスパッチを使用する前に、この機能を使用するメリットがデメリット (追加工数とパフォーマンス低下の可能性) よりも重要かどうかをよく考慮してください。コードで手動プロセッサー・ディスパッチを使用する場合、次のような問題が発生することがあります。
コードと実行ファイルのサイズが非常に大きくなります。
関数呼び出しの追加によりパフォーマンス・オーバーヘッドが増えます。
リリース前に、すべてのターゲット・プラットフォームでアプリケーションをテストしてください。
#pragma intel optimization_parameter target_arch を使用して、特定のインテル® プロセッサーで実行するルーチンに対してコードでフラグを設定できます。このプラグマは、ルーチンレベルで -m オプションや /arch オプションを制御し、コマンドラインで指定されたオプションの値よりも優先されます。ターゲット・プロセッサーには、-m オプションや /arch オプションと同じ値を使用します。次の例は、コマンドラインで指定された値に関係なく、プラグマを使用してルーチン bar() をインテル® AVX 対応プロセッサーでのみ実行するようにする方法を示します。
例 |
---|
include <immintrin.h> #define N 1024 double x[N], y[N], z[N]; void VectorMultiply(int allow_avx) { int i; if (allow_avx) { _allow_cpu_features(_FEATURE_AVX); for (i = 0; i < N; i++) { z[i] = x[i] * y[i]; } } else { for (i = 0; i < N; i++) { z[i] = x[i] * y[i]; } } } |
また、_allow_cpu_features 組込み関数を使用して、コード領域が特定の機能をサポートするプロセッサー専用であることをコンパイラーに伝え、_may_i_use_cpu_feature で、プロセッサー固有機能が利用可能かどうか判断するため、ソースレベルで動的にプロセッサーに問い合わせることができます。
最適化に関する注意事項 |
---|
インテル® コンパイラーでは、インテル® マイクロプロセッサーに限定されない最適化に関して、他社製マイクロプロセッサー用に同等の最適化を行えないことがあります。これには、インテル® ストリーミング SIMD 拡張命令 2、インテル® ストリーミング SIMD 拡張命令 3、インテル® ストリーミング SIMD 拡張命令 3 補足命令などの最適化が該当します。インテルは、他社製マイクロプロセッサーに関して、いかなる最適化の利用、機能、または効果も保証いたしません。本製品のマイクロプロセッサー依存の最適化は、インテル® マイクロプロセッサーでの使用を前提としています。インテル® マイクロアーキテクチャーに限定されない最適化のなかにも、インテル® マイクロプロセッサー用のものがあります。この注意事項で言及した命令セットの詳細については、該当する製品のユーザー・リファレンス・ガイドを参照してください。 注意事項の改訂 #20110804 |