朋友曾經給我推薦了乙個有關**優化的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都跑起來?
2個alu處理的資料不能有資料依賴,也就是說:某個alu的輸入條件不能是別的alu的輸出,這樣才可以並行。void calc_lum()
}
這次成績是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時間肯定放下了這一年的包袱,想好好輕鬆一下了,我也是如此。春節這段時間比較心細有上進心的站長春節期間還在大理著自己的 但有些 春節這段期間已經停止了更新和維護。這就給我們這些比較勤...