x86 ではどちらの書き込みバリアが優れていますか。lock+addl または xchgl?

StackOverflow https://stackoverflow.com/questions/4232660

  •  26-09-2019
  •  | 
  •  

質問

Linux カーネルが使用するのは、 lock; addl $0,0(%%esp) RE2 ライブラリは書き込みバリアとして使用します。 xchgl (%0),%0 書き込みバリアとして。何が違いますか? どちらが優れていますか?

x86 にも読み取りバリア命令が必要ですか?RE2 は読み取りバリア機能を x86 上で no-op として定義しますが、Linux はそれを次のいずれかとして定義します。 lfence SSE2 が利用可能かどうかに応じて、何も操作しません。時である lfence 必須?

役に立ちましたか?

解決

の"ロック;addl$0,0(%%esp)"より速やかにその試験を0の状態をロック変数(%%esp)アドレスです。でを追加しました0値のロック変数でのゼロフラグが設定された場合は1設定値のロックの変数のアドレス(%%esp)は0になります。


lfence インテルのデータシート:

に処理し、直列化す操作 全負荷からメモリの指示が 発行前のLFENCE ました。この直列化さ 動作保証する負荷 指導する前にプログラム のLFENCE指導を 世界に見える前に負荷 指導のLFENCE 指導は世界的に見えています。

(編集部注: mfence または locked操作がする可能性があるフェンス(店舗)の連続整合性. lfenceない ブロックStoreLoad並べ替えする店舗のバッファをいう。)


たとえば、次のようになります。メモリの書きの指導のが"mov"とは原子間にする必要がないのロックの接頭辞である場合には適切なっております。この命令は正常に実行されCPUキャッシュされません世界に見えるこの時のその他のすべてのスレッド、メモリのフェンス実施することが必要である最初にこのスレッドで以前の店舗はほかのスレッド)。


その主な違いはこれらの指示が xchgl 指導しておりませんの条件フラグがあります。確からして試験、ロック状態変数 ロックcmpxchg 指導もしていただくことが可能です。複合体によ ロックを追加$0 ました。

他のヒント

引用のIA32マニュアル(第3A,第8.2:メモリの順序):

単一のプロセッサシステムのためのメモリ領域として定義の書き戻しcacheableの記憶-発注モデルを尊重し、以下の原則[..]

  • を読み込みのない注文の読み込み
  • 書き込みのない注文は旧を読み込み
  • 書き込みメモリは注文の書き込み以外の
    • 書き込み実行される CLFLUSH 指導
    • ストリーミング店舗(書き込みます)を実行との間の移動説([リストの指示はこちら】)
    • 文字列操作部8.2.4.1)
  • を読み込み可注文以前に書き込み異なる箇所がない以前に書き込みにしましょう。
  • を読み込みや書き込みできない注文のI/O指示、命令、または直列化さの指示
  • を読み込みできない LFENCEMFENCE 指示
  • 書き込みできない SFENCEMFENCE 指示

注意:の"シングルプロセッサシステム"は若干誤解を招きます。同じルールを予定して各(論理的な)プロセッサは個別にマニュアルを記述を追加順規則よりも複数のプロセッサです。のバックグラウンドについに関する質問が

  • ロックの指示計です。

短期、長い文書を書くバックメモリはすべてのメモリまえなが見ていないドライバーまたはグラフィックプログラマー)は、x86指導はほとんどを順次整を並べ替えるx86CPUで行うことが再注文後(独立)を読み込みを実行する前に書き込みます.主なものを書くの障壁がいっそうの lock プレフィックス(明示または黙示、禁止すべての順序を変更していることを保証し、業務を見るのと同じ順序による全てのプロセッサのマルチプロセッサシステム。

また、書バックメモリを読み込み、あるい注文いための必要はありませんread障壁に対処するであろう。最近のx86プロセッサには弱いメモリの整合性モデルのためのストリーミング店および書き込みメモリ使用のためにマップされたグラフィックいたしました。このような場合は、様々な fence 指示しそれを実現するためには、;いに必要なその他のメモリータイプ、ドライバのLinuxカーネルな対応書き込みのメモリとかの定義を読み取りバリアすることができてうれしいです。リストの順序のモデル毎にメモリータイプの第11.3.1Vol.3AのIA-32ドキュメントへの対応等です。ショートバージョン:書き込み、書き戻しと新しいパスワードを入力保護される投機に読み込み(以下のルールとして、Uncachable強Uncacheableメモリの高い秩序を保証(プロセッサの並べ替えを読み込み/書き込みますが、直ちに実行され、MMIO)と書き込み合わせのメモリが弱い順序付け(ゆったりご注文の規則を必要とする柵).

lock addl $0, (%esp) が代替 mfence, ない lfence.

の利用の場合は要な時に必要なブロックStoreLoad並べ替え(みうるx86の強い記憶モデルでも必要な原子RMW操作共有の可変となります。 https://preshing.com/20120515/memory-reordering-caught-in-the-act/

例えば仮に揃えて std::atomic<int> a,b:

movl   $1, a             a = 1;    Atomic for aligned a
# barrier needed here
movl   b, %eax           tmp = b;  Atomic for aligned b

選択肢は、次の通りです:

  • いシークエンシャル-ペイ方式の一貫店 xchg, など mov $1, %eax / xchg %eax, a 必要ありませんが別の壁;っていうのはそういうもの。これは、最も効率的なオプションで最も近代的なハードウェアC++11コンパイラでコンパイル以外のgccの使用 xchg のためのseq_cstます。
  • 使用 mfence しています。(gccが使用 mov + mfence のためのseq_cstます。
  • 使用 lock addl $0, (%esp) しています。他の lockedは完全バリアになります。 はロックxchg同じ行動をしていてmfence?

    (またはその他の場所のスタックはほとんどの民間および熱L1dのまちとして全国的に有名で、多少いいます。しかしこの場を作る依存関係のチェーンのために何かデータを用いて下部のスタックです。)

のみ使用することができ xchg バリア層とした折りたたみでお店で無条件に書き込みのメモリ位置に合わせることができ値に依存しない、古い値とする。

可能な場合には、 xchg ために配列番号-cst店が最も良いものを読み込みを共有します。 mfence される速度が遅くなり、予想以上、最近のインテルのCpu(いて負荷店舗のみ指示を取得する注文?も阻止のための実行の独立した非メモリの指示と同様 lfence います。

することにもなるのを利用 lock addl $0, (%esp)/(%rsp) の代わりに mfence 場合でも mfence あげたいと思いました実験も行のマイナス面.を使用 -64(%rsp) もう少が長期化データへの依存度も温泉(または申立ができるリーディングプロジェクトvalgrind不幸.


lfence いに役立つメモリの順序付けませんからの読み出しデュアルコアプロセッサ(またはその他のWC弱秩序領域)MOVNTDQA。

直列化さのための実行がない店舗のバッファーな有用停止StoreLoad並べ替え(みうるx86の強い記憶モデルでは通常のWB(書-)メモリを身につけてください

の実世界での活用例 lfence はブロックのための実行 rdtsc タイミング短ブロックのコードは、亡霊の緩和によるブロックを巡る思惑を通じて条件付きまたは間接的ます。

参照 されることがあります。_mm_sfence_mm_lfenceと_mm_mfence 私の答えは、@BeeOnRopeの回答)についての理由 lfence では、どのような場合にそれぞれのバリアです。(鉱、C++intrinsicsがプログラミングC++の代わりにasm).

他の回答とは別に、HotSpot 開発者は次のことを発見しました。 lock; addl $0,0(%%esp) オフセットをゼロにすることは最適ではない可能性があります。一部のプロセッサでは最適な場合があります。 誤ったデータ依存関係を導入する;関連している JDKのバグ.

異なるオフセットのスタック位置をタッチすると、状況によってはパフォーマンスが向上する場合があります。

lock; addlxchglの重要な部分は、lock接頭辞です。それはxchglのための暗黙のです。両者の間に違いは本当にありません。私は、彼らが組み立て方法を見て、それが(それゆえトリックxorl eax,eaxのような)のx86上で同等の操作のために、通常は高速ですので、(バイト単位)短いだものを選ぶと思います。

SSE2の存在は、おそらく最終的にcpuidの関数であり、実際の条件のためだけのプロキシです。これはおそらく、SSE2がlfenceの存在を暗示していることが判明し、SSE2の可用性は、ブート時にキャッシュされた/確認しました。それが利用可能なときlfenceが必要となります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top