讓你的軟體飛起來 RGB轉為YUV

2021-06-05 02:44:25 字數 4537 閱讀 5817

朋友曾經給我推薦了乙個有關**優化的pdf文件《讓你的軟體飛起來》,看完之後,感受頗深。為了推廣其,同時也為了自己加深印象,故將其總結為word文件。下面就是其的詳細內容總結,希望能於己於人都有所幫助。

速度取決於演算法

同樣的事情,方法不一樣,效果也不一樣。比如,汽車引擎,可以讓你的速度超越馬車,卻無法超越音速;渦輪引擎,可以輕鬆 超越音障,卻無法飛出地球;如果有火箭發動機,就可以到達火星。

**的運算速度取決於以下幾個方面

1、  演算法本身的複雜度,比如mpeg比jpeg複雜,jpeg比bmp的編碼複雜。

2、  cpu自身的速度和設計架構

3、  cpu的匯流排頻寬

4、  您自己**的寫法

本文主要介紹如何優化您自己的code,實現軟體的加速。

先看看我的需求

我們乙個圖象模式識別的專案,需要將rgb格式的彩色影象先轉換成黑白影象。

影象轉換的公式如下:

y = 0.299 * r + 0.587 * g + 0.114 * b;

影象尺寸640*480*24bit,rgb影象已經按照rgbrgb順序排列的格式,放在記憶體裡面了。

我已經悄悄的完成了第乙個優化

以下是輸入和輸出的定義:

#define xsize 640

#define ysize 480

#define imgsize xsize * ysize

typedef struct rgb

rgb;

struct rgb in[imgsize]; //需要計算的原始資料

unsigned char out[imgsize]; //計算後的結果

第乙個優化

優化原則:影象是乙個2d陣列,我用乙個一維陣列來儲存。編譯器處理一維陣列的效率要高過二維陣列。

先寫乙個**:

y = 0.299 * r + 0.587 * g + 0.114 * b;

void calc_lum()

}

這大概是能想得出來的最簡單的寫法了,實在看不出有什麼毛病,好了,編譯一下跑一跑吧。

第一次試跑

這個**分別用vc6.0和gcc編譯,生成2個版本,分別在pc上和我的embedded system上面跑。

速度多少?

在pc上,由於存在硬體浮點處理器,cpu頻率也夠高,計算速度為20秒。

我的embedded system,沒有以上2個優勢,浮點操作被編譯器分解成了整數運算,運算速度為120秒左右。

去掉浮點運算

上面這個**還沒有跑,我已經知道會很慢了,因為這其中有大量的浮點運算。只要能不用浮點運算,一定能快很多。

y = 0.299 * r + 0.587 * g + 0.114 * b;

這個公式怎麼能用定點的整數運算替代呢?

0.299 * r可以如何化簡?

y = 0.299 * r + 0.587 * g + 0.114 * b;

y = d + e + f;

d = 0.299 * r;

e = 0.587 * g;

f = 0.114 * b;

我們就先簡化算式d吧!

rgb的取值範圍都是0~255,都是整數,只是這個係數比較麻煩,不過這個係數可以表示為:0.299 = 299 / 1000;

所以 d = ( r * 299) / 1000;

y = (r * 299 + g * 587 + b * 114) / 1000;

這一下,能快多少呢?

embedded system上的速度為45秒;

pc上的速度為2秒;

0.299 * r可以如何化簡

y = 0.299 * r + 0.587 * g + 0.114 * b;

y = (r * 299 + g * 587 + b * 114) / 1000;

這個式子好像還有點複雜,可以再砍掉乙個除法運算。

前面的算式d可以這樣寫:

0.299=299/1000=1224/4096

所以 d = (r * 1224) / 4096

y=(r*1224)/4096+(g*2404)/4096+(b*467)/4096

再簡化為:

y=(r*1224+g*2404+b*467)/4096

這裡的/4096除法,因為它是2的n次方,所以可以用移位操作替代,往右移位12bit就是把某個數除以4096了。

void calc_lum()

}

這個**編譯後,又快了20%。

雖然快了不少,還是太慢了一些,20秒處理一幅影象,地球人都不能接受。

仔細端詳一下這個式子!

y = 0.299 * r + 0.587 * g + 0.114 * b;

y=d+e+f;

d=0.299*r;

e=0.587*g;

f=0.114*b;

rgb的取值有文章可做,rgb的取值永遠都大於等於0,小於等於255,我們能不能將d,e,f都預先計算好呢?然後用查表演算法計算呢?

我們使用3個陣列分別存放def的256種可能的取值,然後。。。

查表陣列初始化

int d[256],f[256],e[256];

void table_init()

}void calc_lum()

}

這一次的成績把我嚇出一身冷汗,執行時間居然從30秒一下提高到了2秒!在pc上測試這段**,眼皮還沒眨一下,**就執行完了。一下提高15倍,爽不爽?

繼續優化

很多embedded system的32bit cpu,都至少有2個alu,能不能讓2個alu都跑起來?

void calc_lum()

}

2個alu處理的資料不能有資料依賴,也就是說:某個alu的輸入條件不能是別的alu的輸出,這樣才可以並行。

這次成績是1秒。

檢視這個**

int d[256],f[256],e[256]; //查表陣列

void table_init()

}

到這裡,似乎已經足夠快了,但是我們反覆實驗,發現,還有辦法再快!

可以將int d[256],f[256],e[256]; //查表陣列

更改為unsigned shortd[256],f[256],e[256]; //查表陣列

這是因為編譯器處理int型別和處理unsigned short型別的效率不一樣。

再改動

inline void calc_lum()

}

將函式宣告為inline,這樣編譯器就會將其嵌入到母函式中,可以減少cpu呼叫子函式所產生的開銷。

這次速度:0.5秒。

其實,我們還可以飛出地球的!

如果加上以下措施,應該還可以更快:

1、  把查表的資料放置在cpu的高速資料cache裡面;

2、  把函式calc_lum()用組合語言來寫

其實,cpu的潛力是很大的

1、  不要抱怨你的cpu,記住一句話:「只要功率足夠,磚頭都能飛!」

2、  同樣的需求,寫法不一樣,速度可以從120秒變化為0.5秒,說明cpu的潛能是很大的!看你如何去挖掘。

3、  我想:要是microsoft的工程師都像我這樣優化**,我大概就可以用489跑windows xp了!

以上就是對《讓你的軟體飛起來》的摘錄,下面,我將按照這位牛人的介紹,對rgb到ycbcr的轉換演算法做以總結。

y =   0.299r + 0.587g + 0.114b

u = -0.147r - 0.289g + 0.436b

v =  0.615r - 0.515g - 0.100b

#deinfe size 256

#define xsize 640

#define ysize 480

#define imgsize xsize * ysize

typedef struct rgb

rgb;

struct rgb in[imgsize]; //需要計算的原始資料

unsigned char out[imgsize * 3]; //計算後的結果

unsigned short y_r[size],y_g[size],y_b[size],u_r[size],u_g[size],u_b[size],v_r[size],v_g[size],v_b[size]; //查表陣列

void table_init()}

inline void calc_lum()

}

根據牛人的觀點,這種演算法應該是非常快的了,以後可直接使用了。

^_^

讓你的程式飛起來

本方法可以讓c語言指令進一步接近彙編指令的執行效率,提高微控制器 嵌入式系統的速度和穩定性,但程式設計時應採取函式化的程式設計法 例如使用swap 函式時,必要時加注釋。0.位運算心法 1.如果乘上乙個2的倍數數值,可以改用左移運算 left shift 加速 300 x x 2 x x 64 改為...

讓你的軟體飛起來 演算法優化

摘自網路 封面 內容 的運算速度取決於以下幾個方面 1 演算法本身的複雜度,比如mpeg比jpeg複雜,jpeg比bmp的編碼複雜。2 cpu自身的速度和設計架構 3 cpu的匯流排頻寬 4 您自己 的寫法 本文主要介紹如何優化您自己的code,實現軟體的加速。先看看我的需求 我們乙個圖象模式識別的...

利用春節期間讓你的流量飛起來

首先在這裡祝大家春節快樂!這段時間大家都放假在家,不是出去應酬,就是在家看春晚。相信大家這段www.cppcns.com時間肯定放下了這一年的包袱,想好好輕鬆一下了,我也是如此。春節這段時間比較心細有上進心的站長春節期間還在大理著自己的 但有些 春節這段期間已經停止了更新和維護。這就給我們這些比較勤...