缓存未命中率的数组

时间:2012-11-28 18:34:19

标签: caching cpu-cache

我试图弄清楚如何计算阵列的未命中率。我有答案,但我不明白答案是如何得出的。 我有以下代码:

int C[N1][N2];
int A[N1][N3];
int B[N3][N2];

initialize_arrays(A, B, C, N1, N2, N3);

for(i=0; i<N1; ++i)
   for(j=0; j<N2; ++j)
      for(k=0; k<N3, ++k)
         C[i][j] += A[i][k] * B[k][j];

我还有以下信息:N1=N2=N3=2048(这意味着什么?)。处理器具有32kB的L1数据高速缓存,线路大小为64B(无L2高速缓存)。 (什么是线条尺寸?)

我知道数组C的未命中率是(N^2/16)/N^3。我知道公式是(total misses)/(total accesses)。我看到总共有N^3次访问,但他们是如何获得完全未命中的?

我也知道数组B的未命中率:(N^3)/(N^3)和A:(N^2/16)/N^3。有人可以向我解释他们是如何在这里完全失败的吗?

1 个答案:

答案 0 :(得分:2)

始终使用行的粒度访问/管理缓存。这里的线条大小是64B。这意味着在一个缓存行中,一个缓存行中将有16个元素(64B / 4B = 16)。接下来重要的是每个第17个元素都在一个新行中,一旦一行被带到缓存,它可能会给出15次点击。

完成后,让我们看一下访问模式。     A [0] [0],B [0] [0],C [0] [0],A [0] [1],B [1] [0],C [0] [0],A [ 0] [2],B [2] [0],C [0] [0],...... A [0] [16],B [16] [0],C [0] [0 ],A [0] [17],B [17] [0],C [0] [0],......等等

现在由于一行有16个元素,可以安全地假设存储器中的元素的行主要位置A [0] [0] - A [0] [15]将属于第一个缓存行(让我们称之为AL1)并且类似地让B [0] [0] -B [0] [15]属于行BL1。根据这些信息,我们可以根据缓存行编写访问模式。     AL1,BL1,CL1,AL1,BL129,CL1,AL1,BL257,CL1,...... AL1,BL2049,CL1,AL2,BL2176,CL1,......等。

现在缓存大小为32kB,这意味着缓存可以容纳512行。由于这是L1,我们假设它是一个双向关联缓存。因此有256套。这意味着在每256行数组之后,第257行映射到与第1行相同的集合。

访问映射到第1组的行时的缓存内容如下所示

第一次迭代 - 内部

Access to - AL1 - Miss
 AL1 
Access to - BL1 - Miss
 AL1
 BL1
Access to - CL1 - Miss
 CL1
 BL1

第二次迭代 - 内在

Access to - AL1 - Miss
 CL1
 AL1
Access to - CL1 - Hit
 CL1
 AL1

第3次迭代 - 内部

Access to - AL1 - Hit
 CL1
 AL1
Access to - BL257 - Miss
 BL257
 AL1
Access to - CL1 - Miss
 BL257
 CL1

第四次迭代 - 内在

Access to - AL1 - Miss
 AL1
 CL1
Access to - CL1 - Hit
 AL1
 CL1

第五次迭代 - 内在

Access to - AL1 - Hit
 CL1
 AL1
Access to - BL513 - Miss
 BL513
 AL1
Access to - CL1 - Miss
 BL513
 CL1

。 。

第16次迭代 - 内部

Access to - AL1 - Miss
 AL1
 CL1
Access to - CL1 - Hit
 AL1
 CL1

17th Iteration - Inner

Access to - BL2049 - Miss
 BL2049
 CL1
Access to - CL1 - Hit
 BL2049
 CL1

第18次迭代 - 内在

Access to - CL1 - Hit
 BL2049
 CL1

对于中间循环的第一次迭代。我们有第1集,

A -> M, M, H, M, H, M, H, M, H, M, H, M, H , M, H, M, ~ , ~ , ~ , ~ , ....... 
=> after 2048 iterations - 7 hits 9 misses, 16 accesses

B -> M, ~ , M, ~ ,  M, ~ , ........
=> after 2048 iterations - 0 Hits, 1024 misses, 1024 accesses

C -> M, H, M, H, M, H, M, H, M, H, M, H, M, H, M, H, H , H, H , H, ......
=> after 2048 iterations - 2040 hits, 8 misses, 2048 accesses

第二次 - 中间循环的第16次迭代,

Exact hit / miss / access pattern as before.

中间循环的第17~2048次迭代,

A -> same as before
B -> No accesses
C -> No accesses

总结 - 对于外循环的1次迭代,我们得到集合1,

A -> N*9 misses , N * 16 accesses
B -> N/2 * 16 Misses , N/2 * 16 accesses
C -> 8 * 16 Misses , N * 16 accesses

在外部循环中,我们可以看到每个交替迭代将具有与数组C和A的第一次迭代(如上所述)相同的命中/未命中/访问模式。外部循环的每次迭代都将具有相同的命中/ miss / access pattern a阵列B的第一次迭代。

因此,(终于!)

对于第1组,在程序结束时,我们有

A -> N^2 * 9 / 2 misses, N^2 * 8 accesses
B -> N^2 * 8 misses, N^2 * 8 accesses
C -> N * 64 misses, N^2 * 8 accesses

所有集合的访问模式都类似。因此,在程序结束时,我们拥有所有集合

A -> N^2 * 1152 misses, N^3 accesses
B -> N^3 misses, N^3 accesses
C -> N^2 * 8 misses, N^3 accesses

我知道这与问题中指出的不同。我无法弄清楚如何。我很乐意听到其他答复。