vector 宣言子は、プログラム中の後に続くループのベクトル化を制御しますが、コンパイラーは入れ子されたループには適用しません。入れ子されたそれぞれのループは、その前に、固有の宣言子が必要です。vector 宣言子は、loop 文の前に配置してください。
vector always 宣言子は、ベクトル化するかどうかを決定する際、効率ヒューリスティックを無効にするようコンパイラーに命令します。そして 1 以外のストライドまたはほとんどアライメントの合っていないメモリーアクセスをベクトル化します。
例: vector always 宣言子 |
---|
#pragma vector always for(i=0; i<=N; i++) { a[32*i]=b[99*i]; } |
ivdep 宣言子は、ベクトル依存性が存在していると推定されてもそれを無視するようコンパイラーに命令します。正しいコードにするため、コンパイラーは、想定される依存性を証明された依存性として扱い、ベクトル化を行わないようにします。この宣言子は、その決定を無視します。推定されたループの依存性が安全で、無視できる場合にのみ ivdep を使用してください。下記の例のループは、k の値が不明なため、ivdep ではベクトル化を行いません (ベクトル化は k < 0 の場合、不正です)。
例: ivdep 宣言子 |
---|
#pragma ivdep for(i=0; i<m; i++) { a[i]=a[i+k]*c; } |
構文 |
---|
#pragma vector{aligned | unaligned} |
vector ループプラグマは、ループのベクトル化が可能である限り、ベクトル化によるメリットの存否についての通常のヒューリスティックな判断を無視してベクトル化を行います。aligned または unaligned 指示子が使用されると、ループは、aligned または unaligned 演算を使用して、ベクトル化されます。aligned または unaligned のいずれか 1 つを指定します。
引数として aligned を指定する場合、ループはこの命令を使用してベクトル化可能であることが確実でなければなりません。それ以外の場合、コンパイラーは誤ったコードを生成します。
次の例に示すループは、コンパイラーは通常それが安全であると証明できないように配列が宣言されているため、aligned 指示子を使用して、aligned 命令でループがベクトル化されるように要求を出します。
例 |
---|
void foo (float *a) { #pragma vector aligned for (i = 0; i < m; i++) { a[i] = a[i] * c; } } |
コンパイラーは、コンパイル時にデータ構造のアライメントが不明な場合に備えて、いくつかのアライメント手法を用意しています。簡単な例を次に示します (ただし、他の方法もサポートされています)。次の例のループにおいて、a のアライメントが不明な場合、コンパイラーはプレリュードのループを生成し、ほとんどの場合に発生する配列参照がアライメントされたアドレスにヒットするまでループを繰返します。これにより、a のアライメント・プロパティーが判明し、そのプロパティーに応じてベクトルループが最適化されます。
例: アライメント手法 |
---|
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 宣言子は、ループのベクトル化が有効であっても、ベクトル化を行わないよう指定します。この例では、反復回数 (ub - lb) が低すぎて、ベクトル化が無駄になるとわかっています。novector を使用して、ループがベクトル化可能であると認識されても、コンパイラーにベクトル化しないように指示できます。
例: novector 宣言子 |
---|
void foo(int lb, int ub) { #pragma novector for(j=lb; j<ub; j++) { a[j]=a[j]+b[j]; } } |
構文 |
---|
#pragma vector nontemporal |
#pragma vector nontemporal は、インテル Pentium 4 プロセッサー・ベースのシステムでストリーミング・ストアをもたらします。生成されたアセンブリーとのループ (float 型) の例は、次のとおりです。N が大きくなると、インテル Pentium 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]; } } |