本連載はHisa Ando氏による連載「コンピュータアーキテクチャ」の初掲載(2005年9月20日掲載)から第72回(2007年3月31日掲載)までの原稿を再掲載したものとなります。第73回以降、最新のものにつきましては、コチラにて、ご確認ください。

以上のように、VI方式で大容量のキャッシュを実現するには制約があるので、より大きな1次キャッシュとする場合はPIPT方式が用いられる。但し、普通にTLBを引き物理アドレスを求めてからキャッシュをアクセスすると時間が掛かるので、メモリの回路特性を利用して高速化する方法を用いることが多い。一般的なメモリの回路構造は図10に示すように、メモリセルアレイの中からアクセスするメモリセルを行アドレスと列アドレスで選択する。行の選択は行アドレスをRow Decoderでデコードし、セル一つのアレイの一行を選択する。列方向にも信号を増幅して読み出すセンスアンプの前に8:1のマルチプレクサがあり、データ出力の各ビット(D0、D1、…)に対して列アドレスに従って8組のビット線ペアの中から読み出すビット線ペアを選択する。

  • メモリアレイの回路構造

    図10:メモリアレイの回路構造

密度を高めるためメモリセルは出来るだけ小さく作るが、センスアンプはずっと大きく、メモリセルの幅で非常に縦長に作るのも具合が悪いので、メモリセル幅の8倍の幅で作るという場合が多い。このために上記のように8:1マルチプレクサを設け、これを列アドレスで選択する構造が用いられる。この構造では、行アドレスからD0出力までの黄緑で書いたパスよりも、列アドレスからD0出力までの青で書いたパスの方が遅延時間が短い。

この時間差を利用し、行アドレスにはVIとPIで違いが無いページサイズで決まるインデックスを入力し、TLBで変換した実ページアドレスの内の下位3ビットを列アドレスに入力する。行アドレスから出力までの遅延時間と、TLBの変換時間+列アドレスから出力までの遅延時間の大きい方でキャッシュのアクセス時間が決まる。つまり、TLBの変換時間が行アクセス時間と列アクセス時間の差と同程度であれば、キャッシュアクセス時間のペナルティー無しにPI方式を実現できる。

AMDのOpteronやVIAのC5PはIntelのIA32プロセサと同様に4KBページを採用しているが、1次キャッシュは64KBで2way(VIA C7は64KB 4way)であり、各wayはページサイズの8倍になっている。AMDやVIAはIntelとの互換性を売り物にしているので、OSのメモリ管理をいじってVIとPIのインデックスを一致させることは出来ないし、キャッシュラインを移動する方法も各wayがページサイズの8倍では移動の頻度が高くなり性能低下のリスクが大きいので、ここで述べたメモリアレイの回路的な特性を利用したPI方式を使っているのではないかと思われる。

IBMのメインフレームもPIPT方式を使うことにより、最小ページサイズより大きなwayのセットアソシアティブキャッシュの使用を可能にしている。しかし、まともにTLBを引いて列アドレスを求めるのでは遅いので、高速で仮想アドレスから実アドレスを予測する機構を備えている。この方式は、キャッシュの高速アクセスと大容量化を両立させる良い方式であるが、予測とTLBを引いた結果が一致しているかどうかを検査し、予測はずれの場合は、これを修正する制御機構が必要であり、また、予測が外れるとその修正に数サイクルを必要とする。

キャッシュコヒーレンシ

システム全体にプロセサが1個でキャッシュも一つしかない(ここでは1次キャッシュ、2次キャッシュという階層は忘れて、1次キャッシュしかないとして話を進める)場合は簡単であるが、Intelプロセサで言えば、Xeon DPとかMPとか言う複数のプロセサでメモリ空間を共用する構成が可能な場合、あるいはシングルチップでもデュアルコアの場合は複数のキャッシュが存在する。

キャッシュが参照専用で書き換えが行われない場合は、コピーが幾つあっても問題ないが、現金や在庫などを管理する元帳などは、それぞれのプロセサがコピーを持って独立に書き換えを行うと滅茶苦茶になってしまう。従って、複数のプロセサがキャッシュを持つシステムでは複数のキャッシュの間で内容に矛盾が出ないようにすることが必要であり、これをキャッシュコヒーレンシ制御と言う。

MSI / MESI / MOSIプロトコル

キャッシュラインの状態を表わすには、最低でも、内容が無効(Invalid)、内容は有効でメモリと同じ(Shared)、内容は有効で書き換えられている(Modified)の3状態が必要である。この3状態を使うと、最初はキャッシュラインの状態はInvalidであるが、プロセサAが読込みを行うと、プロセサAの対応するキャッシュラインはShared状態となる。次いでプロセサBが同じアドレスを読むと、メモリから同じデータが読み出されプロセサBのキャッシュに入り、Shared状態になる。

問題は書き込みを行う場合で、プロセサAがこのアドレスに書き込みを行うと、他のプロセサのキャッシュにもこのアドレスのデータが残っていると矛盾を生じてしまう。このためプロセサAは、他のプロセサ全てに対してそのアドレスのデータをキャッシュに持っている場合は、SharedからInvalid状態への変更を要求する。そして、全てのプロセサから要求を実行したという返事を貰ってから、書き込みを行い、状態をModifiedにする。

このアドレスに対して他のプロセサが読み込みを行うと、プロセサAはキャッシュラインの内容をメモリに書き戻し、状態をSharedに変更する。読込み要求を出したプロセサは、書き戻しが完了してからメモリから読み出すというやり方がハードウェアの作りとしては簡単であるが、プロセサAのメモリへの書き戻しデータを直接受け取るというやり方のほうが性能的には有利である。