キャッシュ内の「ブロックサイズ」の概念

私は、ダイレクトマップキャッシュとセットアソシエイティブキャッシュの概念を学び始めました。 私はいくつかの非常に基本的な疑問を持っています。ここに行く。

アドレスは32ビット長で、64Byteのブロックサイズと512フレームの32KBキャッシュを持っていますが、実際に「ブロック」内にどれくらいのデータが格納されていますか?私がメモリ位置からの値からロードする命令を持っていて、その値が16ビット整数ならば、64Byteブロックのうちの1つが16ビット(2Bytes)整数値だけを格納するのでしょうか?ブロック内の他の62バイトは何ですか?私は今も16ビット整数値をロードする別のロード命令を持っている場合、この値はロードアドレスに応じて別のフレームの別のブロックに入ります(アドレスが前の命令の同じフレームにマップされていれば、ブロックは64バイトに2バイトしか記憶しない)。正しい?

これは非常にばかげた疑いのように思えば私を許してください。私は自分のコンセプトを正しく取りたいと思っています。

8

2 答え

私はキャッシュを説明する誰かのためにこの電子メールを入力しましたが、あなたも役に立つと思うかもしれません。

You have 32-bit addresses that can refer to bytes in RAM. You want to be able to cache the data that you access, to use them later.

Let's say you want a 1-MiB (220 bytes) cache.

What do you do?

You have 2 restrictions you need to meet:

  1. Caching should be as uniform as possible across all addresses. i.e. you don't want to bias toward any particular kind of address.
    • How do you do this? Use remainder! With mod, you can evenly distribute any integer over whatever range you want.
  2. You want to help minimize bookkeeping costs. That means e.g. if you're caching in blocks of 1 byte, you don't want to store 4 bytes of data just to keep track of where 1 byte belongs to.
    • How do you do that? You store blocks that are bigger than just 1 byte.

Let's say you choose 16-byte (24-byte) blocks. That means you can cache 220/24 = 216 = 65,536 blocks of data.

You now have a few options:

  • You can design the cache so that data from any memory block could be stored in any of the cache blocks. This would be called a fully-associative cache.
  • The benefit is that it's the "fairest" kind of cache: all blocks are treated completely equally.
  • The tradeoff is speed: To find where to put the memory block, you have to search every cache block for a free space. This is really slow.
  • You can design the cache so that data from any memory block could only be stored in a single cache block. This would be called a direct-mapped cache.
  • The benefit is that it's the fastest kind of cache: you do only 1 check to see if the item is in the cache or not.
  • The tradeoff is that, now, if you happen to have a bad memory access pattern, you can have 2 blocks kicking each other out successively, with unused blocks still remaining in the cache.
  • You can do a mixture of both: map a single memory block into multiple blocks. This is what real processors do -- they have N-way set associative caches.

Direct-mapped cache:

Now you have 65,536 blocks of data, each block being of 16 bytes.
You store it as 65,536 "rows" inside your cache, with each "row" consisting of the data itself, along with the metadata (regarding where the block belongs, whether it's valid, whether it's been written to, etc.).

Question: How does each block in memory get mapped to each block in the cache?

Answer: Well, you're using a direct-mapped cache, using mod. That means addresses 0 to 15 will be mapped to block 0 in the cache; 16-31 get mapped to block 2, etc... and it wraps around as you reach the 1-MiB mark.

So, given memory address M, how do you find the row number N? Easy: N = M % 220/24.
But that only tells you where to store the data, not how to retrieve it. Once you've stored it, and try to access it again, you have to know which 1-MB portion of memory was stored here, right?

So that's one piece of metadata: the tag bits. If it's in row N, all you need to know is what the quotient was, during the mod operation. Which, for a 32-bit address, is 12 bits big (since the remainder is 20 bits).

So your tag becomes 12 bits long -- specifically, the topmost 12 bits of any memory address.
And you already knew that the lowermost 4 bits are used for the offset within a block (since memory is byte-addressed, and a block is 16 bytes).
That leaves 16 bits for the "index" bits of a memory address, which can be used to find which row the address belongs to. (It's just a division + remainder operation, but in binary.)

You also need other bits: e.g. you need to know whether a block is in fact valid or not, because when the CPU is turned on, it contains invalid data. So you add 1 bit of metadata: the Valid bit.

There's other bits you'll learn about, used for optimization, synchronization, etc... but these are the basic ones. :)

23
追加された
@Faizan:それはあなたのメモリ帯域幅を含む多くの要因に依存します。ブロックサイズが小さくなればなるほど、高いコスト($)でより細かい粒度が得られ、潜在的にRAMからのスループットが低下します。一つの答えはありません。
追加された 著者 Mehrdad,
@ JoaquimFerrer:うわー、5年と私は誰も今まで誤植を指摘して信じられない。私はそれを修正したと思う、確かめるためにそれを再確認できますか?知らせてくれてありがとうございます!
追加された 著者 Mehrdad,
@ JoaquimFerrer:ハハありがとう!しかし、うーん、私はこれが正しいと思いますか? M%2 ^ 20は、キャッシュ内のバイトのインデックスを返します。だから2 ^ 4で割り切れば、ブロックのインデックスが得られるはずですよね?たとえば、M%2 ^ 20が17を与える場合、ブロック17/16 = 1を見る必要があることを意味します。
追加された 著者 Mehrdad,
@ nj2237:キャッシュにもメモリアドレスを格納する必要があります。そうでなければ、特定のアドレスのメモリ内容がキャッシュにあるかどうかをどのように知ることができますか?すべてのメモリブロックを別のキャッシュブロックにマップするのに十分なキャッシュがありません。 RAMについては、そうですが、RAMの1バイトごとに必ずそのアドレスを保存する必要はありません。必要なアドレス(たとえば、大きな配列の先頭)だけを保存します。
追加された 著者 Mehrdad,
@ nj2237:うん、あなたがそれを持っているように聞こえる。
追加された 著者 Mehrdad,
こんにちは@Mehrdad本当に良い説明、多くのありがとう。しかし、2番目の点では、「1バイトがどこに属しているかを追跡するために4バイトのデータを格納したくない」と言います。キャッシュはちょうど4バイトのアドレスで動作しますか?それはデータだけを格納し、正しいアドレスではない?そして、RAM上のbtwは、1バイトのデータを格納するために4バイトのデータ(32ビットアドレス)を使用していませんか?
追加された 著者 nj2237,
ああ、それは意味がある..ありがとう!それはメタデータでしょうか?このプロセスは、たとえばDMCでCPUがストレージからデータをフェッチしようとするときに、メモリアドレスのインデックス部分(中央の16ビット)を使用して、それが所属する「行」またはブロックを確認します。 (キャッシュ内の)データのメタデータ内のタグ(上位12ビット)をメモリアドレスのタグ部分と比較し、それらが等しい場合はキャッシュヒットかどうかを確認します。また、RAMの部分に良い点も、私は認識していませんでした。ありがとう!
追加された 著者 nj2237,
ブロックサイズが大きくなったり、ブロックサイズが小さくなったりする効率の点で優れていますか?
追加された 著者 Faizan,
ありがとう..すべてが今意味があります:)
追加された 著者 hektor,
@Mehrdadメモリブロックがマップされるキャッシュブロックを発見すると言うと、それはM(メモリアドレス)mod S(キャッシュサイズ)ですが、そのようにアドレス0はブロック0にマップされ、アドレス1はブロック1にマップされています。また、あなたの例では、間違っている2 ^ 20ブロックのキャッシュがあります。または私は何かを逃していますか?
追加された 著者 Joaquim Ferrer,
@Mehrad私はこれに新しいですが、私はあなたが間違っていると思うので、キャッシュは2 ^ 4ブロックを持つことになります。私はそれがブロックサイズのM /ブロックサイズであると思います。 M /ブロックはあなたにブロック番号を与え、modはそれを許容範囲内に置きます。
追加された 著者 Joaquim Ferrer,
@Mehradそれはstackoverlfowの魔法だよ! 5年後でもあなたの答えは信じられないほど役に立ちました。
追加された 著者 Joaquim Ferrer,
@Mehradはい、あなたは正しいです!答えもありがとう!
追加された 著者 Joaquim Ferrer,

私はあなたがタグ、インデックス、オフセットの基礎を知っていると仮定していますが、ここで私のコンピュータアーキテクチャのクラスで学んだように簡単な説明があります。ブロックは64バイトブロックに置き換えられます。したがって、新しいブロックがキャッシュに置かれるたびに、1バイトしか必要ないかどうかにかかわらず、すべての64バイトが置換されます。そのため、キャッシュにアドレッシングするときに、ブロックから取得するバイトを指定するオフセットがあります。あなたの例を挙げると、16ビット整数だけがロードされている場合、キャッシュはインデックスによってブロックを検索し、タグをチェックして正しいデータを確認し、オフセットに従ってバイトを取得します。今度は別の16ビット値をロードし、同じインデックスで異なるタグを使って64バイトブロックを新しいブロックに置き換え、指定されたオフセットから情報を取得します。 (直接マッピングされていると仮定して)

私はこれが助けて欲しい!これ以上の情報が必要な場合やこれがまだ不明な場合は教えてください。

5
追加された
はい、それは助けます..しかし、私に他のサイトを追加してください。
追加された 著者 hektor,
@hektorこのリンクをご覧ください。記憶とさまざまな交換技術と私を最も助けてくれたものです。インタラクティブなJavaモジュールもあります。
追加された 著者 GSilva,