摘自網路:
封面:
內容:
**的運算速度取決於以下幾個方面
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
unsigned char r;
unsigned char g;
unsigned char b;
}rgb;
struct rgb in[imgsize]; //需要計算的原始資料
unsigned char out[imgsize]; //計算後的結果
第乙個優化:
優化原則:影象是乙個2d陣列,我用乙個一維陣列來儲存。編譯器處理一維陣列的效率要高過二維陣列。
先寫乙個**:
y = 0.299 * r + 0.587 * g + 0.114 * b;
void calc_lum()
int i;
for(i = 0; i < imgsize; i++)
double r,g,b,y;
unsigned char yy;
r = in[i].r;
g = in[i].g;
b = in[i].b;
y = 0.299 * r + 0.587 * g + 0.114 * b;
yy = y;
out[i] = yy;
這大概是能想得出來的最簡單的寫法了,實在看不出有什麼毛病,好了,編譯一下跑一跑吧。
第一次試跑
這個**分別用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秒;
優化三:將除法轉化為移位操作
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()
int i;
for(i = 0; i < imgsize; i++)
int r,g,b,y;
r = 1224 * in[i].r;
g = 2404 * in[i].g;
b = 467 * in[i].b;
y = r + g + b;
y = y >> 12; //這裡去掉了除法運算
out[i] = y;
這個**編譯後,又快了20%。
雖然快了不少,還是太慢了一些,20秒處理一幅影象,地球人都不能接受
優化四:將有限的計算結果變為查詢表的方法:
rgb的取值有文章可做,rgb的取值永遠都大於等於0,小於等於255,我們能不能將d,e,f都預先計算好呢?然後用查表演算法計算呢?
我們使用3個陣列分別存放def的256種可能的取值,然後。。。
查表陣列初始化
int d[256],f[256],e[256];
void table_init()
int i;
for(i=0;i<256;i++)
d[i]=i*1224;
d[i]=d[i]>>12;
e[i]=i*2404;
e[i]=e[i]>>12;
f[i]=i*467;
f[i]=f[i]>>12;
void calc_lum()
int i;
for(i = 0; i < imgsize; i++)
int r,g,b,y;
r = d[in[i].r];//查表
g = e[in[i].g];
b = f[in[i].b];
y = r + g + b;
out[i] = y;
這一次的成績把我嚇出一身冷汗,執行時間居然從30秒一下提高到了2秒!在pc上測試這段**,眼皮還沒眨一下,**就執行完了。一下提高15倍,爽不爽?
優化五、復用將單個或者序列轉化為多路並行
很多embedded system的32bit cpu,都至少有2個alu,能不能讓2個alu都跑起來?
void calc_lum()
int i;
for(i = 0; i < imgsize; i += 2) //一次並行處理2個資料
int r,g,b,y,r1,g1,b1,y1;
r = d[in[i].r];//查表 //這裡給第乙個alu執行
g = e[in[i].g];
b = f[in[i].b];
y = r + g + b;
out[i] = y;
r1 = d[in[i + 1].r];//查表 //這裡給第二個alu執行
g1 = e[in[i + 1].g];
b1 = f[in[i + 1].b];
y = r1 + g1 + b1;
out[i + 1] = y;
2個alu處理的資料不能有資料依賴,也就是說:某個alu的輸入條件不能是別的alu的輸出,這樣才可以並行。
這次成績是1秒。
優化六,改變資料型別或者資料位數
檢視這個**
int d[256],f[256],e[256]; //查表陣列
void table_init()
int i;
for(i=0;i<256;i++)
d[i]=i*1224;
d[i]=d[i]>>12;
e[i]=i*2404;
e[i]=e[i]>>12;
f[i]=i*467;
f[i]=f[i]>>12;
到這裡,似乎已經足夠快了,但是我們反覆實驗,發現,還有辦法再快!
可以將int d[256],f[256],e[256]; //查表陣列
更改為unsigned shortd[256],f[256],e[256]; //查表陣列
這是因為編譯器處理int型別和處理unsigned short型別的效率不一樣。
再改動inlinevoid calc_lum()
int i;
for(i = 0; i < imgsize; i += 2) //一次並行處理2個資料
int r,g,b,y,r1,g1,b1,y1;
r = d[in[i].r];//查表 //這裡給第乙個alu執行
g = e[in[i].g];
b = f[in[i].b];
y = r + g + b;
out[i] = y;
r1 = d[in[i + 1].r];//查表 //這裡給第二個alu執行
g1 = e[in[i + 1].g];
b1 = f[in[i + 1].b];
y = r1 + g1 + b1;
out[i + 1] = y;
將函式宣告為inline,這樣編譯器就會將其嵌入到母函式中,可以減少cpu呼叫子函式所產生的開銷。
這次速度:0.5秒
主要思想:空間、時間的相互轉化
讓你的程式飛起來
本方法可以讓c語言指令進一步接近彙編指令的執行效率,提高微控制器 嵌入式系統的速度和穩定性,但程式設計時應採取函式化的程式設計法 例如使用swap 函式時,必要時加注釋。0.位運算心法 1.如果乘上乙個2的倍數數值,可以改用左移運算 left shift 加速 300 x x 2 x x 64 改為...
讓SQL飛起來
讓sql飛起來 人們在使用sql時往往會陷入乙個誤區,即太關注於所得的結果是否正確,而忽略了不同的實現方法之間可能存在的效能差異,這種效能差異在大型的或是複雜的資料庫環境中 如聯機事務處理oltp或決策支援系統dss 中表現得尤為明顯。筆者在工作實踐中發現,不良的sql往往來自於不恰當的索引設計 不...
讓你的軟體飛起來 RGB轉為YUV
朋友曾經給我推薦了乙個有關 優化的pdf文件 讓你的軟體飛起來 看完之後,感受頗深。為了推廣其,同時也為了自己加深印象,故將其總結為word文件。下面就是其的詳細內容總結,希望能於己於人都有所幫助。速度取決於演算法 同樣的事情,方法不一樣,效果也不一樣。比如,汽車引擎,可以讓你的速度超越馬車,卻無法...