これを行の粒度ベースで実際に見る必要はありません。維持するのはかなり複雑であり (ドウェルチが彼の非常に良い答えで指摘しているように)、十分な回数繰り返さない限り測定することはほとんど不可能です (これにより、特定のキャッシュレベルを強制的にヒットするための適切な条件)。
代わりに、連続した物理空間に存在する単純な配列を作成することから始めることができます (OS に精巧なページ割り当てメカニズムがある場合は、微調整が必要になる場合があります)。この配列にデータを入力し (キャッシュラインごとに 1 回のアクセスで十分です)、繰り返し読み取りを開始します。配列サイズが L1 に収まるほど小さい場合 (たとえば 32k の場合、32k 文字またはそれより少し少ない文字を割り当てて、64 番目の要素ごとにアクセスすることができます)、十分な繰り返しの後、そこに到達するアクセスの大部分を取得する必要があります。ページマップ エントリ、スタック、またはその他のヒープ変数など、他のキャッシュされた行が干渉するまれなケースがいくつかありますが、ほとんどの場合、L1 ヒットが発生するため、うまく調整されます。安定した結果を得るのに十分な回数繰り返すと、コンテキスト スイッチのようなイベント (システムを制御してそれを防ぐことができない場合) でさえ消えてしまいます。
次に、データ セットのサイズを徐々に増やしていきます。L1 サイズを超えると、アクセスあたりの時間 (全体の時間をアクセス数で割った値) の明確な低下を確認できるはずです。キャッシュが LRU で動作する方法に注意してください。配列に線形の順序でアクセスするという事実は、配列が L1 に収まらないほど大きくなった分、最後の要素がおそらく最初の要素を追い出すため、部分的な利益を得るべきではないことを意味します。次のイテレーションがそこにそれらを見つけるのを防ぐためにちょうど間に合うもの (ただし、最新の CPU ではロードが順不同になる可能性があるという事実を楽しむことができます)。さらに進んで、多かれ少なかれ L2 サイズに達すると (システムの L2 が厳密に包括的でない場合、L1 + L2 の両方を使用することでわずかな利点が得られる可能性がありますが、説明されているアクセス パターンはそれをほぼ完全に防止するはずです)。
一部の HW 機能は問題を複雑にする可能性があることに注意してください。まず第一に、HW プリフェッチャーです。これは、開始して先の行を取得することがほとんど認められています。可能であれば、BIOS で無効にする必要があります。それ以外の場合は、より大きなストライド (64 の代わりに 128 または 256) にジャンプできます。キャッシュは直接マップされている可能性が高く (いくつかの結合性を使用して)、すべてのキャッシュに 1 つだけを強調する効果があります。 2 ~ 4 セットで、残りは空のままで問題ありません (時間を新しいアクセス数で割ることを忘れない限り)。また、プリフェッチ アシストではなく、実際のタイミングを取得するのに十分なストリームを中断します (ストライド ベースのプリフェッチャーを使用することもできますが、通常はストリーマーほど強力ではありません)。