我试图弄清楚如何计算阵列的未命中率。我有答案,但我不明白答案是如何得出的。 我有以下代码:
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
。有人可以向我解释他们是如何在这里完全失败的吗?
答案 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
我知道这与问题中指出的不同。我无法弄清楚如何。我很乐意听到其他答复。