ループを引数キーワード (always/aligned/unaligned/nontemporal/temporal) に従ってベクトル化するようにコンパイラーに指示します。
#pragma vector {always|aligned|unaligned|nontemporal|temporal} |
#pragma vector nontemporal[(var1[, var2, ...])] |
always |
ベクトル化するかどうかを決定する際、効率ヒューリスティックを無効にするようコンパイラーに指示します。非ユニットストライドまたはほとんどアライメントの合っていないメモリーアクセスをベクトル化して、プログラムで後に続くループのベクトル化を制御します。 |
aligned |
ベクトル化の際にすべての配列参照に対して aligned データ移動命令を使用するようにコンパイラーに指示します。 |
unaligned |
ベクトル化の際にすべての配列参照に対して unaligned データ移動命令を使用するようにコンパイラーに指示します。 |
nontemporal |
IA-32 およびインテル(R) 64 アーキテクチャー・ベースのシステムでは、一時的ではない (ストリーミング) ストアを使用するようにコンパイラーに指示します。オプションでカンマ区切りの変数リストも指定できます。 |
temporal |
IA-32 およびインテル(R) 64 アーキテクチャー・ベースのシステムでは、一時的な (非ストリーミング) ストアを使用するようにコンパイラーに指示します。 |
vector プラグマは、ループのベクトル化が可能である限り、ベクトル化によるメリットの有無に関する通常のヒューリスティックな判断を無視してベクトル化を行うように指示します。vector プラグマは、引数キーワードを使用して必要なループのベクトル化の種類を指定します。キーワードは、aligned、unaligned、always、および nontemporal です。
aligned/unaligned キーワードの使用
このプラグマで aligned/unaligned 引数キーワードが使用された場合、すべての配列参照に対して aligned/unaligned データ移動命令を使用してループをベクトル化することを示します。引数キーワードとして aligned または unaligned のいずれかを指定します。
引数として aligned を指定する場合、ループはこのプラグマを使用してベクトル化可能であることが確実でなければなりません。それ以外の場合、コンパイラーは誤ったコードを生成します。
always キーワードの使用
always 引数キーワードが使用されると、プラグマは後に続くループのベクトル化を制御します。コンパイラーは入れ子のループに vector プラグマを適用しないため、入れ子にされたそれぞれのループの前に、プラグマ文が必要です。loop 制御文の前にプラグマを配置してください。
vector{always|aligned|unaligned} プラグマは注意して使用してください。コンパイラーの効率性ヒューリスティックの変更は、ベクトル化によりパフォーマンスが向上することが確実である場合にのみ行います。また、アライメントの合ったデータ移動命令ですべての配列参照をコンパイラーに実装すると、アライメントの合っていないアクセスパターンがある場合にランタイム例外が発生します。
nontemporal/temporal キーワードの使用
nontemporal と temporal 引数キーワードは、IA-32 およびインテル® 64 アーキテクチャー・ベースのシステムで、レジスター内容のストア方法 (ストリーミングか非ストリーミング) を制御します。
デフォルトでは、コンパイラーはそれぞれの変数にストリーミング・ストアを使用するかどうかを自動で決定します。
ストリーミング・ストアは、特定のプロセッサーにおいて非ストリーミング・ストアよりも、大幅なパフォーマンスの向上をもたらす可能性があります。ただし、ストリーミング・ストアの使用を誤ると、パフォーマンスが大幅に低下します。
例 1: vector 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;
}
例 2: vector always プラグマの使用
次の例は、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];
}
例 3a: vector nontemporal プラグマの使用
生成されたアセンブリーとのループ (float 型) の例は、次のとおりです。N が大きくなると、インテル® Pentium® 4 プロセッサー・システムで非ストリーミング組み込み関数のパフォーマンスが大幅に向上します。
float a[1000];
void foo(int N){
int i;
#pragma vector nontemporal
for (i = 0; i < N; i++) {
a[i] = 1;
}
}
例 3b: ループ本体の ASM コードの使用
.B1.2:
movntps XMMWORD PTR _a[eax], xmm0
movntps XMMWORD PTR _a[eax+16], xmm0
add eax, 32
cmp eax, 4096
jl .B1.2
例 4: vector nontemporal プラグマと変数の使用
次の例は、ストリーミング・ストアの実装に #pragma vector nontemporal を変数とともに使用する方法を示します。
double A[1000];
double B[1000];
void foo(int n){
int i;
#pragma vector nontemporal (A, B)
for (i=0; i<n; i++){
A[i] = 0;
B[i] = i;
}
}