キャッシュ汚染

キャッシュ汚染とは、実行中のコンピュータプログラムがCPUキャッシュに不必要なデータをロードし、[ 1 ] 、他の有用なデータがキャッシュからメモリ階層の下位レベルに追い出され、パフォーマンスが低下する状況を指します。例えば、マルチコアプロセッサでは、あるコアが他のコアによってフェッチされたブロックを共有キャッシュに置き換えたり、プリフェッチされたブロックがキャッシュからデマンドフェッチされたブロックを置き換えたりすることがあります。

次の図を考えてみましょう。

T[0] = T[0] + 1; i が 0 の場合... sizeof (CACHE) C[i] = C[i] + 1; T[0] = T[0] + C[(CACHE)のサイズ-1]; 

(ここでの前提は、キャッシュが 1 つのレベルのみで構成され、ロック解除されており、置換ポリシーが疑似 LRUであり、すべてのデータがキャッシュ可能であり、キャッシュのセット連想性が N (ただし N > 1) であり、プログラム値を格納するために最大 1 つのプロセッサ レジスタが使用可能であるということです)。

ループ開始直前に、T[0]はメモリからキャッシュにフェッチされ、その値が更新されます。しかし、ループの実行に伴い、ループが参照するデータ要素の数に応じてキャッシュ全体がその容量まで満たされる必要があるため、T[0]を含むキャッシュブロックを強制的に削除する必要があります。そのため、プログラムが次にT[0]の更新を要求した際にキャッシュミスが発生し、キャッシュコントローラは対応するキャッシュブロックをメインメモリから再度取得するためにデータバスを要求しなければなりません。

この場合、キャッシュは「汚染されている」と言えます。T[0]の最初の更新をループと2番目の更新の間に配置することで、データアクセスのパターンを変更することで、この非効率性を排除できます。

i が 0 の場合... sizeof (CACHE) C[i] = C[i] + 1; T[0] = T[0] + 1; T[0] = T[0] + C[(CACHE)のサイズ-1]; 

ソリューション

前述のコード再構築以外に、キャッシュ汚染の解決策としては、再利用性の高いデータのみがキャッシュに格納されるようにすることが挙げられます。これは、特別なキャッシュ制御命令オペレーティングシステムのサポート、またはハードウェアのサポートを利用することで実現できます。

特殊なハードウェア命令の例としては、 PowerPC AltiVecが提供する「lvxl」が挙げられます。この命令は、128ビット幅の値をレジスタにロードし、対応するキャッシュブロックを「最も使用頻度の低い」ブロック、つまりキャッシュセットからブロックを退避させる必要がある際に退避すべき最有力候補としてマークします。上記の例のコンテキストでこの命令を適切に使用するには、ループで参照されるデータ要素をこの命令を使用してロードする必要があります。このように実装すると、ループの実行によってT[0]がキャッシュから早期に退避されることがないため、キャッシュ汚染は発生しません。ループが進行するにつれて、C内の要素のアドレスが同じキャッシュウェイにマッピングされ、実際には古い(ただし「最も使用頻度の低い」としてマークされていない)データは他のウェイにそのまま残るため、この問題は回避されます。キャッシュから退避されるのは最も古いデータ(この例には関係ありません)のみです。T[0]はループ開始直前に更新されるため、キャッシュのメンバーではありません。

同様に、オペレーティングシステム(OS)のサポートを利用することで、Cデータ配列に対応するメインメモリ内のページを「キャッシュ禁止」、つまりキャッシュ不可としてマークすることができます。同様に、ハードウェアレベルでは、プログラムのアクセスパターンに基づいて再利用性の低いデータを識別し、キャッシュからバイパスするキャッシュバイパス方式を使用できます。また、共有キャッシュを分割することで、実行中のアプリケーション間の破壊的な干渉を回避することもできます。これらのソリューションのトレードオフは、OSベースの方式ではレイテンシが大きくなり、キャッシュ汚染回避によって得られるメリットが打ち消される可能性があることです(メモリ領域が最初からキャッシュ不可でない限り)。一方、ハードウェアベースの手法では、プログラムの制御フローとメモリアクセスパターンを全体的に把握できない可能性があります。

重要性の高まり

いわゆる「メモリウォール」によるペナルティが拡大し続けているため、キャッシュ汚染制御の重要性は高まっています。チップメーカーは、メモリとCPUの相対的なレイテンシの増大を克服するための新たな技術を次々と考案しています。キャッシュサイズを拡大し、ソフトウェアエンジニアがCPUへのデータの到達と滞留を制御するための便利な方法を提供することで、これを実現しています。キャッシュ汚染制御は、(主に組み込み系の)プログラマが利用できる数多くの手段の一つです。しかし、その他にも、ほとんどが独自のものであり、ハードウェアやアプリケーションに大きく依存する手法も用いられています。

参考文献