手動 CPU ディスパッチ (IA-32 のみ)

__declspec(cpu_specific) および __declspec(cpu_dispatch) をコードに使用して、アプリケーションが実行されるプロセッサに特有の命令を生成し、また他のプロセッサ上でも正常に実行できるようにします。

手動 CPU ディスパッチは、インテル® Itanium® プロセッサの認識には使用できません。これらの拡張属性の構文は以下のとおりです:

cpuid および cpuid-list の値は、下の表のとおりです:

プロセッサ cpuid の値
インテル以外から提供されている x86 プロセッサ generic
インテル® Pentium® プロセッサ pentium
インテル MMX® テクノロジ Pentium プロセッサ pentium_mmx
インテル Pentium Pro プロセッサ pentium_pro
インテル Pentium II プロセッサ pentium_ii
インテル Pentium III プロセッサ pentium_iii
インテル Pentium III (xmm レジスタを除く) pentium_iii_no_xmm_regs
インテル Pentium 4 プロセッサ pentium_4
インテル Pentium M プロセッサ pentium_m
HT テクノロジ インテル Pentium 4 プロセッサ (SSE3 対応) future_cpu_10

 

cpuid-list の値
cpuid
cpuid-list, cpuid

属性は大文字と小文字の区別はありません。__declspec(cpu_dispatch) を宣言した関数本体は空でなければなりません。そして、これはスタブ (empty-bodied関数) と呼ばれます。

次のガイドラインに従って、自動プロセッサ・ディスパッチ・サポートを使用してください:

  1. cpu_dispatch のスタブは、cpu_specific で定義された cpuid を持っていなければなりません。
    関数 fcpu_dispatch スタブが cpuid p を持つ場合、cpuid p を持つ fcpu_specific 定義をプログラムのどこかに記述する必要があります。そうでない場合、未解決外部エラーとなります。cpu_specific 関数が static で宣言されない限り、cpu_specific 関数の定義は、対応する cpu_dispatch スタブと同じ交換単位に記述する必要はありません。インライン属性は、すべての cpu_specific および cpu_dispatch 関数で、無効です。
  2. cpu_specific 関数のスタブを持つ必要があります。
    関数 f__declspec(cpu_specific(p)) として定義した場合、cpu_dispatch スタブもまたプログラム内で f に記述する必要があります。そして、p は、そのスタブの cpuid-list になければなりません。そうでない場合、cpu_specific 定義は呼び出されず、またエラー条件も生成しません。
  3. コマンドライン設定の上書き
    cpu_dispatch
    スタブをコンパイルすると、その本体は、プログラムが実行されているプロセッサを決定するコードに置き換えられます。そして、cpuid-list に定義された利用可能な "ベストの" cpu_specific 関数をディスパッチします。cpu_specific 関数は、コマンドライン・オプションの設定にかかわらず、指定されたプロセッサに応じて最適化します。

プロセッサ・ディスパッチ例

これらの関数の使用方法の例を次に示します:

#include <mmintrin.h>

/* Pentium processor function does not use intrinsics to add two arrays. */

 

__declspec(cpu_specific(pentium))

void array_sum(int *r, int *a, int *b,size_t l)

{

   for (; length > 0; l--)

   *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_sum(int *r,int const *a, int *b, size_t l)

{

   __m64 *mmx_result = (__m64 *)result;

   __m64 const *mmx_a = (__m64 const *)a;

   __m64 const *mmx_b = (__m64 const *)b;

 

   for (; length > 3; length -= 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_r;

   a = (unsigned short const *)mmx_a;

   b = (unsigned short const *)mmx_b;

 

   for (; length > 0; l--)

   *result++ = *a++ + *b++;

}

 

__declspec(cpu_dispatch(pentium, pentium_MMX))

void array_sum (int *r,int const *a, int *b, size_t l) )

 

{

 

/* Empty function body informs the compiler to generate the

CPU-dispatch function listed in the cpu_dispatch clause. */

 

}