前者の方式は、プログラマが判断して、本当に必要な情報だけをローカルな高速メモリに入れるので効率が良いが、何時、どのデータを入れるかをプログラマが考えて記述する必要があるので、プログラミングが難しい、あるいは面倒という欠点がある。
一方、後者の方法は、どのデータが必要かをハードウェアが予測するので、必ずしも予測の精度が十分ではなく前者の方法より効率が悪いという問題があるが、プログラムを書くにあたって、特別な考慮は必要ない。また、ローカルな高速メモリを意識せずに書かれた昔のプログラムも自動的にスピードアップするという大きなメリットがあり、現実には、後者のハードウェア方式のローカルメモリが一般的である。
このプログラムで意識する必要のない後者のローカルメモリを、キャッシュ(Cache:秘密の小箱)と呼ぶ。プログラムには気付かれないように隠した小箱で、大幅に性能向上というマジックの仕掛けに対する良い命名であると思う。
図4.2 メモリ階層と入れ替えテクニック |
前述のように、ローカルな高速メモリとメインメモリ、そしてメインメモリと磁気記憶装置の間のデータ入れ替えは、プログラムが明に指示する方法と、プログラムが指示することなく、下層のOSやハードウェアが入れ替える方式があり、これを図示すると図4.2のようになる。
なお、磁気記憶とメインメモリの間を、OSの制御で自動的に入れ替える方式は、仮想記憶と呼ばれ、Windowsを含めて、最近のほとんどの汎用OSで採用されている方式である。Windows PCでCTL+ALT+DELでWindowsタスクマネージャを出してみると、大量のメモリを使用する多数のプロセスが動作しているのが分かる。そして、使用できる物理的なメインメモリが不足する場合には、Windowsが自動的にディスクへの追い出しや、再度、必要となった場合のディスクからの読み込みを行っているのである。
ローカルメモリやキャッシュのような高速、小容量のメモリが有効に働くためには、メモリ上の頻繁にアクセスされるデータがこの小容量のメモリに格納されていなければならない。そのためには、メインメモリの一部のアドレス(連続である必要はない)が頻繁にアクセスされる、あるいは、あるアドレスをアクセスすると、短時間のうちにそのアドレスが何回もアクセスされるというような性質が無ければならない。このようなアクセスを局所性(Locality)があると言い、前者を空間的局所性(Spatial Locality)、後者を時間的局所性(Temporal Locality)があるという。
このような局所性のあるアクセスの場合には、ある時間スケールで見ると、頻繁にアクセスされるアドレスはメモリ全体のごく一部であるので、小容量のメモリに格納できるわけである。
一方、メモリ全域をランダムにアクセスするような場合は、局所性が無い。また、巨大な配列に格納された数値の合計を計算するというような場合は、アクセスするアドレスは連続であるが、それぞれのアドレスは1回読まれるだけで再利用されず、局所性がないのでキャッシュやローカルメモリは有効ではない。
ただし、メモリからローカルメモリへのデータ転送は32B(バイト)か、それ以上の単位でまとめて行うことが多く、連続アドレスでアクセスする場合は、同じ転送単位内のアドレスを複数回続けてアクセスすると言う空間的、時間的局所性が生じて、メモリアクセス回数が減少して性能が向上するという効果はある。
しかし、アクセスされるアドレスが64バイト飛びであるような場合は、32バイトを一纏めにしてメモリから読んでくるのであるが、その内の4バイトしか使用せず、残りの28バイトは無駄に転送され、かつ、無駄にキャッシュメモリを占有してしまうというロスが発生する。