過去の日記では、キャッシュスヌープ方式のキャッシュコヒーレンシ制御の方法をざっくりと見たが、今度はもう一つのディレクトリベースのキャッシュコヒーレンシ制御についてみていく。
キャッシュスヌープ方式の記事はこちら。
キャッシュスヌープ方式はこれはこれでよくできた方式だが、コア数が増えると破綻するという問題である。 つまり、コア数が増えていくと至る所で他コアのキャッシュの状態を確認するコヒーレンス要求信号が飛び交い、肝心なキャッシュ制御の性能が落ちてしまう。
なぜこんなことが起きてしまったんだろう?それは、スヌープ方式が「このキャッシュの最新版持っているのはだーれ?」という情報をブロードキャストしないと、最新の情報が手に入らないことに起因する。
では、「このデータならばxxxが最新の状態を管理しているはずだからxxxに聞いてみよう」という風に、最初からデータの最新情報を持っている人が分かっているようにすればどうか?
最新のデータをメモリから取得したければ、そのデータを管理しているノードに問い合わせを行い、管理ノードは誰が最新のデータを持っているのか知っているのでそのノードに通知、最新のデータを持っているノードはそのそのデータを問い合わせ元のノードに転送、とすれば、スヌープキャッシュのようにすべてのコアに問い合わせの信号を送信する必要がなくなる。
という訳で、(例えばアドレスに応じて)各領域でデータの状態を管理するノードを分散し、各ノードには管理しているデータの管理台帳(これをディレクトリと呼ぶ)を置いておく方式を「ディレクトリベースのキャッシュコヒーレンス制御」と呼んでいる。
例えば、あるデータについて、
- そのデータを管理しているのはプロセッサ1
- 最新のデータを持っているのはプロセッサ0 (このことはプロセッサ1のディレクトリに記録してある:貸し出し済み)
の状態であるとき、プロセッサ5がその最新のデータを取得したいとする。この場合どのような手順を取るのか。
- バスの構成上プロセッサ1に直接問い合わせできない場合(この図はリングバスだが、例えばダイレクト接続で隣接しているノードにしか問い合わせができないとする)、プロセッサ5は隣のプロセッサ2に問い合わせを投げ、プロセッサ2はプロセッサ1に問い合わせを転送する。
- 問い合わせを受けたプロセッサ1は、ディレクトリを見て最新のデータがプロセッサ0のキャッシュに入っていることを確認する。そこで、プロセッサ0に問い合わせを行い、プロセッサ5に対して当該キャッシュラインを転送するように要求する。
- プロセッサ0は要求を受け、プロセッサ5にキャッシュラインを転送する。これにより、プロセッサ0とプロセッサ5がキャッシュラインを持っている状態になり、プロセッサ1は自分のディレクトリに当該キャッシュが共有状態であることを記録しておく。
という訳で、非常に簡単な例であるが、ディレクトリベースのキャッシュコヒーレンス制御の方式について考え方をまとめた。 この後、キャッシュがアップデートされた場合のディレクトリのアップデートなど細かい部分はあるが、ここでは基本的な考え方が分かればよいものとしておく。
その基本的な考え方は、スヌープキャッシュの方式の場合にキャッシュの状態を確認するためのブロードキャストのコストを減らし、各ノードが別々にディレクトリという管理台帳を使い、自分の管理下のデータの状態を一括して管理しているというものである。