问答题 这道题测试考生预测C语言代码的高速缓存行为的能力,请考生对下面这段代码进行分析:
1 int x[2][256];
2 int i;
3 int sum==0;
4
5 for(i=0; i<256; i++){
6 sum+=x[0][i]*x[1][i];
7 }
假设在下列条件下执行这段代码:
·sizeof(int)==4。
·数组x从存储器地址0x0开始,按照行优先顺序存储。
·在下面每种情况中,高速缓存最开始时都是空的。
·唯一的存储器访问是对数组x的条目进行访问。其他所有变量都存储在寄存器中。
给定这些假设,请估算下列情况中的不命中率。
问答题 情况1:假设高速缓存是1024B,直接映射,高速缓存块大小为32B。不命中率是多少?
【正确答案】高速缓存大小为1024B,块大小为32B,那么块数为1024/32=32块。
x数组占用内存空间为4×2×256B=2048B,块数为2048/32=64块。
高速缓存无法一次性容纳下整个x数组。
数组x从存储器地址0x0开始,且采用直接映射的情况下,x数组的第i块映射到高速缓存的第i%32块,如图1所示。
[*]

图1 x数组的第i块映射到高速缓存的第i%32块

分析题目代码可知,系统依次访问x[0][0],x[1][0],x[0][1],x[1][1],…
而x[0][0],x[0][1],…,x[0][7]都在主存第0块,x[1][0],x[1][1],…,x[1][7]都在主存第32块。
所以系统等于是依次访问第0块、第32块、第0块、第32块、…
又第0块和第32块都映射到高速缓存的第0块,所以每次新访问的块将上次未命中而调入缓存的块挤出,使得所有情况都是未命中的。
其他块的情况也是一样的,所以未命中率为512/512=100%。
【答案解析】
问答题 情况2:如果把高速缓存的大小翻倍到2048B,不命中率是多少?
【正确答案】高速缓存大小为2048B,块大小为32B,那么块数为2048/32=64块。
x数组占用内存空间为4×2×256B=2048B,块数为2048/32=64块。
高速缓存能一次性容纳下整个x数组。x数组的第i块映射到高速缓存的第i块,如图2所示。
[*]

图2 x数组的第i块映射到高速缓存的第i块

与1)类似,系统等于是依次访问第0块、第32块、第0块、第32块、…
但各个块都各有其所,不会发生冲突现象,所以未命中都是冷不命中。
即x[0][0],x[1][0],x[0][1],x[1][1],…,x[0][7],x[1][7]。
只有最开始访问x[0][0]和x[1][0]时发生未命中,其他情况下都命中。
其他块的情况也是一样的,所以未命中总次数为1×64,未命中率为64/512=12.5%。
【答案解析】
问答题 情况3:现在假设高速缓存是1024B,2路组相联,使用LRU替换策略,高速缓存块大小为32B,不命中率是多少?
【正确答案】高速缓存块数为32块,2路组相联,则组数为32/2=16组。
x数组的第i块映射到高速缓存的第i%16组,如图3所示。
[*]

图3 x数组的第i块映射到高速缓存的第i%16组

与情况1类似,系统依次访问第0块、第32块、第0块、第32块、…
第0块和第32块都是映射到第0组,但由于每组有2块,不发生冲突,因此未命中也都是冷不命中。
其他块的情况也一样。所以不命中率为64/512=12.5%。
【答案解析】
问答题 对于情况3,更大的高速缓存大小会帮助降低不命中率吗?为什么能或者为什么不能?
【正确答案】不能,此时增加高速缓存大小,只是多增加高速缓存的组数而已,而冷不命中只跟块大小相关。所以更大的高速缓存大小不会帮助降低不命中率。
【答案解析】
问答题 对于情况3,更大的块大小会帮助降低不命中率吗?为什么能或者为什么不能?
【正确答案】能,通过增加块大小可以降低不命中率。不命中只发生在访问块的第一个元素时,剩下都命中,所以块越大,不命中率越低。
【答案解析】