编程除了使程序在所有可能的情况下都正确工作,还需要考虑程序的运行效率,上一节主要介绍了关于读写的优化,本节将对运算的优化进行分析。
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为图像边长。

参数:

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

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

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

优化的主要方法

  1. 循环展开
  2. 并行计算
  3. 提前计算
  4. 分块运算
  5. 避免复杂运算
  6. 减少函数调用
  7. 提高Cache命中率

循环主体只存在一条语句,该语句主要是进行大量的均值运算,而且调用了多层的函数,这样运行时会出现多个函数栈的调用。

通过分析,本节的优化手段比
计算红色区域平均值与黄色区域平均值时,有两行是重复运算的。相应的优化策略是以1*3小矩阵为组计算和,这样每次计算均值只需要3个已知的和相加除以9,减少了一定的运算量。

相应的优化代码如下:

int rsum[4096][4096]; int gsum[4096][4096]; int bsum[4096][4096]; void smooth(int dim, pixel *src, pixel *dst)  {     int dim2 = dim * dim;