第一类问题对比:
块大小16B,int型数据占4B,所以一个Cache块可以放4个数组,所以访问1个数组,后面3个数组的地址可以在同一个Cache块找到。
一个数组要访问2次,即读这个数组,然后给这个数组赋值,4个数组访问次数8次,第1次cache缺失了,所以缺失率1/8=12.5%
注:如果操作改为a[k]=32,那么只需要给数组赋值即可,也就是1个数组访问1次。
第二类问题对比:
只讲Cache缺失率问题
数组a按行存放,程序 A 按行存取。每个Cache块中存放 16 个 int 型数据(64B/4B=16B),除访问的第一个不命中外,随后的15个全都命中,因此程序 A的命中率为15/16=93.75%。
程序 B 逐列访问数组 a,Cache 总数据容量为 64Bx 8 =512B,数组a一行的大小为 1KB,正好是 Cache 容量的2倍,可知不同行的同一列数组元素使用的是同一个 Cache 单元(因为采用直接映射),因此逐列访问每个数据时,都会将之前的主存快置换出,即每次访问都不会命中,命中率为0。
对比下面这道题:
这里的代码,同样都是将按行访问,变为按列访问,但是对于本题:
如果按行优先访问,Cache大小32B,数组大小4B,所以一个Cache块可以装4个32/4=8个数组,访问第一个数组不命中,剩下的数组命中,即:7/8=87.5%
按列访问同样是87.5%,为什么?
这里采用的是4路组相联映射,数据区8KB,Cache块大小32B,总共256块Cache块。那么有256/4=64组。由于按行优先存放,映射方式:
第一个主存块放在第1组,第二个主存块放在第2组....,相邻的主存块都是放在不同的Cache组中,即放在不同的Cache块中。
这里特别注意,由于数组大小为24*64*4B。轮流放一轮Cache组,也就是将64个主存块放到64个Cache组中,大小为64*32B:
64*32B*3=24*64*4B
所以数组论着放3论的Cache组,就可以放完。4路组相联,所以中间不会出现换入换出的情况。
对比上面说的那道题:
每访问同列不同行的数据,都需要将之前的主存块置换出去,而这里并没有换出的情况,虽然是按列访问,即a[0][0],a[1][0],两个在不同的Cache块中,但是当访问到a[0][1]的时候,我仍然可以找到Cache,因为访问a[0][0]时,已经将这个主存块调到Cache中了。
所以可以看到,影响命中率:
① 第一次调入的情况会影响命中率
② 调出的情况也会影响命中率,像第一道题,按列访问,每次都要将主存块调出,所以命中率为0。
由于两道题都出现了需要算某个数组虚拟地址的情况,提供个解题思路:
例如最后一道题:a[1][0],前面有64个元素,大小64B*4=2^8B=256B,页大小为4KB,所以a[0][0]与a[1][0]在同一页,虚页号不变:00422;偏移量就是64*4=2^8B,那么只需要在:
a[0][0]=00422000H中"000H"的基础上,2^8处修改为"1"即可:
0000 0000 0000---->0001 0000 0000=100H
所以两个拼起来,虚拟地址:00422100H