亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

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

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

代碼的運(yùn)算速度取決于以下幾個方面:

(1)處理器的主頻和設(shè)計架構(gòu);

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

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

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

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

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

圖像尺寸640*480*24 bits,RGB圖像已經(jīng)按照RGBRGB順序排列的格式,放在內(nèi)存里面了。

例如,將這個噴火的戰(zhàn)斗機(jī)引擎,轉(zhuǎn)換為右邊的黑白圖片。

程序的靈魂——算法

 

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

#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]; /* 未轉(zhuǎn)換的圖片數(shù)據(jù) */
uint8_t out[IMGSIZE]; /* 轉(zhuǎn)換后的圖片數(shù)據(jù) */

優(yōu)化原則:

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

第一個程序:

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和嵌入式開發(fā)板上面運(yùn)行。

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

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

第一次優(yōu)化

優(yōu)化原則:

去掉浮點(diǎn)數(shù)運(yùn)算。

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

R的系數(shù):0.299 = 299 / 1000

G的系數(shù):0.587 = 587 / 1000

B的系數(shù):0.114 = 114 / 1000

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

即轉(zhuǎn)換圖片的程序變?yōu)椋?/p>

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

再次編譯生成兩個平臺的應(yīng)用程序運(yùn)行,發(fā)現(xiàn):

A、在PC上運(yùn)行的時間為2秒

B、在嵌入式開發(fā)板上運(yùn)行的時間為45秒

第二次優(yōu)化

優(yōu)化原則:

處理器在進(jìn)行除法運(yùn)算時,處理速度比較慢,去除除法操作

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

R的系數(shù):0.299 = 299 / 1000 = 1224 / 4096

G的系數(shù):0.587 = 587 / 1000 = 2404 / 4096

B的系數(shù):0.114 = 114 / 1000 = 467 / 4096

由于4096是2的倍數(shù),除法可用效率更高的移位操作進(jìn)行優(yōu)化,所以圖片轉(zhuǎn)換公式為:

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

所以圖片轉(zhuǎn)換程序為:

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

再次編譯運(yùn)行,發(fā)現(xiàn)在嵌入式開發(fā)板上運(yùn)行時間為30秒。

第三次優(yōu)化

優(yōu)化原則:

由于每一次轉(zhuǎn)換的RGB系數(shù)都要經(jīng)過計算得到,減少各個系數(shù)的計算次數(shù)。

優(yōu)化代碼如下:

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

再次編譯運(yùn)行,發(fā)現(xiàn)在嵌入式開發(fā)板上運(yùn)行時間為2秒。

第四次優(yōu)化

優(yōu)化原則:

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

優(yōu)化代碼如下:

#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)
 { 
 /* 給第一個算術(shù)邏輯單元執(zhí)行 */
 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;
 /* 給第二個算術(shù)邏輯單元執(zhí)行 */
 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;
 /* 如果有更多算術(shù)邏輯單元,可以類似的處理代碼 */
 }
}

再次編譯運(yùn)行,發(fā)現(xiàn)在嵌入式開發(fā)板上運(yùn)行時間為1秒。

第五次優(yōu)化

優(yōu)化原則:

由于各個數(shù)據(jù)類型大小不一樣,處理速度也不一樣,因此可以對數(shù)據(jù)類型優(yōu)化

優(yōu)化代碼如下:

#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)
 { 
 /* 給第一個算術(shù)邏輯單元執(zhí)行 */
 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;
 /* 給第二個算術(shù)邏輯單元執(zhí)行 */
 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;
 }
}

將函數(shù)聲明為inline,這樣編譯器就會將其嵌入到母函數(shù)中,可以減少CPU調(diào)用子函數(shù)所產(chǎn)生的開銷。

再次編譯運(yùn)行,發(fā)現(xiàn)在嵌入式開發(fā)板上運(yùn)行時間為0.5秒。

后續(xù)可優(yōu)化的方向:

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

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

說明:本文來源于網(wǎng)絡(luò),我僅僅是對文章進(jìn)行了一定的整理,刪繁就簡,如有侵權(quán),請及時聯(lián)系我刪除!

分享到:
標(biāo)簽:算法
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

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

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定