インテル® C++ コンパイラー XE 13.1 ユーザー・リファレンス・ガイド

フォルス・シェアリング

キャッシュラインに分割された複数のレベルのキャッシュは、並列処理でメモリーに高速アクセスします。フォルス・シェアリングは、メモリー共有型の並列処理でよく起こる問題です。2 つ以上のコアが同じキャッシュラインのコピーを保持する場合に発生します。

1 つのコアがキャッシュラインの変数に書き込むと、その他のすべてのコアでそのキャッシュライン全体が無効になります。 別のコアがそのデータを使用 (読み取り/書き込み) していなくても、同じキャッシュラインにある別のデータ要素を使用している可能性があります。別のコアは、データにアクセスする前にキャッシュラインをリロードする必要があります。

キャッシュ・ハードウェアはデータの一貫性を保証しますが、フォルス・シェアリングが頻繁に発生する場合は、パフォーマンスが低下します。フォルス・シェアリングの問題は、ハードウェア・カウンターやその他のパフォーマンス・ツールを使用して、予期できない最終レベルのキャッシュミスが増加するかどうか見分けることで発見できます。

簡単な例として、配列要素の値をインクリメントする for ループを含む関数がスポーンされる状況について考えてみましょう。 この配列は volatile であるため、コンパイラーはレジスターに値を保持したり、ループを最適化する代わりに、ストア命令を生成します。

volatile int x[32];

void f(volatile int *p)
{
   for (int i = 0; i < 100000000; i++)
   {
     ++p[0];
     ++p[16];
   }
}

int main()
{
   cilk_spawn f(&x[0]);
   cilk_spawn f(&x[1]);
   cilk_spawn f(&x[2]);
   cilk_spawn f(&x[3]);
   cilk_sync;
   return 0;
 }

x[] の要素は 4 バイトです。64 バイトのキャッシュラインでは、16 個の要素を保持できます。 データ競合はなく、ループ完了時の結果は正しいものです。ただし、個々のストランドが隣接する配列要素を更新するためキャッシュライン競合が発生し、場合によってはパフォーマンスが大幅に低下します。


このヘルプトピックについてのフィードバックを送信