さまざまなレベルのロード・レイテンシーと一時的な局所性の制御方法を提供します。
#pragma memref_control [name1[:<locality>[:<latency>]],[name2...] |
name1、name2 |
配列またはポインターの名前。少なくとも 1 つの name を指定する必要がありますが、関連付けられた locality および latency の値を指定することができます。 |
locality |
将来のアクセス用にデータを格納するキャッシュレベルを示す整数値 (オプション)。これにより、この参照で使用されるロード/ストアのヒント (またはプリフェッチのヒント) が決定します。次のいずれかの値を使用できます。
この引数を使用するには、name も指定してください。 |
latency |
ロードを示す整数値 (またはこのアドレスに対してプリフェッチが発行された場合にオーバーラップしなければいけないレイテンシー) (オプション)。次のいずれかの値を使用できます。
この引数を使用するには、name と locality も指定しなければなりません。 |
memref_control プラグマは、インテル® Itanium® プロセッサーでのみサポートされています。このプラグマは、ロード・レイテンシーの制御方法とさまざまなレベルの一時的な空間の制御方法を提供します。memref_control プラグマは、配列レベルで局所性およびレイテンシーを指定できるようにします。例えば、プラグマを使用することで次の制御が可能になります。
将来のアクセス用にデータを格納する場所 (キャッシュレベル)。
ロードに使用されるのに最適なレイテンシー値、またはこの参照のプリフェッチが発行された場合にオーバーラップされなければならないレイテンシー。
特定のデータアクセスに対して、高いレベルでソースレベルのデータの局所性情報を指定した場合、この情報の使用方法はコンパイラーが決定します。コンパイラーは、参照に有利にプリフェッチした場合、指定されたレイテンシーをカバーする距離のプリフェッチを発行し、対応するロードを指定されたレイテンシーよりも小さなレイテンシーでスケジュールします。また、プリフェッチのヒントを使用して、指定されたキャッシュレベルにデータが保たれるよう適切にロードします。
コンパイラーは、事前にアドレスを計算できない場合、またはプリフェッチのオーバーヘッドが大きすぎると判断した場合、指定されたレイテンシーを使用して (パイプライン化されたループまたはグローバル・コード・スケジューラーによるループで) ロードとその使用を分離します。ロード/ストアのヒントは、locality 引数とともに渡されたキャッシュレベルに対応します。
これを prefetch および noprefetch とともに使用して、ヒントとプリフェッチ手法をチューニングすることが可能です。memref_control を noprefetch とともに使用する場合は、次のガイドラインに従ってください。
noprefetch を memref_control とともに指定すると、コンパイラーはプリフェッチを発行しません。代わりに、memref_control で指定されたレイテンシーの値を使用してロードがスケジュールされます。
2 つのプラグマを一緒に使用する際、決められた順序はありません。プラグマを適用するループの直前に、連続して (どちらが先でも良い) 指定します。1 つのヒントとともにプリフェッチを発行し、後で別のヒントを使用してロードすると、特定のアーキテクチャーに使用されるヒントをより良く制御できます。
memref_control は、prefetch または noprefetch とは処理が異なります。ロードがプリフェッチされない場合でも、非デフォルトのロード・レイテンシーを latency 引数に渡すことによって参照をロードすることができます。
例 1: プリフェッチできない場合の #pragma memref_control の使用
次の例は、事前にアドレスが不明でプリフェッチできないケースを示します。この例では、コンパイラーは (ソフトウェアのパイプライン化が行われたループ、またはグローバル・コード・スケジューラーによるループにおける) L3 ロード・レイテンシーが 15 サイクルのタブ配列のロードをスケジュールします。
#pragma memref_control tab : l2 : l3_latency
for (i=0; i<n; i++)
{
x = <generate 64 random bits inline>;
dum += tab[x&mask]; x>>=6;
dum += tab[x&mask]; x>>=6;
dum += tab[x&mask]; x>>=6;
}
例 2: #pragma memref_control と prefetch プラグマおよび noprefetch プラグマ [sparse matrix] の使用
次の例では、memref_control、prefetch、および noprefetch を一緒に使用する 1 つの方法を示します。
if( size <= 1000 ) {
v#pragma noprefetch cp, vp
#pragma memref_control x:l2:l3_latency
#pragma noprefetch yp, bp, rp
#pragma noprefetch xp
for (iii=0; iii<rag1m0; iii++) {
if( ip < rag2 ) {
sum -= vp[ip]*x[cp[ip]];
ip++;
} else {
xp[i] = sum*yp[i];
i++;
sum = bp[i];
rag2 = rp[i+1];
}
}
xp[i] = sum*yp[i];
} else {
#pragma prefetch cp, vp
#pragma memref_control x:l2:mem_latency
#pragma prefetch yp, bp, rp
#pragma noprefetch xp
for (iii=0; iii<rag1m0; iii++) {
if( ip < rag2 ) {
sum -= vp[ip]*x[cp[ip]];
ip++;
} else {
xp[i] = sum*yp[i];
i++;
sum = bp[i];
rag2 = rp[i+1];
}
}
xp[i] = sum*yp[i];
}