CSAPP lab8 Cache

考虑到能看到这篇文章的基本都是“同道中人”了,我就开门见山地写东西不过多介绍了。。这次lab主要考察的是cache的内容,Part A要求用LRU规则模拟Cache,Part B则是将代码优化成Cache-Friendly-Code。。体感难度是下下位吧,不耗时间但是略吃智力,P-B优化想不出来可能就没戏了系列。。废话不多说。上效果图:


Part A

主要的坑是“禁止warning”,因为编译条件是-Werror,所以频繁使用位运算(<<或者>>)可能会碰一些钉子。

LRU的实现有两个思路:
1、采用全局时间参数,在全局弄个变量标记流程的进度(比如运行到第几条指令了),然后赋给你自己设计的缓存,和tag绑定,这样的话遇到缓存更新的时候就可以判断剔除哪个元素了。
2、采用模拟队列(我采用的方法),说是队列其实就是个列表.jpg,每次miss的时候更新对应set中的tag list,全部后移一个单位,然后把新的放到[0]的位置,当然这个方法很容易忽略hit的时候,hit的时候同样也需要更新这个list,把命中的tag丢到列表最前面

总之。。题目只有正确性要求,没有效率要求,尽情遍历列表吧.jpg

Part B

这个部分主要是让学生优化一个矩阵转置算法,让它变得更加亲民(亲近缓存),具体讲就是要 减少Cache Miss的数量。

Cache的规格为s=5(也就是32个set),每个set都是单行的,每行可以存8个元素(8 elements/line),题设的输入规格是32*32,64*64,61*67三种

第一眼审题,61*67什么玩意儿,太难了玩不了;做下去就会发现,64*64是最大的难点,61*67这种奇怪的规格给的容错反而很大。

先做作为铺垫的32*32:
M=32,N=32
如果把矩阵和set的对应关系画出来的话,策略是一目了然的(据说书上也有),如图,每个格子代表8个int,对应数字表示对应的set

显然的,我们使用矩阵分块策略,以8*8为单位,完成一个一个小矩阵的转化,可以发现,基本上,原始的小矩阵和目标的小矩阵都完全在cache里了,当然减少了很多的冲突。然而单单这样并没有达到满分的要求(
还有一步重要的优化核心在对角线,因为可以发现,对角线上的元素赋值时会造成缓存切换,这将会造成一部分的miss,不过我们可以用题中所说的“额外变量”来解决这个问题!(代码最后一起附)
M=61,N=67
其实做完了上面那个,分块的思想就已经浮出水面了,正激动,就出个质数相乘,导致分块并没有这么满足强迫症,不过由于题目给的Miss上限实在是过分高了,我试了一两种分块并调整了一下遍历顺序以后就莫名其妙满分了。。所以我也不知道写啥,略过了吧.jpg。
M=64,N=64
乍一看以为是32的翻版,可以一以贯之,然而并不是这样。。

很容易可以发现,新的8*8矩阵自己就已经产生了Cache Conflict,老办法当然就行不通了,用4*4的话浪费了Cache Block的大小,显然不是明智之举。好在题目给的提示非常清晰, “你可以对目标矩阵做任何你想做的事情”,并且,题目仅仅统计Miss的数量,也就是说,多于的hit并不会影响你的分数,那么!

首先先不考虑对角线的8*8们,考虑别的地方的转置,转置涉及到纵横的变化,所以很容易会造成连续访问不同的set,会造成极大的Miss数量,我介绍一下我的处理方法。

注意到因为不在对角线上,所以原始和目标的8*8分别使用两批set,互相不产生冲突,只需要考虑自身如何高效利用缓存即可

第一步:将原始矩阵的上半包含的两个4*4方阵分别转置放入目标矩阵

第二步:将原始8*8矩阵的缓存区挪到下面(不使用上面了),然后完成目标8*8的填值(一定要逐行,不然会造成大量Miss)

第三步:你发现对角线完蛋了,单靠上面的优化完不成满分,不过,如果把对角线先做完,就会简单很多很多,所以,
(划去上面)第1.5步:处理对角线的8*8们

由于对角线上的8*8原始矩阵和目标矩阵都公用一套set,所以会很麻烦,但是,因为我们先做对角线,所以所有其他的缓存,统统是可以使用的!

那,就直接去别的地方拆两个4*8出来当临时变量即可,相当于缓存的其他部分全部都是你可以用的临时变量了!(这个方法同样也可以用来优化上面的情况,不过因为是后想到的所以就这样子了,没有实际测试)



void transpose_submit(int M, int N, int A[N][M], int B[M][N])
{
    int i,j,p,q;
    int t1,t2,t3,t4;//t5,t6,t7,t8;
    if (M==32){
        for (i=0;i<4;i++){
            for (j=0;j<4;j++){
                for (p=0;p<8;p++){
                    for (q=0;q<8;q++){
                        if (8*i+q==8*j+p){
                            t1 = A[8*i+q][8*j+p];//avoid same row conflict
                            t2 = 8*i+q;
                        }else{
                            B[8*i+q][8*j+p]=A[8*j+p][8*i+q];
                        }
                    }
                    if (i==j){
                        B[t2][t2] = t1;//set back        
                    }
                }
            }
        }
    }else if (M==61){
        for (j=0;j<5;j++){
            for (i=0;i<5;i++){
                for (p=0;p<16 && (16*i+p)<61;p++){
                    for (q=0;q<16 && (16*j+q)<67;q++){
                        if (16*i+p==16*j+q){
                            t1 = A[16*i+p][16*j+q];//avoid same row conflict
                            t2 = 16*i+p;
                        }else{
                            B[16*i+p][16*j+q]=A[16*j+q][16*i+p];
                        }
                    }
                    if (i==j){
                        B[t2][t2] = t1;//set back        
                    }
                }
            }
        }
    }else if (M==64){
        for (i=0;i<64;i+=8){
            // dui jiao xian
            for (p=0;p<4;p++){
                for (q=0;q<8;q++){
                    B[p][q+8] = A[i+p][i+q];
                }
                for (q=0;q<8;q++){
                    B[p][q+16] = A[i+p+4][i+q];
                }
            }
            for (p=0;p<4;p++){
                for (q=0;q<4;q++){
                    B[i+p][i+q] = B[q][p+8];
                    B[i+p][i+q+4] = B[q][p+16];
                }
                for (q=0;q<4;q++){
                    B[i+p+4][i+q] = B[q][p+12];
                    B[i+p+4][i+q+4] = B[q][p+20];
                }
            }
        }
        for (i=0;i<64;i+=8){
            for (j=0;j<64;j+=8){
                //[i][j] a 8*8 block
                if (i!=j){
                    //not special 8 blocks
                    for (q=i;q<i+4;q++){
                        for (p=j;p<j+4;p++){
                            B[p][q] = A[q][p];//convert 4*4
                            B[p][q+4] = A[q][p+4];//convert 4*4 in a temp place on right
                        }
                    }
                    for (p=j;p<j+4;p++){
                        t1 = B[p][i+4];
                        t2 = B[p][i+5];
                        t3 = B[p][i+6];
                        t4 = B[p][i+7];// save temp before cache tag change
                        B[p][i+4] = A[i+4][p];
                        B[p][i+5] = A[i+5][p];
                        B[p][i+6] = A[i+6][p];
                        B[p][i+7] = A[i+7][p];// correct the temp B line
                        B[p+4][i] = t1;
                        B[p+4][i+1] = t2;
                        B[p+4][i+2] = t3;
                        B[p+4][i+3] = t4;// replace temp line and change cache tag
                        for (q=i;q<i+4;q++){
                            B[p+4][q+4] = A[q+4][p+4];// normal convert
                        }
                    }
                }
            }
        }
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值