OpenMP アプリケーションで不注意に共有メモリー構造体を使用すると、パフォーマンスおよびスケーラビリティーが低下することがあります。メモリー上の連続する共有データを複数のプロセッサが更新すると、マルチプロセッサインターコネクタに過度のトラフィックが生じ、結果的に計算の直列化の原因になることがあります。
ほとんどのメモリー共有型マルチプロセッサコンピュータには、各プロセッサに独自のローカルキャッシュがあります。このキャッシュは、低速のメモリーとプロセッサの高速レジスタの間のバッファーとして動作します。メモリー上の場所にアクセスすると、その要求された場所を含む実際のメモリーのスライス (キャッシュライン) がキャッシュにコピーされます。同じメモリー上の場所またはその周囲の場所への以降の参照は、キャッシュとメモリー間の整合性を維持する必要があるとシステムが判断するまで、キャッシュから行われます。
偽りの共有は、異なるプロセッサのスレッドが同じキャッシュ行にある変数を変更すると発生します。この状況は (真の共有と区別するために) 偽りの共有と呼ばれます。スレッドが同じ変数にアクセスせずに、同じキャッシュ行に偶然あった別の変数にアクセスしているためです。
スレッドがキャッシュ内の変数を変更すると、その変数があるキャッシュ行全体が無効としてマークされます。別のスレッドが同じキャッシュ行の変数にアクセスしようとすると、変更されたキャッシュ行がメモリーに書き戻され、スレッドはメモリーからキャッシュ行を取得します。これが発生するのは、キャッシュ整合性をキャッシュ行のレベルで維持するためであり、個別の変数または要素のためではありません。偽りの共有では、アクセスしようとしている変数が変更されていなくても、スレッドは強制的にキャッシュ行のより新しいコピーをメモリーから取得します。
偽りの共有が頻繁に発生すると、インターコネクトトラフィックが増加し、OpenMP アプリケーションのパフォーマンスとスケーラビリティーが大幅に低下します。偽りの共有によってパフォーマンスが低下するのは、次の条件のすべてが満たされる場合です。
複数のスレッドによって共有データが変更される
複数のスレッドが同じキャッシュ行内のデータを変更する
データが頻繁に変更される (密なループなど)
読み取り専用の共有データにアクセスしても偽りの共有にはならないことに注意してください。
通常、偽りの共有が検出されるのは、特定の変数へのアクセスに著しくコストがかかっていると思われる場合です。アプリケーションの実行で主要な役割を果たす並列ループを綿密に分析することによって、偽りの共有によって引き起こされるパフォーマンスおよびスケーラビリティー上の問題を明らかにすることができます。
一般に、偽りの共有は次の手法を使用して減らすことができます。
できるだけ多くの private または threadprivate のデータを使用する。
コンパイラの最適化機能を使用して、メモリーのロードおよびストア命令を取り除く。
各スレッドのデータが別個のキャッシュ行に配置されるようにデータ構造をパディングする。パディングのサイズはシステムによって異なり、個々のキャッシュ行にスレッドのデータをプッシュするために必要なサイズです。
スレッド間のデータの共有が少なくなるようにデータ構造を変更する。
偽りの共有を追跡するための技法は、アプリケーションによって大きく異なります。データの割り当て方法を変更すると、偽りの共有が減少する場合があります。スレッドの反復のマッピングを変更し、チャンクごとの各スレッドの作業量を増やす (chunk_size の値を変更する) ことで偽りの共有が減少することもあります。