回答:
パフォーマンスを向上させるために、最近のCPUは、利用可能なシリコンを最大限に活用するために、命令を順不同で実行することがよくあります(メモリの読み取り/書き込みを含む)。ハードウェアが命令の整合性を強制するため、単一の実行スレッドでこれに気付くことはありません。ただし、揮発性メモリ(たとえば、メモリマップI / O)を使用する複数のスレッドまたは環境の場合、これは予測できない動作を引き起こす可能性があります。
メモリフェンス/バリアは、メモリの読み取り/書き込みが予期した順序で発生することを意味する命令のクラスです。たとえば、「フルフェンス」とは、フェンスの前のすべての読み取り/書き込みが、フェンスの後の前にコミットされることを意味します。
メモリフェンスはハードウェアの概念であることに注意してください。より高いレベルの言語では、ミューテックスとセマフォの処理に慣れています。これらは低レベルのメモリフェンスを使用して実装でき、メモリバリアを明示的に使用する必要はありません。メモリバリアを使用するには、ハードウェアアーキテクチャを注意深く検討する必要があり、アプリケーションコードよりもデバイスドライバーでよく見られます。
CPUの並べ替えは、コンパイラの最適化とは異なりますが、アーティファクトは似ている場合があります。望ましくない動作(Cでのvolatileキーワードの使用など)が発生する可能性がある場合は、コンパイラーが命令を再配列するのを停止するために、個別の対策を講じる必要があります。
別の質問への私の回答をコピーして、プロセッサがコードを最適化するために行ういくつかのトリックは何ですか?:
最も重要なのは、メモリアクセスの並べ替えです。
メモリフェンスやシリアル化命令がない場合、プロセッサはメモリアクセスを自由に並べ替えることができます。一部のプロセッサアーキテクチャでは、並べ替え可能な量に制限があります。Alphaは最も弱い(つまり、最も多くの順序を変更できる)ことで知られています。
LinuxカーネルソースのドキュメントのDocumentation / memory-barriers.txtで、このテーマの非常に優れた扱いを見つけることができます。
ほとんどの場合、コンパイラまたは標準ライブラリのロックプリミティブを使用するのが最善です。これらは十分にテストされており、必要なすべてのメモリバリアが設定されているはずであり、おそらくかなり最適化されています(ロックプリミティブの最適化はトリッキーです。エキスパートでさえ誤解することがあります)。
Alpha is known for being the weakest
、なぜweakest
ですか?それはより良いのではなく、それはより多くの再注文をするので、結果としてそれははるかに速い実行になりますか?(私はアルファユーザーではありませんが、very reordering
vs の効果について尋ねていますrestricted reordering
)。ロットの並べ替えの欠点は何ですか(未定義の動作のリスクを除きますが、最新のCPUのほとんどは適切な並べ替えを解決し、定義された並べ替えのみを実装している必要があります。
私の経験では、それは複数のスレッド間でメモリアクセスを同期するための命令(明示的または暗黙的)であるメモリバリアを指します。
この問題は、最新のアグレッシブコンパイラー(命令を並べ替える驚くほどの自由がありますが、通常はスレッドについて何も知りません)と最新のマルチコアCPUの組み合わせで発生します。
問題への良い導入は、「「ダブルチェックされたロックが壊れている」宣言」です。多くの人にとって、ドラゴンがいるというのは目覚めの呼びかけでした。
暗黙的なフルメモリバリアは、通常、そのコアをカバーするプラットフォームスレッド同期ルーチンに含まれています。ただし、ロックフリーのプログラミングとカスタムの軽量同期パターンの実装では、多くの場合、バリアのみ、または一方向のバリアのみが必要です。
メモリバリアは、membarまたはメモリフェンスとも呼ばれ、中央処理装置(CPU)がバリア命令の前後に発行されたメモリ操作に順序付け制約を強制する命令のクラスです。
CPUはパフォーマンスの最適化を採用しており、メモリのロードやストア操作など、順序どおりに実行されない場合があります。メモリ操作の並べ替えは、通常、実行の単一スレッド内では気付かれませんが、注意深く制御しない限り、並行プログラムとデバイスドライバーで予測できない動作を引き起こします。順序付け制約の正確な性質はハードウェアに依存し、アーキテクチャのメモリモデルによって定義されます。一部のアーキテクチャは、さまざまな順序の制約を適用するための複数のバリアを提供します。
メモリバリアは通常、複数のデバイスで共有されるメモリで動作する低レベルのマシンコードを実装するときに使用されます。このようなコードには、同期プリミティブ、マルチプロセッサシステムのロックフリーデータ構造、およびコンピューターハードウェアと通信するデバイスドライバーが含まれます。