操作して学ぶ
CPUキャッシュ可視化
同じ量のデータを触っても、触り方(アクセスパターン)で速度は10倍変わります。 鍵はCPUキャッシュ。メモリはラインという固まり単位でキャッシュに載るため、連続アクセスは速く、飛び飛び・ランダムは遅い。 パターンを切り替えて、ヒット率と実効レイテンシの変化を確かめてください。
メモリ(1マス=1キャッシュライン=16要素)
0123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
キャッシュ常駐 ヒット ミス
キャッシュ(0/16行・左がLRU=次に追い出される)
(空)実行するとラインが載ります
アクセス数
0
ヒット率
0.0%
ミス
0
実効レイテンシ
—
速い(L1 4cyc)遅い(主記憶 200cyc)
1本のラインには16要素が丸ごと載る(空間的局所性)。だから連続アクセスは最初の1回だけミスで、残り15回はヒット。 ストライドを16にすると毎回別ラインを踏むのでヒットが消える。ランダムはヒット率がほぼ「容量÷全体」に落ちる。 配列をキャッシュ容量以下(例: 16行+容量16)にすると、ランダムでも2周目から全ヒット=時間的局所性。
メモリ階層と局所性
CPUに近いほど速くて小さく、遠いほど遅くて大きい。概算のアクセスコストは次の通り。数字は目安で世代により変わります。
| 階層 | 概算レイテンシ | 容量の目安 |
|---|---|---|
| レジスタ | 0サイクル | 数百バイト |
| L1キャッシュ | 約4サイクル | 数十KB |
| L2キャッシュ | 約12サイクル | 数百KB |
| L3キャッシュ | 約40サイクル | 数MB〜数十MB |
| 主記憶(DRAM) | 約200サイクル | 数GB〜 |
- 空間的局所性:近くのデータはまとめてラインで載る。だから配列を順に舐めると大半がヒットする。構造体配列(AoS)より配列構造体(SoA)が速いのもこれ。
- 時間的局所性:一度触ったデータはしばらくキャッシュに残る。ホットなデータをキャッシュに収まる大きさに保つと速い。
- 実務では:連結リストより配列、ランダムより連続、行優先の配列は行方向に舐める。これだけで体感が変わる。