关于CSAPP 6.18的习题分析
下面的站点能找到我搜集的所有和CSAPP有关的学习资料.
https://github.com/jasonleaster/CSAPP
问题背景:
强调一下,问题的针对性很强.在这个题目里面,cache究竟遵循什么策略就是这个题目定的.
其他的策略如果题目没说明,不考虑!题目旨在很简明而要的告诉读者替换策略的一种实现而已.
说明了int 的大小是4 byte.这里假设了src 从地址0开始储存, src和dst大小都是是16 bytes,那么 dst的起始地址就是 0x10. 这里只有一级缓存, CPU下面就是一层cache,再往下就是 main memory了.
There is a single L1 data cache that is direct-mapped, write-through, and write-allocate, with a block size of 8 bytes.
题目假设规定了,cache的每个操作都是以 8 byte进行了.
一开始的时候, cache里面啥也没有.每当我们试图去访问某个变量的时候,我们会先访问cache,看看里面有没有个备份,因为访问cache的速度和访问内存的速度两种不是一个数量级的.
法则:
如果cache里面有,那么hit.我们就可以直接读取使用这个数据在cache里面的备份.
如果cache里面没有,从main memory去读取数据,写入到cache中.再从cache中立马读取这个数据.
对于A问:
这里重要的就是自己要画个图出来方便理解.答案里面有了.
对应的你能看到src从0x00开始,dst从0x10开始.
src的前8byte数据和 dst前8 byte数据都会落在 line 0中.
src的后8byte和dst的后八个字节会落在 line 1中.
dst[ j ][ i ] = src[ i ] [ j ].
运行程序前假设cache里什么都没有空数据
cache里面 line 0 装的是 NULL NULL
line 1 装的是 NULL NULL
i = 0; j = 0;
读取 src[0][0], 第一次访问cache空的 src[0][0] miss.把 src[0][0] src[0][1]都拷贝到cache里去
cache里面 line 0 装的是 src[0][0] src[0][1]
line 1 装的是 NULL NULL
赋值操作要求写入到dst[0][0] ,访问cache,此时cache里面有dst嘛?没有.line 0 装的 src,line 1空着.
dst的前8 bytes和 src的前 8 bytes冲突,于是这个时候,把在cache里面的src[0][0] src[0][1]写回内存.
然后再把dst拷贝到cache line 0.
cache里面 line 0 装的是 dst[0][0] dst[0][1]
line 1 装的是 NULL NULL
结论: src[0][0] miss dst[0][0] miss
如果以上没看懂就反复看,因为上面看不懂下面绝壁白搭...
i = 0; j = 1;
读取src[0][1], .和之前第一次赋值操作结束后的cache一样.
由于这时候cache里面的情况是 line 0 装的dst前8 bytes line 1 空着.
读取src[0][1]又和cache里现有数据dst冲突,于是又把dst写回到内存,把内存里卖弄的src[0][0] src[0][1]读取到cache line 0. src[0][1] miss
cache里面 line 0 装的是 src[0][0] src[0][1]
line 1 装的是 NULL NULL
开始赋值操作.需要写入的是 dst[1] [0] , 这里需要访问 line 1,line 1此时是空的.于是 dst[1][0] miss.把dst后8 bytes读取到cache的 line 1
结论: src[0][1] miss dst[1][0]
赋值操作完成后
此时 cache里面 line 0 装的是 src[0][0] src[0][1]
line 1 装的是 dst[1][0] dst[1][1]
i = 1; j = 0;
读取src[1][0], miss 而且和line 1的dst冲突,需要把dst写回到内存.然后读取src[1][0] src[1][1]到cache
此时 cache里面 line 0 装的是 src[0][0] src[0][1]
line 1 装的是 src[1][0] src[1][1]
开始赋值操作.需要写入的是 dst[ 0 ] [ 1 ] , 这里需要访问 line 0,line 0此时是非空的.冲突,里面装着src. 于是把line 0的数据写回内存.把dst[0][0] dst[0][1]读取到cache.
此时 cache里面 line 0 装的是 dst[0][0] dst[0][1]
line 1 装的是 src[1][0] src[1][1]
赋值操作.
结论: src[0][1] miss dst[1][0] miss
i = 1; j = 1;
读取src[1][1], hit cache里面有上次赋值操作后被缓存的src[1][1],
此时 cache里面 line 0 装的是 src[0][0] src[0][1]
line 1 装的是 src[1][0] src[1][1]
开始赋值操作.需要写入的是 dst[ 1 ] [ 1 ] , 这里需要访问 line 1,line 1此时是非空的.冲突 miss,里面装着src. 于是把line 1的数据写回内存.把dst[1][0] dst[1][1]读取到cache.
此时 cache里面 line 0 装的是 src[0][0] src[0][1]
line 1 装的是 dst[1][0] dst[1][1]
赋值操作.
结论 结论: src[1][1] hit dst[1][1] miss
对于B嘛:
注意 , 这里只改变了cache的大小,cache每次读取写入的数据大小还是没变.8 byte
@LeDy 看下面这个图,分析方法还是和前面一样,掌握方法,就能自己分析了.