2009-10-03 97 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%。下一步是消除重複計算。