手動で IA-32 アーキテクチャー・ベースのプロセッサーを対象にする

手動のプロセッサー・ディスパッチを使用すると、cpu_specific キーワードと cpu_dispatch キーワードによって実行時に IA-32 アーキテクチャーをベースとしたプロセッサーを認識でき、ターゲット・プロセッサーのみで実行するコードを作成することが可能です。手動のプロセッサー・ディスパッチは、IA-64 アーキテクチャーをベースとしたプロセッサーは認識しません。

ターゲットのインテル(R) プロセッサー固有のコードを作成して、さらに他の IA-32 プロセッサーでもアプリケーションが正常に動作するようにするには、コードで __declspec(cpu_specific) および __declspec(cpu_dispatch) 構文を使用します。

これらのキーワードの一般的な構文は、次の引数を使用して関数宣言を変更します。

次の表は、cpuid の値を列挙したものです。

cpuid引数

プロセッサー

core_2_duo_ssse3

インテル(R) Core(TM)2 Duo プロセッサーおよびストリーミング SIMD 拡張命令 3 補足命令 (SSSE3) 対応インテル(R) Xeon(R) プロセッサー

pentium_4_sse3

ストリーミング SIMD 拡張命令 3 (SSE3) 対応インテル(R) Pentium(R) 4 プロセッサー、インテル Core Duo プロセッサー、インテル(R) Core(TM) Solo プロセッサー

pentium_4

インテル Pentium 4 プロセッサー

pentium_m

インテル Pentium M プロセッサー

pentium_iii_no_xmm_regs

インテル Pentium III (xmm レジスターを除く)

pentium_iii

インテル Pentium III プロセッサー

pentium_ii

インテル Pentium II プロセッサー

pentium_pro

インテル Pentium Pro プロセッサー

pentium_mmx

MMX(R) テクノロジー インテル Pentium プロセッサー

pentium

インテル Pentium プロセッサー

generic

インテル以外から提供されている x86 プロセッサー

次の表は、cpuid-list の構文を列挙したものです。

cpuid-list構文

cpuid

cpuid-list、cpuid

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

手動プロセッサー・ディスパッチは、一部の種類のインライン化を無効にすることがあります。ほとんどの場合、作成されるコードと実行ファイルのサイズは大きくなります。追加の関数呼び出しが行われるため、パフォーマンスのオーバーヘッドがさらに増加することがあります。リリース前に、ターゲットとするすべてのプラットフォームでアプリケーションをテストしてください。手動ディスパッチを使用する前に、この機能を使用するメリットがデメリット (工数が余計にかかり、パフォーマンスが低下する可能性がある) よりも重要かどうかをよく考慮してください。

プロセッサー・ディスパッチ・サポートを実装するには、次のガイドラインに従ってください。

次の例では、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.*/

}