日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

同樣的事情,使用不一樣的方法去完成,雖然最終的結果一樣,但是完成的效率往往不一樣。假如你離家一千公里路程,過年要回家過春節,你可以走路回家,可以騎自行車回家,可以騎摩托車回家,可以坐汽車回家,可以坐火車回家,當然也可以坐飛機回家,雖然最終目的都是到達一千公里的家鄉,但是乘坐不同的交通工具,回家的時間各異。在程序中,這些不同的“交通工具”我們稱之為算法。

代碼的運算速度取決于以下幾個方面:

(1)處理器的主頻和設計架構;

(2)處理器的總線帶寬;

(3)程序代碼的設計編寫;

(4)程序中所使用算法本身的復雜度,比如MPEG比JPEG復雜,JPEG比BMP圖片的編碼復雜。

比如在一個圖像轉換的項目中,需要將RGB格式的彩色圖像先轉換成黑白圖像。圖像轉換的公式如下:

Y = 0.299 * R + 0.587 * G + 0.114 * B;

圖像尺寸640*480*24 bits,RGB圖像已經按照RGBRGB順序排列的格式,放在內存里面了。

例如,將這個噴火的戰斗機引擎,轉換為右邊的黑白圖片。

程序的靈魂——算法

 

圖片輸入和輸出的定義如下:

#define XSIZE (640)
#define YSIZE (480)
#define IMGSIZE XSIZE*YSIZE
typedef struct rgb
{
 uint8_t r;
 uint8_t g;
 uint8_t b;
}RGB;
RGB in[IMGSIZE]; /* 未轉換的圖片數據 */
uint8_t out[IMGSIZE]; /* 轉換后的圖片數據 */

優化原則:

圖像是一個二維數組,我用一個一維數組來存儲。編譯器處理一維數組的效率要高于二維數組。

第一個程序:

void convert_rgb_image(void)
{
 int i = 0;
 for(i = 0; i < IMGSIZE; i++)
 { 
 uint8_t r = in[i].r; 
 uint8_t g = in[i].g; 
 uint8_t b = in[i].b;
 double temp_out = 0.299 * r + 0.587 * g + 0.114 * b;
 out[i] = temp_out;
 }
}

分別用VC6.0和交叉編譯工具,生成2個版本,分別在PC和嵌入式開發板上面運行。

A、在PC上,由于存在硬件浮點處理器,CPU頻率也夠高,運行時間為20秒。

B、在嵌入式開發板 ,主頻時鐘比較低,也沒有浮點處理器,浮點操作被編譯器分解成了整數運算,運行時間為120秒左右。

第一次優化

優化原則:

去掉浮點數運算。

在公式Y = 0.299 * R + 0.587 * G + 0.114 * B由于RGB的取值范圍都是0~255,只是系數都是浮點數,將RGB的系數轉換為:

R的系數:0.299 = 299 / 1000

G的系數:0.587 = 587 / 1000

B的系數:0.114 = 114 / 1000

所以圖片轉換公式可表示成:Y = (299 * R + 587 * G + 114 * B)/ 1000

即轉換圖片的程序變為:

void convert_rgb_image(void)
{
 int i = 0;
 for(i = 0; i < IMGSIZE; i++)
 { 
 uint8_t r = in[i].r; 
 uint8_t g = in[i].g; 
 uint8_t b = in[i].b;
 double temp_out = (299 * r + 587 * g + 114 * b) / 1000;
 out[i] = temp_out;
 }
}

再次編譯生成兩個平臺的應用程序運行,發現:

A、在PC上運行的時間為2秒

B、在嵌入式開發板上運行的時間為45秒

第二次優化

優化原則:

處理器在進行除法運算時,處理速度比較慢,去除除法操作

將公式Y = (299 * R + 587 * G + 114 * B)/ 1000的RGB的系數優化如下:

R的系數:0.299 = 299 / 1000 = 1224 / 4096

G的系數:0.587 = 587 / 1000 = 2404 / 4096

B的系數:0.114 = 114 / 1000 = 467 / 4096

由于4096是2的倍數,除法可用效率更高的移位操作進行優化,所以圖片轉換公式為:

Y = (1224 * R + 2404 * G + 467 * G) >> 12

所以圖片轉換程序為:

void convert_rgb_image(void)
{
 int i = 0;
 for(i = 0; i < IMGSIZE; i++)
 { 
 int r = 1224 * in[i].r; 
 int g = 2404 * in[i].g; 
 int b = 467 * in[i].b;
 int temp_out = (r + g + b) >> 12;
 out[i] = temp_out;
 }
}

再次編譯運行,發現在嵌入式開發板上運行時間為30秒。

第三次優化

優化原則:

由于每一次轉換的RGB系數都要經過計算得到,減少各個系數的計算次數。

優化代碼如下:

#define RGB_SIZE (256)
int R[RGB_SIZE];
int G[RGB_SIZE];
int B[RGB_SIZE];
void rgb_table_init(void)
{
 int i = 0;
 for(i = 0; i < RGB_SIZE; i++)
 {
 R[i] = 1224 * i;
 R[i] = R[i] >> 12;
 G[i] = 2404 * i;
 G[i] = G[i] >> 12;
 B[i] = 467 * i;
 B[i] = B[i] >> 12;
 }
}
void convert_rgb_image(void)
{
 int i = 0;
 for(i = 0; i < IMGSIZE; i++)
 { 
 int r = R[in[i].r]; 
 int g = G[in[i].g]; 
 int b = B[in[i].b];
 int temp_out = r + g + b;
 out[i] = temp_out;
 }
}

再次編譯運行,發現在嵌入式開發板上運行時間為2秒。

第四次優化

優化原則:

32位的嵌入式CPU,都至少有2個算術邏輯單元(ALU),讓2個ALU一起運行

優化代碼如下:

#define RGB_SIZE (256)
int R[RGB_SIZE];
int G[RGB_SIZE];
int B[RGB_SIZE];
void rgb_table_init(void)
{
 int i = 0;
 for(i = 0; i < RGB_SIZE; i++)
 {
 R[i] = 1224 * i;
 R[i] = R[i] >> 12;
 G[i] = 2404 * i;
 G[i] = G[i] >> 12;
 B[i] = 467 * i;
 B[i] = B[i] >> 12;
 }
}
void convert_rgb_image(void)
{
 int i = 0;
 for(i=0; i < IMGSIZE; i += 2)
 { 
 /* 給第一個算術邏輯單元執行 */
 int r0 = R[in[i].r]; 
 int g0 = G[in[i].g]; 
 int b0 = B[in[i].b];
 int temp_out_0 = r0 + g0 + b0;
 out[i] = temp_out_0;
 /* 給第二個算術邏輯單元執行 */
 int r1 = R[in[i+1].r]; 
 int g1 = G[in[i+1].g]; 
 int b1 = B[in[i+1].b];
 int temp_out_1 = r1 + g1 + b1;
 out[i+1] = temp_out_1;
 /* 如果有更多算術邏輯單元,可以類似的處理代碼 */
 }
}

再次編譯運行,發現在嵌入式開發板上運行時間為1秒。

第五次優化

優化原則:

由于各個數據類型大小不一樣,處理速度也不一樣,因此可以對數據類型優化

優化代碼如下:

#define RGB_SIZE (256)
uint16_t R[RGB_SIZE];
uint16_t G[RGB_SIZE];
uint16_t B[RGB_SIZE];
void rgb_table_init(void)
{
 uint8_t i = 0;
 for(i = 0; i <= RGB_SIZE; i++)
 {
 R[i] = 1224 * i;
 R[i] = R[i] >> 12;
 G[i] = 2404 * i;
 G[i] = G[i] >> 12;
 B[i] = 467 * i;
 B[i] = B[i] >> 12;
 }
}
inline void convert_rgb_image(void)
{
 uint32_t i = 0;
 for(i=0; i < IMGSIZE; i += 2)
 { 
 /* 給第一個算術邏輯單元執行 */
 uint16_t r0 = R[in[i].r]; 
 uint16_t g0 = G[in[i].g]; 
 uint16_t b0 = B[in[i].b];
 uint32_t temp_out_0 = r0 + g0 + b0;
 out[i] = temp_out_0;
 /* 給第二個算術邏輯單元執行 */
 uint16_t r1 = R[in[i+1].r]; 
 uint16_t g1 = G[in[i+1].g]; 
 uint16_t b1 = B[in[i+1].b];
 uint32_t temp_out_1 = r1 + g1 + b1;
 out[i+1] = temp_out_1;
 }
}

將函數聲明為inline,這樣編譯器就會將其嵌入到母函數中,可以減少CPU調用子函數所產生的開銷。

再次編譯運行,發現在嵌入式開發板上運行時間為0.5秒。

后續可優化的方向:

(1)將RGB查表的數據放入CPU的高速緩沖存儲器(Cache)中,從而提升程序運行時的加載速度。

(2)代碼使用匯編語言進行編寫

說明:本文來源于網絡,我僅僅是對文章進行了一定的整理,刪繁就簡,如有侵權,請及時聯系我刪除!

分享到:
標簽:算法
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定