perflab实验报告(CSAPP)

更新时间:2024-01-29 04:25:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Perflab优化实验

【实验目的】

理解编译器,学习程序优化,从优化程序代码和程序执行速度两方面着手。

【实验原理】 通过循环展开、cache友好、替换变量等手段来实现程序优化。

【实验内容】

将下载下来的kernels.c中的rotate、smooth函数进行优化。

【操作界面】

从网上下载了SSH Secure Shell Client和SSH Secure File Transfer Client代替Putty作为实验平台,可以方便的进行文件上传与下载,所以此次实验以本地编辑文件,再上传覆盖原文件运行为主。软件界面如下:

通过在SSH Secure Shell Client将压缩包解压之后,可以直接通过SSH Secure File Transfer Client下载所需要的kernels.c文件,无需通过cmd输入长指令进行下载。

改好的kernel.c也只需通过SSH Secure File Transfer Client,右击upload即可。

【程序优化】

1. Naive_rotate

1-1.原始代码

char naive_rotate_descr[] = \void naive_rotate(int dim, pixel *src, pixel *dst) {

int i, j;

for (i = 0; i < dim; i++)

for (j = 0; j < dim; j++) dst[RIDX(dim-1-j, i, dim)] = src[RIDX(i, j, dim)]; }

1-2.分析

这段代码的作用就是将所有的像素进行行列调位、导致整幅图画进行了90度旋转。P从defs.h中可以找到 #define RIDX(i,j,n) ((i)*(n)+(j)) 。

代码从阅读性上来说,这段代码非常具有可读性,但是,从cache友好性来说,这段代码则显得难以接受。所以考虑到cache的大小,应在存储的时候进行32个像素依次存储(列存储)。这样可以做到cache友好、可以大幅度提高效率。

1-3.优化代码

char rotate_descr[] = \void rotate(int dim, pixel *src, pixel *dst) {

int i, j;

int dst_base = (dim-1)*dim; dst += dst_base;

for (i = 0; i < dim; i+=32){ for (j = 0; j < dim; j++){

*dst=*src;src+=dim;dst++; //共31组 *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++;

*dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src+=dim;dst++; *dst=*src;src++; src-=(dim<<5)-dim; //src -= 31*dim dst-=31+dim; }

dst+=dst_base+dim; dst+=32;

src+=(dim<<5)-dim; //src +=31*dim } }

2. Naive_smooth

2-1. 原始代码

void naive_smooth(int dim, pixel *src, pixel *dst){ int i, j;

for (i = 0; i < dim; i++) {

for (j = 0; j < dim; j++) {

dst[i*dim+j] = avg(dim, i, j, src); } } }

2-2.分析

这段代码频繁地调用avg函数,并且avg函数中也频繁调用initialize_pixel_sum 、accumulate_sum、assign_sum_to_pixel这几个函数,且又含有2层for循环,而我们应该减少函数调用的时间开销。所以,需要改写代码,不调用avg函数。

Smooth函数处理分为4块,一为主体内部,由9点求平均值;二为4个顶点,由4点求平均值;三为四条边界,由6点求平均值。从图片的顶部开始处理,再上边界,顺序处理下来,其中在处理左边界时,for循环处理一行主体部分,于是就有以下优化的代码。

2-3.优化代码

char smooth_descr[] = \void smooth(int dim, pixel *src, pixel *dst) { int i,j; int dim0=dim; int dim1=dim-1; int dim2=dim-2;

pixel *P1, *P2, *P3; pixel *dst1; P1=src; P2=P1+dim0; //左上角像素处理 dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red)>>2; dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green)>>2; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue)>>2; dst++; //上边界处理 for(i=1;ired=(P1->red+(P1+1)->red+(P1+2)->red+P2->red+(P2+1)->red+(P2+2)->red)/6; dst->green=(P1->green+(P1+1)->green+(P1+2)->green+P2->green+(P2+1)->green+(P2+2)->green)/6; dst->blue=(P1->blue+(P1+1)->blue+(P1+2)->blue+P2->blue+(P2+1)->blue+(P2+2)->blue)/6; dst++; P1++; P2++; } //右上角像素处理 dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red)>>2; dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green)>>2; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue)>>2; dst++; P1=src; P2=P1+dim0; P3=P2+dim0; //左边界处理 for(i=1;ired=(P1->red+(P1+1)->red+P2->red+(P2+1)->red+P3->red+(P3+1)->red)/6; dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green+P3->green+(P3+ 1)->green)/6; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue+P3->blue+(P3+1)->blue)/6; dst++; dst1=dst+1; //主体中间部分处理 for(j=1;j

dst->red=(P1->red+(P1+1)->red+(P1+2)->red+P2->red+(P2+1)->red+(P2+2)->red+P3->red+(P3+1)->red+(P3+2)->red)/9;

dst->green=(P1->green+(P1+1)->green+(P1+2)->green+P2->green+(P2+1)->green+(P2+2)->green+P3->green+(P3+1)->green+(P3+2)->green)/9;

dst->blue=(P1->blue+(P1+1)->blue+(P1+2)->blue+P2->blue+(P2+1)->blue+(P2+2)->blue+P3->blue+(P3+1)->blue+(P3+2)->blue)/9;

dst1->red=((P1+3)->red+(P1+1)->red+(P1+2)->red+(P2+3)->red+(P2+1)->red+(P2+2)->red+(P3+3)->red+(P3+1)->red+(P3+2)->red)/9;

dst1->green=((P1+3)->green+(P1+1)->green+(P1+2)->green+(P2+3)->green+(P2+1)->green+(P2+2)->green+(P3+3)->green+(P3+1)->green+(P3+2)->green)/9;

dst1->blue=((P1+3)->blue+(P1+1)->blue+(P1+2)->blue+(P2+3)->blue+(P2+1)->blue+(P2+2)->blue+(P3+3)->blue+(P3+1)->blue+(P3+2)->blue)/9; dst+=2;dst1+=2; P1+=2;P2+=2;P3+=2; } for(;j

dst->red=(P1->red+(P1+1)->red+(P1+2)->red+P2->red+(P2+1)->red+(P2+2)->red+P3->red+(P3+1)->red+(P3+2)->red)/9;

dst->green=(P1->green+(P1+1)->green+(P1+2)->green+P2->green+(P2+1)->green+(P2+2)->green+P3->green+(P3+1)->green+(P3+2)->green)/9;

dst->blue=(P1->blue+(P1+1)->blue+(P1+2)->blue+P2->blue+(P2+1)->blue+(P2+2)->blue+P3->blue+(P3+1)->blue+(P3+2)->blue)/9; dst++; P1++;P2++;P3++; } //右侧边界处理 dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red+P3->red+(P3+1)->red)/6;

dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green+P3->green+(P3+1)->green)/6; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue+P3->blue+(P3+1)->blue)/6; dst++; P1+=2; P2+=2; P3+=2; }

//左下角处理

dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red)>>2;

dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green)>>2; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue)>>2;

dst++;

//下边界处理 for(i=1;ired=(P1->red+(P1+1)->red+(P1+2)->red+P2->red+(P2+1)->red+(P2+2)->red)/6;

dst->green=(P1->green+(P1+1)->green+(P1+2)->green+P2->green+(P2+1)->green+(P2+2)->green)/6;

dst->blue=(P1->blue+(P1+1)->blue+(P1+2)->blue+P2->blue+(P2+1)->blue+(P2+2)->blue)/6; dst++; P1++; P2++; }

//右下角像素处理

dst->red=(P1->red+(P1+1)->red+P2->red+(P2+1)->red)>>2;

dst->green=(P1->green+(P1+1)->green+P2->green+(P2+1)->green)>>2; dst->blue=(P1->blue+(P1+1)->blue+P2->blue+(P2+1)->blue)>>2; }

于是最终得到:

附分路并行的各种结果: 1)不分

2)分2路

3)分3路

4)分4路

分路并行,并不是分路越多越好,执行加法和除法的功能单元是流水化操作的,而他们的个数也有限,超过其最大负荷也会让程序执行速率减慢。

【实验心得】

通过本次实验,我理解了代码优化的一些手段,编写出更具效率的代码。然而更重要的是更好地理解了计算机的工作原理,使我们以后编写代码的时候具有能结合硬件思考的能力。

本文来源:https://www.bwwdw.com/article/a9ew.html

Top