CSAPP LAB4 perflab-handout性能优化 smooth负优化详解

本文介绍了CSAPP实验第四部分关于性能优化的实践,重点讲解了如何消除循环中的低效率、减少函数调用等优化方法,并以`naive_smooth`函数为例,展示了如何通过消除`avg`函数中的循环低效率进行优化。通过添加边框避免边界条件判断,实现了负优化,将加速比降低到7.6,以此探讨优化策略的影响。
摘要由CSDN通过智能技术生成


在优化代码之前,首先要知道我们有哪些方法可以优化性能?

翻书!把教材翻到目录,第五章赫然写着优化方法:

1、使用内联函数。一种替换代码方法,尽可能减少函数调用;

2、消除循环中的低效率。比如说for循环判断里面带了个函数,那么就属于低效率的循环,从时间复杂度上面也能分析;

3、减少过程调用。比如说经常需要先取数,再操作,那么优化的方法通常是把这些数安排在连续的地址里面,这样可以减少地址的计算;

4、消除不必要的存储器引用。在看书之前,我认为是减少局部变量的定义,毕竟定义一个变量就要占一个寄存器,但是书上的意思是尽量拿一个变量专门用来做某一件特定的事情,举个例子,inti就是用来for循环的,不要再拿来做计数器或者权值计算器了,如果要统计和,就应该再定义一个sum,避免汇编代码层次中,要额外使用一个寄存器临时保存变量的值。

5、循环展开。减少for循环的步长,每一次循环,尽可能的让cpu做更多的运算,提高并行性,充分发挥流水的作用。

 

这个实验妙处在于可以融合以上所有优化方法,容我慢慢道来~

 

首先看smooth函数initial版本:

char naive_smooth_descr[] = "naive_smooth: Naive baselineimplementation";
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[RIDX(i, j, dim)] =avg(dim, i, j, src);
}

首先要明白RIDX(i,j, dim)是什么?

在头文件def.h中,写着#defineRIDX(i,j,n) ((i)*(n)+(j))

这是我们平时不常接触的函数型宏定义,传入i和j还有n,就计算出(i)*(n)+(j),这是dst的地址。

作为一个二维的图片,通常是用二维数组存储的,但是二维数组在内存中依然是连续的物理地址。可以把dst[RIDX(i,j, dim)] 直接理解为二维数组a[i][j]。

然后问题来了,avg(dim,i, j, src) 又是什么?直觉告诉我它是一个函数!

果然在同一个文件下面找到了这个函数:

static pixel avg(int dim, int i, int j, pixel *src) //因为缺点出于函数内部,所以这个函数无法使用
{
    int ii, jj;
    pixel_sum sum;
    pixel current_pixel;


    initialize_pixel_sum(&sum);
    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++) 
             accumulate_sum(&sum,src[RIDX(ii, jj, dim)]);


    assign_sum_to_pixel(&current_pixel, sum);
    return current_pixel;
}

这个函数有个问题:

就是循环中的低效率!       max(i-1, 0) 和min(i+1, dim-1)都是函数,每次for循环判断条件的时候,都要调用函数min(i+1, dim-1),所以我们首先想到的是消除循环中的低效率。

但是,这个for循环被封装在avg函数里面了,怎么办?只能放弃这个函数了,我们自己写函数。

我们首先看计算像素点平均颜色是如何计算的?

static void accumulate_sum(pixel_sum *sum, pixel p) //统计颜色数据
{
    sum->red += (int) p.red;
    sum->green += (int) p.green;
    sum->blue += (int) p.blue;
    sum->num++;
    return;
}

static void assign_sum_to_pixel(pixel *current_pixel, pixel_sumsum) //计算平均值
{
    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);
    return;
}

通过以上两个函数,我们看到了原理,就是把相邻的像素点的RGB颜色各取平均值。

 

现在开始负优化啦~~~

对于32*32的图片,关键是要对四个角以及边框进行讨论。如何避免讨论呢?在迷宫问题中,解决方法就是在它的外面加一个边框。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值