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

キャッシュに頻繁に使うデータを溜め、遅いメモリまでアクセスに行かないで済むようになれば性能が上がるのは当然であるが、それではどのくらい性能が上がるのであろうか?

プロセサの性能はクロック周波数まで考慮にいれた毎秒何命令実行できるかを示すMIPS(Million Instructions Per Second)のような絶対性能の指標もあるが、アーキテクチャ的な性能を言う時には、クロックの影響を除いて1サイクルに何命令実行できるかというIPC(Instructions Per Cycle)あるいは、その逆数である1命令の実行に何サイクルかかるかというCPI(Cycles Per Instruction)が使われる。

プログラムの実行のためのメモリアクセスの頻度は、当然、アプリケーション依存であるが、Load命令は5命令に1回、Store命令は10命令に1回、命令のフェッチは4バイト命令を64バイト単位でメモリからキャッシュに読み込むとすると、最低でも16命令に1回、平均的に半分として8命令に1回というのが、当たらずとも遠からずという頻度である。理想的な完全ヒットの1次キャッシュがあり、メモリアクセスの待ち時間が生じない場合のCPIをCcoreとし、上記の頻度でアクセス時間Tmのメモリをアクセスする場合のCPIは次の式で表わされる。

  • CPI=Ccore+Tm*(1/5+1/10+1/8)=Ccore+0.425Tm

Ccoreは最近のスーパースカラプロセサでは0.7~1サイクル/命令程度の値である。一方、プロセサのサイクルタイム(クロック周波数の逆数)は2.5GHzクロックの場合で0.4nsであり、メモリのアクセス時間が80nsとするとプロセサにとっては200サイクルであり、0.425Tmは85サイクルになる。つまり、平均命令実行時間は約86サイクルであり、そのうちの85サイクル分はメモリアクセス待ちという状態になる。これではプロセサコアにトランジスタを注ぎ込んで高度な並列実行をやらせてCcoreを改善しても、全く意味がない。

次に1次キャッシュを設けた場合は、命令当たりの1次キャッシュのミス率をm1、1次キャッシュをミスしてメモリからデータを取ってくる場合のアクセス時間をTmとすると、CPIは次式で表わされる。

  • CPI=Ccore+Tm*m1

1次キャッシュのミス率は実行するプログラムとキャッシュ量や構成によるが、32KB程度の1次キャッシュの場合、5~10%というのは当たらずとも遠からずの値であり、仮に10%とすると、Ccoreが1サイクル、Tm*m1が20サイクルとなり平均命令実行時間は21サイクルとなる。つまり、1次キャッシュを設けることにより性能は4倍以上に向上したことになる。しかし、まだ、メモリアクセスの待ち時間がプロセサコアの実行時間の20倍という状況であり効率が悪い。

  • キャッシュの役割

次に、2次キャッシュを設ける場合を考える。1次キャッシュのミス率をm1、2次キャッシュのミス率をm2、1次キャッシュをミスして2次キャッシュをヒットした場合の待ち時間をTm12、2次キャッシュもミスしてメモリからデータを持ってくる時間をTmとすると、CPIは、

  • CPI=Ccore+Tm12m1(1-m2)+Tm*m2

と表わされる。Tm12 は典型的な値として10サイクル、大容量2次キャッシュの場合のm2は0.1%~1%とすると、Ccoreは約1サイクル、第2項も約1サイクル、第3項はm2が0.1%の場合は0.2サイクルとなり、平均命令実行時間は2.2サイクルとなる。一方、m2が1%の場合は、第3項は2サイクルとなり、全体の平均命令実行時間は4サイクルとなる。従って、1次キャッシュだけの場合に比べて、大容量の2次キャッシュを設けることにより5倍から10倍の性能向上が達成され、メモリ待ち時間とプロセサコアの実行時間をおおよそ同程度の値とすることが出来る。

しかし、2次キャッシュミスが大きいプログラムでは、2次キャッシュの容量を更に大きくしてm2を下げるか、あるいは、さらに容量の大きな3次キャッシュを設けてミス率を下げてメモリアクセス頻度を減らすことが必要となる。データベースなどのビジネス系の大規模アプリケーションは大きなメモリ領域をランダムにアクセスする2次キャッシュミス率の高いプログラムであり、これらを効率よく実行することが求められるサーバ用プロセサでは、2次キャッシュを大容量化したり、速度は落ちるが更に大容量の3次キャッシュを使用したりする構成が一般的である。

  • 2次キャッシュを持つ性能モデル

つまり、キャッシュミスが大きいプログラムを実行する場合にはコアを複雑にしてCPIを減らしたり、クロックを上げても性能は殆ど改善されず、性能を改善するためには、キャッシュのミス率の低減と、下位のキャッシュやメモリのアクセス時間を短縮することが重要である。

一つ注意すべきことは、ここで述べたCPIの計算式は、1次キャッシュをミスするとデータが到着するまでコアでの処理はストップするという単純なプロセサを想定して作られているが、最近のプロセサでは命令の先読みをしたり、データアクセスについてもキャッシュミスがあっても、そのデータに依存しない次の命令をどんどん実行し続けるというようなOut-of-Order処理を行ったりしており、このオーバーラップの時間を待ち時間Tm*から差し引くような補正が必要である。