読者です 読者をやめる 読者になる 読者になる

メモリバリアを理解するために必要な3つのこと

Togetter - 「メモリバリアとガチャピン先生」
上の話において、「メモリバリア」の意味するところをもう少し明確にすべきかなあと思ったので、簡単にまとめてみます。
「メモリバリア」が満たすべき性質は、以下の3つに分類することができます。

  1. atomicity
  2. release/acquire fence
  3. sequential consistency

これらの性質は、C++0xのmemory_orderと以下のように対応しています。

C++0x memory_order 持っている性質
memory_order_relaxed atomicity
memory_order_acquire, memory_order_release, memory_order_acq_rel atomicity + release/acquire fence
memory_order_seq_cst atomicity + release/acquire fence + sequential consistency

atomicity とは文字通り「不可分な」操作を保証するものですが、その影響は操作対象のオブジェクトに限定されます。つまり、あるatomic変数に対する memory_order_relaxed でのアクセスは、他の変数に対するアクセスの順序付けには何も影響しません。
一方 release/acquire fence では、release操作とacquire操作の対によってアクセスの順序付けを行ないます。この順序付けの効果は、releaseより前とacquireより後にある全ての変数に対して影響します。
そして、この release/acquire fence を用いても実装できない、「複数のatomic変数に対する書き込みの見た目の順序に依存するようなアルゴリズム」を実装するために必要なのが sequential consistency になります。
これら3つの性質について、x86アーキテクチャでの実現方法は以下のようになります。

単純なread, write read-modify-write
atomicity 対象の変数が正しくalignされていればよい lock-prefix付き命令を用いる
release/acquire fence 自動的に保証される 自動的に保証される
sequential consistency writeを XCHG または MOV+MFENCE にする lock-prefix付き命令を用いる

このように、CMPXCHGやXADDなどのread-modify-write命令では atomicity の実現のためだけでも lock-prefix が必要となりますが、その結果 sequential consistency までもオマケに付いてくることになるわけです。