6

C++0x のアトミック変数のドキュメントの 1 つで、メモリの順序を説明するときに、次のように言及されています。

リリース - 取得注文

厳密に順序付けされたシステム (x86、SPARC、IBM メインフレーム) では、リリースと取得の順序付けは自動的に行われます。この同期モードでは追加の CPU 命令は発行されません。特定のコンパイラの最適化のみが影響を受けます...

まず、x86 が厳密なメモリ順序に従っているというのは本当ですか? 常にこれを課すのは非常に非効率的です。すべての書き込みと読み取りにフェンスがあるということですか?

また、x86 システムで整列された int がある場合、アトミック変数は何らかの目的を果たしますか?

4

4 に答える 4

12

はい、確かに x86 には厳密なメモリ順序があります。Intel マニュアルの Volume 3A、Chapter 8.2 を参照してください。386 などの古い x86 プロセッサでは、真に厳密な順序付け (強い順序付けと呼ばれる) セマンティクスが提供されていましたが、最近の x86 プロセッサでは条件がわずかに緩和されている場合がいくつかありますが、心配する必要はありません。たとえば、Pentium および 486 では、書き込みがキャッシュ ヒットである (したがって、読み取りとは異なるアドレスへの) 場合、読み取りキャッシュ ミスがバッファーされた書き込みよりも先に進むことができます。

はい、非効率的です。このため、高性能ソフトウェアは、メモリーの順序付け要件が緩い他のアーキテクチャー向けにのみ作成されることがあります。

はい、アトミック変数は x86 でも目的を果たします。それらは、典型的な読み取り-変更-書き込み操作がアトミックに発生するように、コンパイラとの特別なセマンティクスを持っています。アトミック変数 ( std::atomic<T>C++11 の型の変数を意味します) を同時にインクリメントする 2 つのスレッドがある場合、値が 2 大きくなることは保証できます。がないstd::atomicと、x86 ではメモリへのストアがアトミックであっても、1 つのスレッドがインクリメントの実行中に現在の値をレジスタにキャッシュしたため、間違った値になる可能性があります。

于 2012-08-06T21:41:10.563 に答える
5

x86 では、すべてのストアにリリースがあり、すべてのロードにセマンティクスが取得されるのは事実です。

それは C++ の書き方には影響しませんし、影響すべきではありません: コンカレントで競合のないコードを書くには、std::atomicコンストラクションまたはロックのいずれかを使用する必要があります。

アーキテクチャの詳細が意味することは、x86 では、最大でも取得/解放の順序を要求する限り、ワード サイズのアトミック型の操作用に余分なコードがほとんどまたはまったく生成されないということです。(ただし、順次整合性ではmfence命令が発行されます。) ただし、 C++ アトミック型を使用する必要があり、正しく整形式のプログラムを作成するために単純に省略することはできません。アトミック変数の重要な機能の 1 つは、プログラムの正確性に不可欠なコンパイラのリオーダを防ぐことです。

(C++11 より前では、GCC の__sync_*一連の関数など、コンパイラが提供する拡張機能を使用して、コンパイラを正しく動作させる必要がありました。ネイキッド変数を本当に使用したい場合は、少なくともコンパイラを挿入する必要があります。自分自身を妨げます。)

于 2012-08-06T21:23:00.240 に答える
1

発生する可能性のあるさまざまな並べ替え操作の素晴らしい表があり、(たとえば) x86 はそれらのほとんどを実行しません。他のアーキテクチャ (悪名高い Alpha) はほとんど何でもできます。

メモリ モデルは標準で定義されているため、x86 などは本質的に準拠しています。

原子変数に関するあなたの質問には、少し異なる答えがあります。複数のスレッドが同じ変数を更新すると、更新が失われる可能性があるなど、変数への変更には競合状態が伴います。アトミック変数は、アトミック操作の正しい型になるように定義されているため、この競合状態が解消されます。したがって、それらの目的の 1 つは注文以外です。

于 2012-08-06T21:19:15.937 に答える