在多维数组中查找缓存未命中/命中率

时间:2013-12-13 04:20:39

标签: arrays caching matrix-multiplication

我正在尝试研究测试,其中一个练习问题涉及计算缓存的“命中”和“未命中”率。我有问题的答案,但我无法弄清楚它背后的过程。

鉴于以下内容;

具有32字节块的2048字节直接映射数据高速缓存。 假设sizeof(int)== 4,Square从内存地址0开始, 缓存最初为空,变量i和j存储在寄存器中。

  struct point_color { 
  int c; 
  int m; 
  int y; 
  int k; 
  }; 

  struct point_color square[16][16]; 
  int i, j;

  for (i = 0; i < 16; i++){ 
  for (j = 0; j < 16; j++) { 
  square[i][j].c = 0; 
  square[i][j].m = 0; 
  square[i][j].y = 1; 
  square[i][j].k = 0; 
  } 
  } 

我正在尝试查找“缓存中遗漏的写入总数”和“未命中率”

到目前为止,我知道写入的总数是16 * 16 * 4 = 1024次,但在尝试查找缓存命中率和未命中率时,我完全丢失了。

1 个答案:

答案 0 :(得分:2)

  

具有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%