CPU(具体的にはメモリコントローラー)は、メモリが変更されていないという事実を活用できます。
利点は、この事実により、コンパイラーがデータにアクセスするときにmembar命令を使用する必要がなくなることです。
メモリバリアは、membar、メモリフェンス、またはフェンス命令とも呼ばれ、バリア命令の一種であり、中央演算処理装置(CPU)またはコンパイラがバリア命令の前後に発行されるメモリ操作に順序付け制約を適用します。これは通常、特定の操作がバリアの前に実行され、他の操作がその後に実行されることが保証されることを意味します。
最新のCPUのほとんどはパフォーマンスの最適化を採用しているため、メモリのバリアが必要になります。このメモリ操作(ロードとストア)の並べ替えは、通常、単一の実行スレッド内では気付かれませんが、慎重に制御されない限り、並行プログラムおよびデバイスドライバーで予期しない動作を引き起こす可能性があります...
マルチコアCPUで異なるスレッドからデータにアクセスすると、次のようになります:異なるスレッドが異なるコアで実行され、それぞれ独自の(コアに対してローカルな)キャッシュ-グローバルキャッシュのコピーを使用します。
データが可変であり、プログラマーが異なるスレッド間で一貫性を保つ必要がある場合、一貫性を保証するための対策を講じる必要があります。プログラマーにとって、これは特定のスレッドのデータにアクセス(読み取りなど)するときに同期構造を使用することを意味します。
コンパイラの場合、コード内の同期コンストラクトは、他のコアでのキャッシュを保証するために、コアの1つでデータのコピーに加えられた変更が適切に伝播(「公開」)されるように、membar命令を挿入する必要があることを意味します同じ(最新の)コピーがあります。
多少単純化するため、下記のメモを参照してください。membarのマルチコアプロセッサで起こることは次のとおりです。
- すべてのコアは処理を停止します -キャッシュへの誤った書き込みを避けるため。
- ローカルキャッシュに加えられたすべての更新は、グローバルキャッシュに書き戻されます-グローバルキャッシュに最新のデータが含まれるようにします。これには時間がかかります。
- 更新されたデータは、グローバルキャッシュからローカルキャッシュに書き戻されます-ローカルキャッシュに最新のデータが含まれるようにします。これには時間がかかります。
- すべてのコアが実行を再開します。
ご覧のとおり、グローバルキャッシュとローカルキャッシュの間でデータがコピーされている間、すべてのコアは何もしていません。これは、可変データが適切に同期されるようにするために必要です(スレッドセーフ)。4つのコアがある場合、4つすべてが停止し、キャッシュの同期中に待機します。8個ある場合、8個すべてが停止します。16がある場合...これらのいずれかで必要な処理を待機している間、15のコアがまったく何も実行していないことになります。
それでは、データが不変の場合に何が起こるか見てみましょう。どのスレッドがそれにアクセスしても、同じであることが保証されます。プログラマーにとって、これは、特定のスレッドのデータにアクセス(読み取り)するときに同期構造を挿入する必要がないことを意味します。
コンパイラの場合、これはmembar命令を挿入する必要がないことを意味します。
その結果、データへのアクセスは、グローバルキャッシュとローカルキャッシュ間でデータが書き込まれている間、コアを停止して待機する必要がありません。これは、メモリが変化しないという事実の利点です。
上記の説明をいくぶん単純化すると、パイプラインなど、データが可変であるというより複雑な悪影響がなくなることに注意してください。必要な順序を保証するために、CPUはデータ変更の影響を受けるパイルラインを無効にする必要があります。これはパフォーマンスの低下につながります。これがすべてのパイプラインの単純な(したがって信頼できる:)無効化によって実装される場合、マイナスの影響はさらに増幅されます。