2009-10-03 96 views
2

我想要做的就是利用这个代码:如何优化

char naive_smooth_descr[] = "naive_smooth: Naive baseline implementation"; 

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); 
} 

,并在页面最底部替换函数调用avg(dim, i, j, src);与实际的代码。然后,采取代码并替换与实际的代码,代码中所有的函数调用等

如果你问为什么做这一切的原因很简单:当你摆脱了函数调用的程序运行速度更快,并且我试图通过摆脱所有函数调用并将其替换为实际代码来实现上述代码运行时每个元素的最快周期。

现在我真的只是有很多的麻烦事情了。我是否将括号中的代码复制并粘贴?我不支持括号吗?我是否包含代码的开始,例如,static pixel avg(int dim, int i, int j, pixel *src)然后括号,然后代码来替换函数调用?

我要贴上这里的所有代码:

/* A struct used to compute averaged pixel value */ 

typedef struct { 

    int red; 
    int green; 
    int blue; 
    int num; 

} pixel_sum; 

/* Compute min and max of two integers, respectively */ 


static int min(int a, int b) { return (a < b ? a : b); } 

static int max(int a, int b) { return (a > b ? a : b); } 



/* 
* initialize_ pixel_ sum - Initializes all fields of sum to 0 
*/ 


static void initialize_ pixel_ sum (pixel_sum *sum) 

{ 

    sum->red = sum->green = sum->blue = 0; 
    sum->num = 0; 
    return; 

} 

/* 
* accumulate_sum - Accumulates field values of p in corresponding 
* fields of sum 
*/ 

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; 

} 


/* 
* assign_ sum_ to_ pixel - Computes averaged pixel value in current_pixel 
*/ 

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; 

} 

/* 
* avg - Returns averaged pixel value at (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; 


} 

/* 
* mysmooth - my smooth 
*/ 

char mysmooth_ descr[] = "my smooth: My smooth"; 

void mysmooth (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++) 
{ 
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); 
dst[RIDX(i, j, dim)] = current_pixel; 
} 

所以这是我的代码应该看起来像我完成代码后fr om avg()并用函数替换它?

+1

你为什么要尽全力去微观优化?你从中得到什么? – 2009-10-09 13:44:21

+0

大卫的问题尤其重要,因为通过滚动计算平均值而不是从头开始,可以使该算法更快得多。如果你是为了好玩而做这些事情,那么就自己解决吧,但是如果你真的希望代码以最小的努力跑得更快,那就用更高效的alg。 – PeterAllenWebb 2009-10-22 21:57:47

回答

2

我不得不说我同意确保您使用编译器优化和内联的方法...但如果你仍然想回答您的具体问题,我想你在说是一样的东西:

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

    /* ...avg() code body except for the return... */ 

    dst[RIDX(i, j, dim)] = current_pixel; 
} 
+0

actuall ...这正是我正在寻找...现在我基本上做同样的avg()代码体内的其余功能? – 2009-10-03 08:10:30

+0

我在底部发布代码以查看它是否是正确的代码... – 2009-10-03 08:50:59

8

如果你的代码基数很小,包括10-12个函数,你可能想尝试在每个函数前面加上关键字inline

第二个选项,使用内联的所有函数调用编译器选项,不要做手工(这就是为什么编译器存在)。你使用什么编译器?您可以在线查看其内联函数调用的选项(如果有的话)。

第三,如果你正在使用GCC编译的代码,您可以指定功能always_inline属性。这里是如何使用它:

static pixel avg (int dim, int i, int j, pixel *src) __attribute__((always_inline)); 
4
  1. 如果您使用的是C99编译器或C++编译器,你可以使用inline关键字。但是,只有在编译器认为它更高效时,它才能保证该调用将被实际代码替代。
  2. 否则,如果您使用的是纯C89,然后avg()必须是一个宏。然后你保证将函数“call”替换为实际的代码。
0

我展开的开始和周期结束时以消除MIN()和MAX()从代码:

void smooth_B(int dim, struct pixel src[dim][dim], struct pixel dst[dim][dim]){ 
    dst[0][0].red =(src[0][0].red +src[1][0].red +src[0][1].red +src[1][1].red )/4; 
    dst[0][0].green=(src[0][0].green+src[1][0].green+src[0][1].green+src[1][1].green)/4; 
    dst[0][0].blue =(src[0][0].blue +src[1][0].blue +src[0][1].blue +src[1][1].blue)/4; 
    for(int j=1; j<dim-1; j++){ 
    dst[0][j].red =(src[0][j-1].red +src[1][j-1].red +src[0][j].red +src[1][j].red +src[0][j+1].red +src[1][j+1].red )/6; 
    dst[0][j].green=(src[0][j-1].green+src[1][j-1].green+src[0][j].green+src[1][j].green+src[0][j+1].green+src[1][j+1].green)/6; 
    dst[0][j].blue =(src[0][j-1].blue +src[1][j-1].blue +src[0][j].blue +src[1][j].blue +src[0][j+1].blue +src[1][j+1].blue)/6; 
    } 
    dst[0][dim-1].red =(src[0][dim-2].red +src[1][dim-2].red +src[0][dim-1].red +src[1][dim-1].red )/4; 
    dst[0][dim-1].green=(src[0][dim-2].green+src[1][dim-2].green+src[0][dim-1].green+src[1][dim-1].green)/4; 
    dst[0][dim-1].blue =(src[0][dim-2].blue +src[1][dim-2].blue +src[0][dim-1].blue +src[1][dim-1].blue)/4; 

    for(int i=1; i<dim-1; i++){ 
    dst[i][0].red =(src[i-1][0].red +src[i-1][1].red +src[i][0].red +src[i][1].red +src[i+1][0].red +src[i+1][1].red )/6; 
    dst[i][0].green=(src[i-1][0].green+src[i-1][1].green+src[i][0].green+src[i][1].green+src[i+1][0].green+src[i+1][1].green)/6; 
    dst[i][0].blue =(src[i-1][0].blue +src[i-1][1].blue +src[i][0].blue +src[i][1].blue +src[i+1][0].blue +src[i+1][1].blue)/6; 
    for(int j=1; j<dim; j++){ 
     dst[i][j].red =(src[i-1][j-1].red +src[i][j-1].red +src[i+1][j-1].red +src[i-1][j].red +src[i][j].red +src[i+1][j].red +src[i-1][j+1].red +src[i][j+1].red +src[i+1][j+1].red )/9; 
     dst[i][j].green=(src[i-1][j-1].green+src[i][j-1].green+src[i+1][j-1].green+src[i-1][j].green+src[i][j].green+src[i+1][j].green+src[i-1][j+1].green+src[i][j+1].green+src[i+1][j+1].green)/9; 
     dst[i][j].blue =(src[i-1][j-1].blue +src[i][j-1].blue +src[i+1][j-1].blue +src[i-1][j].blue +src[i][j].blue +src[i+1][j].blue +src[i-1][j+1].blue +src[i][j+1].blue +src[i+1][j+1].blue)/9; 
    } 
    dst[i][dim-1].red =(src[i-1][dim-2].red +src[i][dim-2].red +src[i+1][dim-2].red +src[i-1][dim-1].red +src[i][dim-1].red +src[i+1][dim-1].red )/6; 
    dst[i][dim-1].green=(src[i-1][dim-2].green+src[i][dim-2].green+src[i+1][dim-2].green+src[i-1][dim-1].green+src[i][dim-1].green+src[i+1][dim-1].green)/6; 
    dst[i][dim-1].blue =(src[i-1][dim-2].blue +src[i][dim-2].blue +src[i+1][dim-2].blue +src[i-1][dim-1].blue +src[i][dim-1].blue +src[i+1][dim-1].blue)/6; 
    } 
    dst[dim-1][0].red =(src[dim-2][0].red +src[dim-2][1].red +src[dim-1][0].red +src[dim-1][1].red )/4; 
    dst[dim-1][0].green=(src[dim-2][0].green+src[dim-2][1].green+src[dim-1][0].green+src[dim-1][1].green)/4; 
    dst[dim-1][0].blue =(src[dim-2][0].blue +src[dim-2][1].blue +src[dim-1][0].blue +src[dim-1][1].blue)/4; 
    for(int j=1; j<dim; j++){ 
    dst[dim-1][j].red =(src[dim-2][j-1].red +src[dim-1][j-1].red +src[dim-2][j].red +src[dim-1][j].red +src[dim-2][j+1].red +src[dim-1][j+1].red )/6; 
    dst[dim-1][j].green=(src[dim-2][j-1].green+src[dim-1][j-1].green+src[dim-2][j].green+src[dim-1][j].green+src[dim-2][j+1].green+src[dim-1][j+1].green)/6; 
    dst[dim-1][j].blue =(src[dim-2][j-1].blue +src[dim-1][j-1].blue +src[dim-2][j].blue +src[dim-1][j].blue +src[dim-2][j+1].blue +src[dim-1][j+1].blue)/6; 
    } 
    dst[dim-1][dim-1].red =(src[dim-2][dim-2].red +src[dim-1][dim-2].red +src[dim-2][dim-1].red +src[dim-1][dim-1].red )/4; 
    dst[dim-1][dim-1].green=(src[dim-2][dim-2].green+src[dim-1][dim-2].green+src[dim-2][dim-1].green+src[dim-1][dim-1].green)/4; 
    dst[dim-1][dim-1].blue =(src[dim-2][dim-2].blue +src[dim-1][dim-2].blue +src[dim-2][dim-1].blue +src[dim-1][dim-1].blue)/4; 
} 

正如我测量它比原来的代码快了50%。下一步是消除重复计算。