ライン衝突、TLBあふれ

アクセスするよう素数nを比較的小さい値に固定し、ストライドの間隔mを大きくしていくと、配列のサイズがキャッシュサイズの2倍の倍数になったとき、ライン衝突が起こり、性能が低下します。いくつかのライン上に全てのアクセスが集中するため、nが小さくキャッシュサイズに余裕があるにもかかわらす、毎回キャッシュミスが起きてしまうためです。また、mがキャッシュの1way分のサイズ(=キャッシュサイズ/way数)の倍数のとき、全てのアクセスが同じラインにくるため、さらに性能が低下します。

また、配列TLBのサイズを超えると、TLBあふれによる大幅な性能低下が起こります。この時、ストライドの間隔mがページサイズ以下の場合は、mを増やすとページ更新の頻度が上がる為に性能が次第に低下していきますが、ページサイズ以上になった時点で毎回新しいページが必要になり、上記のライン衝突部分以外では性能はほぼ一定になります。

プログラムline.c

実行結果(クリックすると詳細な図を表示)

図1.n=32 図2.n=64
図1.n=32 図2.n=64
図3.n=128 その1 図4.n=128 その2
図3.n=128 その1 図4.n=128 その2
図5.n=256 その1 図6.n=256 その2
図5.n=256 その1 図6.n=256 その2
図7.n=512 その1 図8.n=512 その2
図7.n=512 その1 図8.n=512 その2

全体的に、原因不明の性能低下が多く、あまりきれいなグラフは得られませんでした。

どのグラフでも、mが大きくなると等間隔で性能が低下する部分がでてきましたが、mが小さいうちは規則性は見られませんでした。それぞれ何の倍数のところで性能が低下しているのかをまとめると次のようになります。m×nが一定、もしくはmが一定の部分が同じ列にくるようにしてあります。

表1.速度が低下している箇所
n mの間隔
32 64 128   1024 2048  
64   128 512 1024 8192
128 32 64 256 512 8192
256 16 32 128 256 8192

mの間隔が8K(64KB)のところでは、n=32のとき以外では性能低下が起こっています。間隔が64KBと1次キャッシュの容量より大きいので、2次キャッシュのライン全衝突と考えられます。ここから、2次キャッシュは4-way set associativeだろうと考えました。(256KB÷64KB=4より。)しかし、実際には2次キャッシュは8-way set associativeでした。

右から二列目の性能低下は、m×nが64Kの倍数、すなわち配列のサイズが512KBの倍数のときです。これは2次キャッシュの容量の2倍なので、2次キャッシュのライン衝突によるものと考えられます。それ以外にも、m×nが一定の値で遅くなっていますが、原因はよくわかりません。これらの中には、あまり大きな変化ではないものもありますが、はっきりとその部分だけ遅くなっているものもあります。

また、nが128以上の場合、2のべき以外の場所での速度が途中で次第に遅くなっていき、m=512で一定になっています。このときの間隔は512×8=4KBで、TLBのページサイズと一致しました。TLBのエントリ数は64なので、nがTLBのエントリ数を超えた場合にTLBあふれが起こっていることがわかります。

nが64以下の場合、m×n=64K(512KB)以上ではなぜかmが小さいときより速くなっています。これは、配列のサイズが2次キャッシュの2倍以上になったときに相当します。何か理由がありそうな値ですが、原因はよく分かりません。


Prev. ストライドアクセス Next ループアンローリング
性能測定メニューへ戻る

最終更新日:2003/1/28