手動のプロセッサー・ディスパッチを使用すると、cpu_specific キーワードと cpu_dispatch キーワードにより、実行時に IA-32 またはインテル® 64 アーキテクチャー・プロセッサーを認識でき、ターゲット・プロセッサーのみで実行するコードパスと、その他のプロセッサーで実行するコードパスを作成することができます。
ターゲットのインテル® プロセッサー固有のコードを作成して、さらにほかの IA-32 またはインテル® 64 アーキテクチャー・プロセッサーでも正常に動作するよにするには、コードで __declspec(cpu_specific) および __declspec(cpu_dispatch) 構文を使用します。
これらの C++ キーワードの使用に関しての情報は、「アプリケーションのビルド」の「言語が混在したプログラミング」を参照してください。
これらのキーワードの一般的な構文は、次の引数を使用して関数宣言を変更します。
cpu_specific(cpuid)
cpu_dispatch(cpuid-list)
次の表は、cpuid の値を列挙したものです。
cpuid の引数 |
プロセッサー |
---|---|
core_aes_pclmulqdq |
AES (Advanced Encryption Standard) 命令およびキャリーなし乗算命令対応インテル® Core™ プロセッサー |
core_i7_sse4_2 |
インテル® ストリーミング SIMD 拡張命令 4.2 (SSE4.2) 対応インテル® Core™ i7 プロセッサー |
core_2_duo_sse4_1 |
ストリーミング SIMD 拡張命令 4.1 (SSE4.1) 対応インテル® 45nm Hi-k 次世代 インテル® Core™ プロセッサー |
core_2_duo_ssse3 |
インテル® Core™2 Duo プロセッサーおよびインテル® ストリーミング SIMD 拡張命令 3 補足命令 (SSSE3) 対応インテル® Xeon® プロセッサー |
pentium_4_sse3 |
インテル® ストリーミング SIMD 拡張命令 3 (SSE3) 対応インテル® Pentium® 4 プロセッサー、インテル® Core™ Duo プロセッサー、インテル® Core™ Solo プロセッサー |
pentium_4 |
インテル® Pentium® 4 プロセッサー |
pentium_m |
インテル® Pentium® M プロセッサー |
pentium_iii |
インテル® Pentium® III プロセッサー |
generic |
インテル以外から提供されている x86 プロセッサー |
次の表は、cpuid-list の構文を列挙したものです。
cpuid-list の構文 |
---|
cpuid |
cpuid-list、cpuid |
属性は大文字と小文字の区別はありません。__declspec(cpu_dispatch) を宣言した関数本体は空でなければなりません。そして、これはスタブ (本体が空の関数) と呼ばれます。
手動プロセッサー・ディスパッチは、一部の種類のインライン化を無効にすることがあります。ほとんどの場合、作成されるコードと実行ファイルのサイズは大きくなります。追加の関数呼び出しが行われるため、パフォーマンスのオーバーヘッドがさらに増加することがあります。リリース前に、ターゲットとするすべてのプラットフォームでアプリケーションをテストしてください。手動ディスパッチを使用する前に、この機能を使用するメリットがデメリット (追加工数とパフォーマンス低下の可能性) よりも重要かどうかをよく考慮してください。
プロセッサー・ディスパッチ・サポートを実装するには、次のガイドラインに従ってください。
関数 f の cpu_dispatch スタブが cpuid p を含む場合、cpu_dispatch のスタブは cpu_specific で定義された cpuid を持っている必要があります。また、cpuid p を含む f の cpu_specific 定義をプログラムのどこかに記述する必要があります。そうでない場合、未解決外部エラーとなります。
cpu_specific 関数が static で宣言されない限り、cpu_specific 関数の定義は、対応する cpu_dispatch スタブと同じ交換単位に記述する必要はありません。インライン属性は、すべての cpu_specific および cpu_dispatch 関数で無効です。
関数 f を __declspec(cpu_specific(p)) として定義した場合、cpu_specific 関数のスタブを持つ必要があります。また、cpu_dispatch スタブもプログラム内で f に記述する必要があります。p は、そのスタブの cpuid-list になければなりません。そうでない場合、cpu_specific 定義は呼び出されず、またエラー条件も生成しません。cpu_dispatch スタブをコンパイルすると、コマンドラインの設定は無視され、その本体は、プログラムが実行されているプロセッサーを決定するコードに置き換えられます。そして、cpuid-list に定義された利用可能な "ベストの" cpu_specific 実装をディスパッチします。
cpu_specific ルーチンを使用して特定のインテル® プロセッサー向けに最適化します。コンパイルは、命令セットを定義するコマンドライン・オプションまたはコンパイラーのデフォルト値に依存します。特定のプロセッサー向けに cpu_specific ルーチンを定義し、より新しいプロセッサー向けの命令でコンパイルすると、コードにはこの新しいプロセッサー向け命令も含まれます。
次の例では、cpu_specific と cpu_dispatch の両方を含む手動ディスパッチの使用方法を示します。
例 |
---|
#include <stdio.h> #include <mmintrin.h> /* Pentium processor function does not use intrinsics to add two arrays. */ __declspec(cpu_specific(pentium)) void array_sum1(int *result, int *a, int *b, size_t len) { for (; len > 0; len--) *result++ = *a++ + *b++; } /* Implementation for a Pentium processor with MMX technology uses an MMX instruction intrinsic to add four elements simultaneously. */ __declspec(cpu_specific(pentium_MMX)) void array_sum2(int *result, int const *a, int *b, size_t len) { __m64 *mmx_result = (__m64 *)result; __m64 const *mmx_a = (__m64 const *)a; __m64 const *mmx_b = (__m64 const *)b; for (; len > 3; len -= 4) *mmx_result++ = _mm_add_pi16(*mmx_a++, *mmx_b++); /* The following code, which takes care of excess elements, is not needed if the array sizes passed are known to be multiples of four. */ result = (unsigned short *)mmx_result; a = (unsigned short const *)mmx_a; b = (unsigned short const *)mmx_b; for (; len > 0; len--) *result++ = *a++ + *b++; } __declspec(cpu_dispatch(pentium, pentium_MMX)) void array_sum3(int *result, int const *a, int *b, size_t len) { /* Empty function body informs the compiler to generate the CPU-dispatch function listed in the cpu_dispatch clause. */ } |
© 1996-2010 Intel Corporation. 無断での引用、転載を禁じます。