csapp 2e cachelab

part 1

这部分主要是LRU的问题,我是通过维护双向链表来模拟的:

1.每当一个缓存被命中或者新加入时,将该缓存移到链表头。

2.当新加入缓存且链表个数到达上限时,需删除链表尾的节点,新结点放到链表头。


part 2

只解决了64*64的矩阵转置,耗费了我两天时间,其余问题感觉意义不大,实用性也不强,懒得做了。

因为s=5,E=1,b=5,所以对于64*64的矩阵, 第一行和第五行的元素是命中的同一块缓存,依此类推。所以块大小取8*8,实际在完成一个8*8的块的转置时,还需再分为4*4的小块。

问题主要分为两部分:
1.位于对角线的块。
2.不位于对角线的块。

先解决对角线的块:
先复制到B矩阵的非对角线的块区域,再由非对角线块转置到目的块。
转置的过程类似于非对角线块的解决办法。
从A块复制到B的非对角线块---16miss
从B非对角线块转置到对角线块---16miss
总计32miss
对角线块一共有8个,那就是8*32=256,题目的上限是1100
而非对角线块总共有56个,因此每个非对角线块的miss上限最多为18个。
非对角线的块:
对于非对角线的块,A矩阵与B矩阵中的相应块是不会占用同一块缓存的。

步骤如下(分为4个4*4小块):
1.转置左上角的小块到目的块,完成时A、B中右上角的小块已经位于缓存中。
2.将A中右上角的小块转置并存储到B右上角的小块(做容器用)中。完成时,A的左上角和右上角的小块没用了。
3.将B右上角中第一行的四个值赋值给四个临时变量,再从A中取相应的值转置到这一行中。完成时,B第一行已被填满,可以退出缓存了。
4.将临时变量的值赋值到相应位置(即第五行前四个坑,B的左下小块第一行).
重复3、4,直到完成B左下小块的转置。
5.将A右下小块转置到B右下小块中。

总计是16个miss,充分利用了缓存(实在繁琐,不知道各位大神有没有简便的方法。)

在虚拟机上跑的结果是总计1155个miss:

代码如下:
void transpose_submit(int M, int N, int A[N][M], int B[M][N])
{
	if(N<16 || M<16){
		trans(M, N, A, B);
	}
	
	int m, n;
	int i, j;
	int tem, tem2;
	int col,row;
	int t1,t2,t3,t4;
	
	
	//diagonal block
	tem = M < N ? M : N;
	for(n=0;n+8<=tem;n+=8){
		if(n>tem-16){// last block
			row = n;
			col = n - 8;
		}else{
			row = n;
			col = n + 8;
		}
		
		//copy A diagonal block to B's block
		for(i=0;i<8;i++){
			for(j=0;j<8;j++){
				B[row+i][col+j] = A[n+i][n+j];
			}
		} 
		
		//Transpose copied block to B's diagonal block				
		for(i=0;i<4;i++){
			for(j=0;j<4;j++){
				B[n+i][n+j] = B[row+j][col+i];
				B[n+i][n+j+4] = B[row+i][col+j+4];						
			}
		}
		
		for(i=0;i<4;i++){
			for(j=0;j<4;j++){
				tem2 = B[row+4+i][col+j];
				B[row+4+i][col+j] = B[n+j][n+i+4];
				B[n+j][n+i+4] = tem2;
			}
		}
		
		for(i=0;i<4;i++){
			for(j=0;j<4;j++){
				B[n+4+i][n+j] = B[row+4+i][col+j];
				B[n+4+i][n+4+j] = B[row+4+j][col+4+i]; 
			}
		}
	}
	// end
	
	for(n=0;n+8<=N;n+=8){
		for(m=0;m+8<=M;m+=8){
			if(m!=n){
				for(i=0;i<4;i++){
					for(j=0;j<4;j++){
						row = n + i;
						col = m + j;
						B[col][row] = A[row][col];
						B[col][row+4] = A[row][col+4];						
					}
				}
				
				for(i=0;i<4;i++){
					row = m + i;
					t1 = B[row][n+4];
					t2 = B[row][n+5];
					t3 = B[row][n+6];
					t4 = B[row][n+7];
					
					row = n + 4;
					col = m + i;
					for(j=0;j<4;j++){
						B[col][row+j] = A[row+j][col];
					}
					
					row = m + 4 + i;
					B[row][n] = t1;
					B[row][n+1] = t2;
					B[row][n+2] = t3;
					B[row][n+3] = t4;
				}
				
				for(i=0;i<4;i++){
					for(j=0;j<4;j++){
						row = n + 4 + i;
						col = m + 4 + j;
						B[col][row] = A[row][col]; 
					}
				}
			}	
		}
		
		for(;m<M;m++){//边界条件处理,待优化
			for(j=0;j<8;j++){
				B[m][n+j] = A[n+j][m];
			}
		}
	}
	
	for(;n<N;n++){//边界条件处理,待优化
		for(j=0;j<M;j++){
			B[j][n] = A[n][j];
		}
	}

}

这个过不了61*67的,应该是因为边界条件没好好处理(即对于矩阵分块后的边角料),懒得处理了,网上应该有正确解答的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值