FE EXAM

ダイレクトマップ方式(direct mapping)

メモリアドレスからキャッシュ位置が1つに決まるキャッシュ配置方式

INTERACTIVE VISUALIZATION
タグインデックスオフセット
シナリオ
アドレスを分割して試す20
010100
→ インデックス = 2 行に入る
ステップ1 / 7
STEP 1/7初期状態 — キャッシュは空(4行)キャッシュは4行(インデックス0〜3)あり、すべて空です。主記憶のアドレスは6ビットで表されるとします。ダイレクトマップ方式では、アドレスのうち決まったビットを見れば「どの行に入るか」が機械的に1つに決まります。
アドレス 20(2進 010100タグ010インデックス10OFS0インデックス=2行へキャッシュ(4行)0123
解説

📌
ダイレクトマップ方式とは

アドレスmod 行数0123入る行が1つに決まる(行2に固定)

ダイレクトマップ方式とは、主記憶(メインメモリ)のあるブロックをキャッシュのどの行に置くかが、アドレスから機械的に1つに決まるキャッシュ配置方式のことです。キャッシュ=CPU のそばにある小さく速い記憶、ブロック=主記憶をひとまとまりにした単位のことです。

位置の決め方はとても単純で、キャッシュ位置 = アドレス(ブロック番号) mod キャッシュサイズ(行数)です。割り算の余りを使うので、同じブロックは必ず同じ行に入ります。上のツールでスライダーを動かすと、アドレスのインデックス部が示す行が1つに定まる様子を確認できます。

身近な例で言うと、下駄箱(くつ箱)の番号が出席番号で固定されているようなものです。出席番号10番の人は必ず10番の箱を使い、空いている箱を自由に選ぶことはできません。探すときは決まった箱だけ見ればよいので速い反面、同じ箱を使う人どうしはぶつかります。

📐
位置決めの仕組み

位置を決めるために、アドレスを3つの部分に分割します。アドレスのビットの並びは、上位から順に次のようになります。

タグ部:同じ行を使う複数のブロックを区別する印。行に記録しておき、ヒット判定で照合する
インデックス部:どのキャッシュ行に入るかを直接示す番号
オフセット部:ブロック内の何バイト目かを示す位置

例: アドレス 010100 を分割(行数 4)
─────────────────────
タグ 010 | インデックス 10 | オフセット 0
→ インデックス 10(2) = 2 → 必ず「行2」に入る

ヒット判定の手順は次のとおりです。まずインデックス部で行を1つに絞り、その行に記録されているタグと、アドレスのタグ部を照合します。タグが一致すればヒット、一致しなければミスです。1行だけ見ればよいので、照合は1回で済み、回路が単純で高速になります。

上のツールの「アドレスを分割して試す」スライダーを動かすと、どのアドレスがどの行に入るかが一目で分かります。インデックス部が同じアドレスは、タグ部が違っても必ず同じ行に入る点に注目してください。

⚖️
利点と欠点

「位置が1つに固定される」という性質が、ダイレクトマップの利点にも欠点にもなります。両面を整理しましょう。

○ 利点
・行の特定がインデックスを見るだけで済む
・照合するタグは1つだけ(検索不要)
・回路が単純で安価・低消費電力
× 欠点
・同じインデックスのブロックは同じ行を奪い合う
・他の行が空いていても衝突(追い出し)が起きる
・特定のアクセスパターンで効率が落ちる

最大の欠点は衝突(コンフリクトミス)です。たまたまインデックス部が同じになる2つのブロックを交互にアクセスすると、ほかの行が空っぽでも、その1行を取り合って毎回追い出しが起きます。上のツールの最後で、タグ違いの別ブロックが同じ行を上書きする様子を確認できます。

この衝突を緩和するために、行に少し置き場所の自由を持たせたのがセットアソシアティブ方式、完全に自由にしたのがフルアソシアティブ方式です。ダイレクトマップは「速いが衝突しやすい」極端な一方の方式だと位置づけられます。

📌
なぜ衝突(コンフリクト)が起きるのか

主記憶(メモリ)ブロック0ブロック1ブロック2ブロック3ブロック4ブロック5ブロック6ブロック7キャッシュ(4行)0123どちらも行0へ!4で割ると余りが同じ(0 mod 4 = 0, 4 mod 4 = 0)→ 互いに追い出し合う

結論:ダイレクトマップでは、インデックス部(アドレスをキャッシュ行数で割った余り)が同じになるブロックは、必ず同じ行に入ることが決まっているからです。他の行が空いていても「別の行を使う」という選択肢がありません。

具体例で見てみましょう。キャッシュが4行のとき、キャッシュ行 = ブロック番号 mod 4 で決まります。
ブロック00 mod 4 = 0 → 行0に入る
ブロック44 mod 4 = 0 → 行0に入る(被る!)
ブロック8・12・16…:すべて行0に入る(mod 4 の余りが0)

身近な例で言うと、出席番号が「1番・5番・9番…」のように4の倍数ずれた生徒は、全員同じ番号の下駄箱を使わなければならないルールと同じです。空いている箱が隣にあっても使えず、毎回「今日の当番」が前の人を追い出します。ダイレクトマップの衝突はまさにこの状況です。

📌
ヒット率とキャッシュの効果

ヒットキャッシュで見つかった→ 高速に取得ミス主記憶を取りに行く→ 時間がかかるヒット率が高いほどCPUの待ち時間が減る

ヒット率(=キャッシュで見つかった回数 ÷ 総アクセス回数)が高いほど、CPUが主記憶を待つ時間が減り、コンピュータ全体が速くなります。ダイレクトマップでヒット率を上げるには、主に2つのアプローチがあります。

キャッシュ容量を増やす:行数が増えればインデックスの種類が増え、同じ行に入るブロックが減って衝突しにくくなる
アクセスの局所性を活かす:プログラムは短い時間に近い番地を繰り返しアクセスする傾向(局所性)がある。この傾向が強いほどキャッシュに残っている確率が上がりヒットしやすい

なぜ局所性があるとヒットしやすいのか。プログラムはループ(繰り返し処理)や配列(連続するデータの並び)を多用します。繰り返すたびに同じ番地へアクセスするので、1回目にキャッシュへ読み込まれたデータが2回目・3回目にもそのままヒットします。ダイレクトマップでも、衝突さえ起きなければこの恩恵を最大限受けられます。逆に衝突が多いアクセスパターンでは局所性の恩恵が消えてしまうのが、ダイレクトマップの泣き所です。

関連コンテンツ