ベクトル化のサポート

これらのプラグマは、プログラム中の後に続くループのベクトル化を制御しますが、コンパイラーは入れ子されたループには適用しません。入れ子されたそれぞれのループの前に、プラグマ文が必要です。loop 文の前にプラグマを配置してください。

vector always プラグマ

構文

#pragma vector always

vector always プラグマは、ベクトル化するかどうかを決定する際、効率ヒューリスティックを無効にするようコンパイラーに指示します。そして 1 以外のストライドまたはほとんどアライメントの合っていないメモリーアクセスをベクトル化します。

例: vector always 宣言子

void vec_always(int *a, int *b, int m)

{

  #pragma vector always

  for(int i = 0; i <= m; i++)

    a[32*i] = b[99*i];

}

ivdep プラグマ

構文

#pragma ivdep

ivdep プラグマは、ベクトル依存性が存在していると推定されてもそれを無視するようコンパイラーに指示します。正しいコードにするため、コンパイラーは、想定される依存性を証明された依存性として扱い、ベクトル化を行わないようにします。このプラグマは、その決定を無視します。推定されたループの依存性が安全で、無視できる場合にのみ使用してください。

この例のループは、k の値が不明なため、ivdep プラグマなしではベクトル化を行いません (ベクトル化は k < 0 の場合、不正です)。

void ignore_vec_dep(int *a, int k, int c, int m)

{

  #pragma ivdep

  for (int i = 0; i < m; i++)

    a[i] = a[i + k] * c;

}

プラグマは、現在の関数に含まれている for ループだけをバインドします。これには、現在の関数によって呼び出されるサブ関数に含まれる for ループも含まれます。

vector プラグマ

構文

#pragma vector {aligned | unaligned}

プラグマは、ループのベクトル化が可能である限り、ベクトル化によるメリットの有無についての通常のヒューリスティックな判断を無視してベクトル化を行うことを示します。aligned または unaligned 指示子が使用されると、ループは、aligned または unaligned 演算を使用して、ベクトル化されます。aligned または unaligned のいずれか 1 つを指定します。 

警告

引数として aligned を指定する場合、ループはこの命令を使用してベクトル化可能であることが確実でなければなりません。それ以外の場合、コンパイラーは誤ったコードを生成します。

次の例に示すループは、コンパイラーは通常それが安全であると証明できないように配列が宣言されているため、aligned 指示子を使用して、aligned 命令でループがベクトル化されるように要求を出します。

void vec_aligned(float *a, int m, int c)

{

  int i;

  // Instruct compiler to ignore assumed vector dependencies.

  #pragma vector aligned

  for (i = 0; i < m; i++)

    a[i] = a[i] * c;

  // Alignment unknown but compiler can still align.

  for (i = 0; i < 100; i++)

    a[i] = a[i] + 1.0f;

}

コンパイラーは、コンパイル時にデータ構造のアライメントが不明な場合に備えて、いくつかのアライメント手法を用意しています。簡単な例を次に示します (ただし、他の方法もサポートされています)。ループにおいて、アライメントが不明な場合、コンパイラーはプレリュードのループを生成し、ほとんどの場合に発生する配列参照がアライメントされたアドレスにヒットするまでループを反復します。

例: アライメント手法

float *a;

// Alignment unknown

for (i = 0; i < 100; i++)

{

   a[i] = a[i] + 1.0f;

}

// Dynamic loop peeling

p = a & 0x0f;

if (p != 0)

{

   p = (16 - p) / 4;

   for (i = 0; i < p; i++)

   {

      a[i] = a[i] + 1.0f;

   }

}

// Loop with a aligned (will be vectorized accordingly)

for (i = p; i < 100; i++)

{

   a[i] = a[i] + 1.0f;

}

novector プラグマ

構文

#pragma novector

プラグマは、ループのベクトル化が有効な場合でもループをベクトル化しないことを示します。この例では、反復回数 (ub - lb) が低すぎて、ベクトル化が無駄になるとわかっています。novector を使用して、ループがベクトル化可能であると認識されても、コンパイラーにベクトル化しないように指示できます。

例: novector 宣言子

void foo(int lb, int ub)

{

  #pragma novector

  for(j=lb; j<ub; j++)

  {

     a[j]=a[j]+b[j];

  }

}

vector nontemporal プラグマ (Windows*)

構文

#pragma vector nontemporal

IA-32 アーキテクチャー・ベースのシステムでストリーミング・ストアをもたらします。生成されたアセンブリーとのループ (float 型) の例は、次のとおりです。N が大きくなると、インテル(R) Pentium(R) 4 プロセッサー・システムでの非ストリーミング組み込み関数のパフォーマンスが大幅に向上します。

#pragma vector nontemporal

for (i = 0; i < N; i++)

  a[i] = 1;

  .B1.2:

movntps XMMWORD PTR _a[eax], xmm0

movntps XMMWORD PTR _a[eax+16], xmm0

add eax, 32

cmp eax, 4096

jl .B1.2

 

例: 動的依存性のテスト例

float *p, *q;

for (i = L; I <= U; i++)

{

  p[i] = q[i];

}

...

pL = p * 4*L;

pH = p + 4*U;

qL = q + 4*L;

qH = q + 4*U;

if (pH < qL || pL > qH)

{

  // loop without data dependence

  for (i = L; i <= U; i++)

  {

     p[i] = q[i];

  } else {

  for (i = L; i <= U; i++)

  {

     p[i] = q[i];

  }

}