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; } |
vector alignedディレクティブは、ループのベクトル化が可能である限り、ベクトル化によるメリットの存否についての通常のヒューリスティックな判断を無視してベクトル化を行います。alignedまたはunaligned指示子が使用されると、ループは、alignedまたはunaligned演算を使用して、ベクトル化されます。alignedまたはunalignedのいずれか1つを指定します。
注意
アライメントされているものを引数に指定する場合、ループはこの命令を使用してベクトル化可能であることが確実でなければなりません。それ以外の場合、コンパイラは誤ったコードを生成します。次の例に示したループは、アライメントされた指示子を使用して、アライメントされた命令でループがベクトル化されるように要求を出します。コンパイラは通常そうすることが安全であると証明できないように、配列が宣言されているためです。
vector 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]; } } |