キャッシュ領域が最強だった

以前、こんなことを紹介した。

予約してメモリを書き換える

Load-Link/Store-Conditional(LL/SC)方式というのがあって、

メモリ上のあるアドレスを予約して、他のコアが触っていないことを確認してからライトする。

このような形で排他制御を実現しようとしているのだが、この方式には制約があり、

この方式は予約したアドレスへの他のコアのアクセス有無がわかればよいが、

この仕組みが働く領域と働かない領域があるようで、

その都合でcmpxchg関数でプログラムが停止する問題が起きていた。

というわけでどの領域でも使えるわけではなかったという話。


で、いろいろ資料を見ていて判明したのは、この仕組みはキャッシュが働く領域だけ働くということだった。

これはCPUによっても違うんだろうけど、典型的にはそうらしい。

一見するとキャッシュがある方が排他制御はやりにくそうなのだが、

キャッシュを使う場合、キャッシュコヒーレンシが求められる。

複数のコアで各々キャッシュを持っていて、あるコアがキャッシュ上のデータを更新したとき、

他のコアはその領域のキャッシュデータを無効化したり更新しなければならない。

元々そういう仕組みを持っているキャッシュ領域ではLL/SCはやりやすいと。


LL/SCはあるアドレスを予約してから、そのアドレスを他のコアが触っていないことを把握できればよいので、

キャッシュコヒーレンシの仕組みに頼らずに実現する方法もありそうだが、

もっとも典型的なのはキャッシュコヒーレンシの仕組みに乗っかる方法らしい。


同じような排他制御が求められる処理にアトミック操作というのがあって、

例えばメモリスワップを1命令で排他的に行う仕組みを持っている場合がある。

メモリのデータをリードしてr0に格納して、r1の値に書き換える

というのを排他的に一息でやってしまうような命令である。


こういう命令はシングルコアでも価値があって、

なぜかというとリード・ライトを2命令でやると、その間に割り込まれる可能性があるから。

(これを防ぐためにはこの間を割り込み禁止にする必要がある)

ところが、1命令でやればその間に割り込まれることはなくなる。

なのでシングルコアの時代からこういう命令は活用されてきたらしい。

ここにマルチコアの時代が来て「排他的に」実現することが必要になったと。


これもキャッシュコヒーレンシが働く領域だと対応しやすいようだ。

キャッシュ上でスワップして、他のコアのキャッシュを無効化・更新すればよいから。

これも他の実現方法はありそうだが、典型的にはこうやるらしい。


というわけでキャッシュ領域が最強なわけですね。

キャッシュを介することで実メモリとの整合は取りにくくなるが、

コア間の整合はもともと意識されているので排他制御はやりやすいと。

そういう意味だったのかといまさら理解した。