HNU计算机系统实验perflab3

此为本人在进行实验时所做的实验日志,仅供参考。这个应该是汇总版的实验报告,具体的忘了。

PART A
代码一:

void naive_rotate1(int dim,pixel *src,pixel *dst){
    int i,j,tmp;//设置一个中间变量tmp,用来存储中间值
    for(j=0;j

代码一说明:
这里是书上的第一个方法,消除循环的低效率。通过观察源代码可以发现在循环中对dim-1-j这个数据进行了重复的调用,所以这里可以对循环进行修改,将计算时的行列进行调换,可以提前计算dim-1-j,这样就可以省去每一次循环中重复计算的时间,可以很好的提高效率。

代码二:

void naive_rotate2(int dim,pixel *src,pixel *dst){
    int i,j,i1,j1;//将程序分成4*4的小块
    for(i1=0;i1

代码二说明:
通过划分成4*4的小方块对整个图进行划分,可以提高空间局部性,但当dim比较小的时候,反而会变慢,因为当dim比较小的时候,决定时间的主要因素是算法复杂度,而分块算法的复杂度比较高。

代码三:

void naive_rotate5(int dim, pixel *src, pixel *dst){
    int i,j,tmp1=dim*dim,tmp2=dim *31,tmp3=tmp1-dim,tmp4=tmp1+32,tmp5=dim+31;//定义中间变量
    dst+=tmp3;  
    for(i=0; i< dim; i+=32){         
        for(j=0;j

代码三说明:
将for循环进行展开,在每一次循环中尽可能多的做操作,以此来达到优化的目的。对于partA这是目前已有的办法中最好的办法。

PART B:
代码一:

void naive_smooth2(int dim, pixel *src, pixel *dst) 
{
    int i, j;
    for (i = 0; i < dim; i=i+4){
	for (j = 0; j < dim; j=j+4){//分块执行,每4*4为一块
	    dst[RIDX(i, j, dim)] = avg(dim, i, j, src);
	    dst[RIDX(i, j+1, dim)] = avg(dim, i, j+1, src);
	    dst[RIDX(i, j+2, dim)] = avg(dim, i, j+2, src);
	    dst[RIDX(i, j+3, dim)] = avg(dim, i, j+3, src);
	    dst[RIDX(i+1, j, dim)] = avg(dim, i+1, j, src);
	    dst[RIDX(i+1, j+1, dim)] = avg(dim, i+1, j+1, src);
	    dst[RIDX(i+1, j+2, dim)] = avg(dim, i+1, j+2, src);
	    dst[RIDX(i+1, j+3, dim)] = avg(dim, i+1, j+3, src);
	    dst[RIDX(i+2, j, dim)] = avg(dim, i+2, j, src);
	    dst[RIDX(i+2, j+1, dim)] = avg(dim, i+2, j+1, src);
	    dst[RIDX(i+2, j+2, dim)] = avg(dim, i+2, j+2, src);
	    dst[RIDX(i+2, j+3, dim)] = avg(dim, i+2, j+3, src);
	    dst[RIDX(i+3, j, dim)] = avg(dim, i+3, j, src);
	    dst[RIDX(i+3, j+1, dim)] = avg(dim, i+3, j+1, src);
	    dst[RIDX(i+3, j+2, dim)] = avg(dim, i+3, j+2, src);
	    dst[RIDX(i+3, j+3, dim)] = avg(dim, i+3, j+3, src);
	}
    }
}

代码一说明:
通过划分成4*4的小方块对整个图进行划分,可以提高空间局部性,但当dim比较小的时候,反而会变慢,因为当dim比较小的时候,决定时间的主要因素是算法复杂度,而分块算法的复杂度比较高。

代码二:

void naive_smooth5(int dim, pixel *src, pixel *dst){
    int i, j;
    int ii, jj;
    pixel_sum sum;
    pixel current_pixel;
    for (i = 0; i < dim; i++){
	for (j = 0; j < dim; j++){//avg函数展开,直接在主函数中使用
    	    sum.red = sum.green = sum.blue = sum.num = 0;
	    for(ii = max(i-1, 0); ii <= min(i+1, dim-1); ii++) 
		for(jj = max(j-1, 0); jj <= min(j+1, dim-1); jj++){ 
		    sum.red += (int) src[ii*dim+jj].red;
		    sum.green += (int) src[ii*dim+jj].green;
		    sum.blue += (int) src[ii*dim+jj].blue;
		    sum.num++;
		}
	    current_pixel.red = (unsigned short) (sum.red/sum.num);
	    current_pixel.green = (unsigned short) (sum.green/sum.num);
	    current_pixel.blue = (unsigned short) (sum.blue/sum.num);
	    dst[i*dim+j] =current_pixel;
	}
    }
}

代码二说明:
这里可以看到有一个交avg的函数被反复的调用了,所以这里我将这个函数直接放到了主函数中,免去了很多函数调用的时间,这种方法相对来讲是比较好的,但仍旧一般

代码三:

void naive_smooth8(int dim, pixel *src, pixel *dst){
    int i, j;
    pixel current_pixel;
    pixel_sum sum;
    sum.red = sum.green = sum.blue= 0;//左上角
    sum.red=src[0*dim+0].red+src[1*dim+0].red+src[0*dim+1].red+src[1*dim+1].red;    sum.green=src[0*dim+0].green+src[1*dim+0].green+src[0*dim+1].green+src[1*dim+1].green;
    sum.blue=src[0*dim+0].blue+src[1*dim+0].blue+src[0*dim+1].blue+src[1*dim+1].blue;
    current_pixel.red = (unsigned short) (sum.red/4);
    current_pixel.green = (unsigned short) (sum.green/4);
    current_pixel.blue = (unsigned short) (sum.blue/4);
    dst[0] =current_pixel;
    sum.red = sum.green = sum.blue= 0;//右上角
    sum.red=src[0*dim+dim-1].red+src[1*dim+dim-1].red+src[0*dim+dim-2].red+src[1*dim+dim-2].red;
    sum.green=src[0*dim+dim-1].green+src[1*dim+dim-1].green+src[0*dim+dim-2].green+src[1*dim+dim-2].green;
    sum.blue=src[0*dim+dim-1].blue+src[1*dim+dim-1].blue+src[0*dim+dim-2].blue+src[1*dim+dim-2].blue;
    current_pixel.red = (unsigned short) (sum.red/4);
    current_pixel.green = (unsigned short) (sum.green/4);
    current_pixel.blue = (unsigned short) (sum.blue/4);
    dst[dim-1] =current_pixel;
    sum.red = sum.green = sum.blue= 0;//左下角
    sum.red=src[(dim-1)*dim+0].red+src[(dim-2)*dim+0].red+src[(dim-1)*dim+1].red+src[(dim-2)*dim+1].red;
    sum.green=src[(dim-1)*dim+0].green+src[(dim-2)*dim+0].green+src[(dim-1)*dim+1].green+src[(dim-2)*dim+1].green;
    sum.blue=src[(dim-1)*dim+0].blue+src[(dim-2)*dim+0].blue+src[(dim-1)*dim+1].blue+src[(dim-2)*dim+1].blue;
    current_pixel.red = (unsigned short) (sum.red/4);
    current_pixel.green = (unsigned short) (sum.green/4);
    current_pixel.blue = (unsigned short) (sum.blue/4);
    dst[dim*dim-dim] =current_pixel;
    sum.red = sum.green = sum.blue= 0;//右下角
    sum.red=src[(dim-1)*dim+(dim-1)].red+src[(dim-2)*dim+(dim-1)].red+src[(dim-1)*dim+dim-2].red+src[(dim-2)*dim+dim-2].red;
    sum.green=src[(dim-1)*dim+(dim-1)].green+src[(dim-2)*dim+(dim-1)].green+src[(dim-1)*dim+dim-2].green+src[(dim-2)*dim+dim-2].green;
    sum.blue=src[(dim-1)*dim+(dim-1)].blue+src[(dim-2)*dim+(dim-1)].blue+src[(dim-1)*dim+dim-2].blue+src[(dim-2)*dim+dim-2].blue;
    current_pixel.red = (unsigned short) (sum.red/4);
    current_pixel.green = (unsigned short) (sum.green/4);
    current_pixel.blue = (unsigned short) (sum.blue/4);
    dst[dim*dim-1] =current_pixel;
    for (j=1;j

代码三说明:
这是最快的算法,将四个角(22),四条边(23),内部(3*3)进行分块计算,直接将avg函数去除,实际上如果再进行并行操作和展开,可能会更快,但如果从单个方法来说,这是最快的方法。

利用amdahl定律分析:
partA初始状态;
在这里插入图片描述
代码一优化:
在这里插入图片描述
代码二优化:
在这里插入图片描述
代码三优化:
在这里插入图片描述
可以看到对于part A影响最大的部分是for循环展开,这是因为part A 进行的是一个类似于“复制”的操作,上一次的操作结果不会影响到这次的运行结果,所以可以尽可能多的在依次循环中执行多次操作,这样就可以大大节约从寄存器中取值的时间。另一方面可以对行列的顺序进行交换,这样可以节约每次进行的算数计算的时间,同时因为数据在计算机中的存储方式的原因,如果先执行行再执行列,那么每次对一个数据进行复制的时候都要重新提取两个指针,而如果先执行列再执行行,那么就可以节约重新提取指针的时间,同样可以很强的优化。所以对于part A的优化方法中最有效的是变量提取和函数展开。

partB初始状态:
在这里插入图片描述
代码一优化:
在这里插入图片描述
代码二优化:
在这里插入图片描述
代码三优化:
在这里插入图片描述
可以看到对于part B影响最大的部分是avg函数去除。分块计算的效果对于part B影响并不是很明显,可能是因为part B是一个类似于“马赛克”的操作,这就导致了上一次的操作结果会影响到这一次的运行结果,所以操作与操作之间不是并行而是串行的关系,没有办法从增加for单次循环执行操作次数的操作来进行优化。而其原本的avg函数本身的效率并不高,所以只是将avg函数拿到主函数里面虽然可以起到优化的效果,但并不明显。
所以对于这个函数的优化思路应该从修改avg函数本身的方向入手。可以看到avg函数的思路是取九宫格,然后取整个九宫格的平均值给中间的格。而对于角、边的边界情况分别对应的是22和23的矩形,所以我们可以直接将整个avg函数进行修改,直接分成“四个角+四条边+中心内部”三个区域进行计算,从而省去了if条件判断的时间,最终可以达到极强的优化作用。

你可能感兴趣的:(计算机系统)