CSAPP:代码优化【矩阵运算】

博客园:https://www.cnblogs.com/ustca/p/11796896.html
编程除了使程序在所有可能的情况下都正确工作,还需要考虑程序的运行效率,上一节主要介绍了关于读写的优化,本节将对运算的优化进行分析。读写优化

编写高效程序需要做到以下两点:

  1. 选择一组合适的算法和数据结构
  2. 编写编译器能够有效优化以转换成高效可执行代码的源代码

第一点合适的算法和数据结构往往是大家写程序时会首先考虑到的,而第二点常被忽略。这里我们就代码优化而言,主要讨论如何编写能够被编译器有效优化的源代码,其中理解优化编译器的能力和局限性是很重要的。

除了读写与运算的区别,本节与上一节最大的不同的是:本次的优化示例会影响程序的可读性。

但这也是编程中时常会遇到的情况,在没有更好的优化手段,但又对程序有迫切的性能需求时,采取空间换时间,或降低代码可读性换取运行效率的方法并非不可取。

当你编写一个小工具临时处理某种事务(也许以后并不重用),或者想验证自己的某个想法是否可行时(比如测试某个算法是否正确),若是编写了一个可读性不错但运行很慢的程序,往往会浪费很多不必要的时间。这时候你就可以不需要那么在乎代码的可读性,而是去多关注当前程序的运行性能来更早获得想要的结果。

以下我们将举例对常见的矩阵运算进行代码优化。

目标函数:图像平滑处理

平滑操作要求:

  1. 修改图像矩阵的每个像素点的值,
    新值 = 以该像素点为中心点所相邻的九个像素的平均值
  2. 图像矩阵的四个角点,只需要求角上四个像素的平均值
  3. 图像矩阵的四条边,只需要求当前点相邻的六个像素平均值

原理图:
在这里插入图片描述
1、2、3处分别代表角点、边缘点以及内部点的相邻像素

我们用以下结构体表示一张图像的像素点:

typedef struct {
    
    unsigned short red;   /* R value */ 
    unsigned short green; /* G value */ 
    unsigned short blue;  /* B value */ 
} pixel;

red、green、blue分别表示一张彩色图像的红绿蓝三个通道。

原平滑函数如下:

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_sum sum) 
{
   
    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;
}
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;
}
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);
}

图像是标准的正方形,用一维数组表示,第(i,j)个像素表示为I[RIDX(i,j,n)],n为图像边长。

参数:

  • dim:图像的边长
  • src: 指向原始图像数组首地址
  • dst: 指向目标图像数组首地址

优化目标:使平滑运算处理的更快

当前我们拥有一个driver.c文件,可以对原函数和我们优化的函数进行测试,得到表示程序运行性能的CPE(每元素周期数)参数。

我们的任务就是实现优化代码,与原有代码同时运行进行参数的对比,查看代码优化情况。

优化的主要方法

  1. 循环展开
  2. 并行计算
  3. 提前计算
  4. 分块运算
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值