プロセッサ構成はますますマルチコア化しており、同期処理や各プロセッサでの通信、データ共有をどのように行うかという問題は重要になっている。
ハードウェア・ソフトウェアには「メモリモデル」というものが定義されており、共有する変数をどのようにして取り扱うか、レーシングの状態をどのように取り扱うかというものが定義されているが、少し気になって復習がてら「ハードウェアのメモリコンシステンシとは何なのか」について調査を行ったのでメモする。
参考文献
- 作者:John L. Hennessy,David A. Patterson
- 出版社/メーカー: Morgan Kaufmann
- 発売日: 2017/12/07
- メディア: ペーパーバック
メモリコンシステンシモデルが必要な状況
例えば、以下のような状況を考えたとき、2つのプロセッサはどのような動作をするだろうか。
キャッシュの存在しない状態で、メモリの書き込みとメモリの読み込みがプログラムの順番通りに行われる場合、最後のB==0は不成立で、A==0も不成立となるだろう。
しかし、キャッシュが存在しておりキャッシュの中身をWriteInvalidateするようなケースでは時間軸が互いにずれてしまい、上記のように互いに必ず不成立になるという状態はありえなくなる。
また、プロセッサの高速化によりMEM[B]
の読み込み動作がMEM[A]
の書き込み動作を追い越すような場合、上記の前提は成立しなくなる。
厳密にメモリアクセスの順序を守ればいいのではないか?
基本的にはその通り。この、すべてのメモリアクセスの順番を守るメモリモデルのことを「シーケンシャルコンシステンシ」と呼ぶ。
しかしこのシーケンシャルコンシステンシに基づいているアーキテクチャでは、厳密にメモリアクセスの順番を守るために非常に性能が落ちるという問題がある。
そこで、ある程度であればメモリアクセスの順番を入れ替えてもよい、というのが、シーケンシャルコンシステンシ以外のメモリコンシステンシモデルである。
誰がメモリコンシステンシを守るのか
プロセッサの種類(プロセッサーアーキテクチャ)によって守るべきメモリコンシステンシモデルは異なっている。 例えば、ARMやRISC-Vはほとんどメモリアクセスの順番を入れ替えてもよい仕様になっているが、SPARCは一定のメモリアクセスの順番を守らなければならない。
また、それぞれのアーキテクチャ向けのコンパイラは、個々のアーキテクチャのメモリモデルに応じてアセンブリを出力する必要がある。
制約を緩和したメモリコンシステンシモデル(リラックスコンシステンシモデル)
というわけで、シーケンシャルコンシステンシでは十分に性能を出すことができないため、もう少し制約を緩和してもいいんじゃないの?というメモリモデルが存在する。 それらについて紹介するとともに、代表的なプロセッサアーキテクチャを列挙していく。
ここでは、Write(W)→Read(R)という表現を使い、W→Rは、Wが実行された後にRが実行されなければならない、ということを意味する。
- Total Store Ordering(TSO)もしくはプロセッサコンシステンシ : シーケンシャルコンシステンシに対して、W→Rのオーダリングを許可する。つまり、アセンブリの順番的にストア命令の後にロード命令が配置されているものを、順番を入れ替えてロード命令を先に発行してもよいという意味である。
- Partial Store Ordering(PSO) : シーケンシャルコンシステンシに対して、W→R, W→Wのオーダリングを許可する。つまり、アセンブリの順番的に2つ並んだストア命令を、逆の順序にメモリアクセスを行ってもよい、という意味である (ヘネパタ第5版は誤解を生みやすい表現なので注意!第6版が正しい)
- Weak Ordering : シーケンシャルコンシステンシに対して、すべての操作に対してオーダリングを許可する。
- Release Consistency : 考え方はWeak Orderingと同一だが、同期操作に対してオーダリングの制約が異なる。
以下はヘネパタ第6版からの流用(一部改変)。メモリコンシステンシ毎の動作の違いについて。
こちらもヘネパタからの流用で、各プロセッサにおけるオーダリングの仕様について。
Model | Used in | Ordinary Ordering | Synchronization Orderings |
---|---|---|---|
Sequential Consistency | 殆どのプロセッサではオプション | R→R, R→W, W→R, W→W | S→W, S→R, R→S, W→S, S→S |
Total Store Ordering or Processor Oreding | IBMS/370, DEC VAX, SPARC | R→R, R→W, W→W | S→W, S→R, R→S, W→S, S→S |
Partial Store Ordering | SPARC | R→R, R→W | S→W, S→R, R→S, W→S, S→S |
Weak Ordering | PowerPC | S→W, S→R, R→S, W→S, S→S | |
Release Consistency | MIPS, RISC-V, Armv8, C, C++ | →W, →R, R→, W→ →, →, →, → |
難しいのはWeak OrderingとRelease Consistencyの違いなのだが、どうも同期操作に対してRelease Consistencyの方が順序が少しだけ緩い。
ここで、"S"というのは同期操作を意味し、より厳密にはtex:S_Rとtex:S_A に分類できる。 Weak Orderingでは、すべての同期操作に対して、R/WのどちらもSの前後で完全に実行を完了しなければならない。 しかし、Release Consistecyは
- Acquire(S)後のWrite/Readの順番は守るべき(→W, →R)、しかし、Release(S)後のWrite/Readは守らなくてもよい(つまり、Release前に次のRead/Writeを出してもよい→W, →R)。
- Read/Write後のRelease(S)の順番は守るべき(R→, W→)、しかし、Read/Write後のAcquire(S)の順番は守らなくてもよい(つまり、Read/Writeの前にAcquireを出してもよいR→, W→)。
という意味があり、Weak Orderingよりも少し制約が緩いものになっている。