具有 32 字节块的 2048 字节直接映射数据缓存。并假设 sizeof(int) == 4,Square 从内存地址 0 开始,缓存最初是空的,变量 i 和 j 存储在寄存器中。
您可以将struct point_color square[16][16]; 视为内存中从 0 开始的长磁带。矩阵中的每个条目都包含一个大小为 4*4 = 16 字节的结构。当矩阵完全被结构填充时,它的大小将是 16*16*16 = 4096 字节。 (内存地址 0...4095-16),看起来像这样(右侧的内存地址):
+-----------------+
| square[0][0] | 0-15
+-----------------+
| square[0][1] | 16-31
+-----------------+
| square[0][2] | 32-47
+-----------------+
.
.
.
+-----------------+
| square[15][15] | 4080-4095
+-----------------+
缓存直接映射为 32 字节块,这意味着它看起来像这样:
+----------------+
| 32 bytes | row 0
+----------------+
| 32 bytes | row 1
+----------------+
| 32 bytes | row 2
+----------------+
.
.
.
+----------------+
| 32 bytes | row 63
+----------------+
如您所见,写入的前 2048 个字节将全部放入缓存中,之后缓存将需要开始替换缓存中的行。由于这是一个直接映射的缓存,因此替换是直截了当的。您可以通过查看内存地址并将其分成几部分来计算内存块应放置在缓存中的哪一行。对于这个特定的缓存,地址布局是:
+----------------------+----------+--------+
| 21bits | 6bits | 5bits |
| tag | index | offset |
+----------------------+----------+--------+
操作顺序和缓存命中/未命中如下所示:
write square[0][0].c = 0; ---> cache miss (address 0), load memory block 0-31 into cache
write square[0][0].m = 0; ---> cache hit (address 4)
write square[0][0].y = 0; ---> cache hit (address 8)
write square[0][0].k = 0; ---> cache hit (address 12)
write square[0][1].c = 0; ---> cache hit (address 16)
write square[0][1].m = 0; ---> cache hit (address 20)
write square[0][1].y = 0; ---> cache hit (address 24)
write square[0][1].k = 0; ---> cache hit (address 28)
write square[0][2].c = 0; ---> cache miss (address 32), load memory block 32-63 into cache
write square[0][2].m = 0; ---> cache hit (address 36)
write square[0][2].y = 0; ---> cache hit (address 40)
.
.
.
.
write square[8][0].c = 0; ---> cache miss (address 2048), load memory block 2048-2079 into cache and replace the cache-row containing memory block 0-31
write square[8][0].m = 0; ---> cache hit (address 2052)
write square[0][0].y = 0; ---> cache hit (address 2056)
.
.
.
你看到模式了吗? 1/8 操作将是缓存未命中。
未命中率: 12.5%
命中率: 87.5%