
組み込み入門第六段では、これまでちょこちょこ触れいていたキャッシュメモリについて、改めて解説していきます。メモリ編最期になります。
なぜ必要?どんな役割を果たす?どのように動作する?という疑問が解決できればと思います。
そもそも、メモリって?どんなものがあるの?という方はこちらの記事で基礎をまとめています。
では、早速見ていきましょう。
目次
キャッシュメモリの基礎
キャッシュメモリとは

キャッシュメモリは主記憶装置とCPUの間に配置される高速メモリです。
通常CPUのアクセス処理は1ns程度かかるのに対して、SDRAMなどで構成される主記憶装置では100ns程度のアクセス時間がかかります。これでは、せっかくCPUが早く動けてもほとんどが待ち時間になってしまいます。
そこで、主記憶装置よりも高速なメモリ=キャッシュメモリを間に配置し、頻繁にアクセスするデータはキャッシュメモリに保持することでCPUの待ち時間を減らそうというのがキャッシュメモリのコアコンセプトとなります。
ちなみにキャッシュメモリは、主にSRAMにより構成されますが、SRAMのアクセス時間は8ns程度と非常に高速です。
SDRAMやSRAMの原理や構造はこちらで解説しています。
キャッシュメモリの構成

主記憶とCPUの間で速度差が大きく、1つのキャッシュでは効果が得られない場合、複数のキャッシュメモリを階層的に配置することがあります。
このとき、CPU日開放からL1(Level1)キャッシュ、L2キャッシュと呼びます。
一般的には、CPU日開放が容量が小さく、速度が早いように設計します。
キャッシュメモリの動作
キャッシュメモリの動作方式には次の2つがあります。
- インクルージョンキャッシュ
- ビクティムキャッシュ
インクルージョンキャッシュ

インクルージョンキャッシュでは、CPUが要求するデータがない場合、主記憶にあるデータをL3、L2、L1と伝達し、CPUに伝えます。このとき、L3、L2、L1は伝達しながらそのデータをキャッシュに保持します。そのためインクルージョンキャッシュでは上位(CPU側)のデータは下位のキャッシュが必ず保持しています。
ビクティムキャッシュ

ビクティムキャッシュではCPUの要求するデータがない場合、主記憶からL3、L2を飛ばし、L1キャッシュに直接データを渡します。そこでL1キャッシュから溢れたデータをL2キャッシュに、同様にL2キャッシュから溢れたデータをL3キャッシュに渡すという制御を行います。
キャッシュのヒット

キャッシュがどの程度機能しているかの指標として、キャッシュのヒット率があります。アクセスするデータがキャッシュに存在することをキャッシュヒットといい、その確率をヒット率といいます。
一方で、アクセスするデータがキャッシュに存在しないことをキャッシュミス、その確率をミスヒット率といいます。
また、キャッシュミスに起因して、CPUが停止する時間をミスペナルティと言います。
書き込み時の制御方式

次に、データ書き込み時の制御方式について見ていきます。
- ライトスルー方式
- ライトバック方式
ライトスルー方式では、書き込み時にキャッシュ上にデータがあるかに関わらず、主記憶に書き込みを行います。主記憶への書き込みは遅いため、処理時間が長くなってしまいますが、キャッシュと主記憶の間でデータが不一致になる場合がないため制御が簡便です。
一方で、ライトバック方式では、通常キャッシュメモリ飲みに書き込み、主記憶への書き込みはキャッシュメモリから追い出されたときなどに行います。主記憶への書き込み頻度が減ることで高速になります。一方でキャッシュメモリと主記憶の内容が不一致になることから制御が複雑化します。
マルチプロセッサシステムでの注意

ライトバック方式では、主記憶を共有するようなマルチプロセッサシステムに対して注意点があります。1つの主記憶に対して、複数のキャッシュおよびCPUが並行して存在するため、キャッシュメモリ間と主記憶との間に一貫性が崩れます。
例えば、CPU1が「りんご」のデータを書き込んだとき、キャッシュ1でデータが止まっているのに、CPU2が「りんご」のデータを要求したらどうなるでしょう?「りんご」は主記憶に到達していないため、データは取得できなさそうです。
このような問題に対処するために各CPUが主記憶の内容が変化したか監視し、変化があったら各キャッシュに反映させる「バススヌープ」や各CPUが他のCPUのキャッシュ更新を監視する「スヌープキャッシュ」などにより対策を行う必要がある。
キャッシュのデータ構造

最期に、キャッシュメモリのデータ構造について解説します。
キャッシュメモリでは、キャッシュラインと呼ばれる単位で、主記憶のアドレス範囲と対応させます。
これだけだと???だと思いますので、次の3つの具体的なデータ構造を見て理解を深めましょう。
- ダイレクトマップ方式
- セットアソシアティブ方式
- フルアソシアティブ方式
ダイレクトマップ方式

ダイレクトマップ方式では、主記憶のアドレスとキャッシュラインの対応が予め決まっています。
例えば、図に示した例では、キャッシュアドレス0x00には主記憶アドレス0x00か0x08が入り、キャッシュアドレス0x01には主記憶アドレス0x01か0x09が入る。などと対応関係を決めておきます。こうすることで、主記憶からキャッシュメモリにコピーする際にどこに格納すればよいか計算しなくていいため、非常に処理が単純で早くなります。その一方で、主記憶側から見れば格納箇所が制限されるためキャッシュミスが発生しやすいです。
セットアソシアティブ方式

キャッシュライン側に冗長性を持たせ、ヒット率をアップさせたものがセットアソシアティブ方式です。例えば、主記憶の0x00と0x08はキャッシュメモリの0x00か0x08の空いている方に格納できるようにします。キャッシュメモリ側の格納先が増えたことでヒット率がアップできます。キャッシュ側が2箇所格納できるのであれば2ウェイなどと呼びます。
一方で実装の際に回路が複雑化するのがデメリットです。
フルアソシアティブ方式

最期のフルアソシアティブ方式では、キャッシュ位置と主記憶位置の対応関係を予め作りません。キャッシュメモリの空き位置に格納します。
なんだそれができるならヒット率上がって一番いいじゃん、と一見思うのですが、都度書き込み位置を計算するため処理が遅く採用されません。
まとめ
以上、キャッシュメモリについてまとめてきました。
3記事に渡って、メモリ編をまとめてきましたがひとまずこれで以上になります。
次は、今回も少し登場した、「バス」について解説していきます。