使用者工具

網站工具


programming:speed_enhance
作者: StubbornLin (Victor) 看板: C_and_CPP
標題: Re: [問題] 程式的執行速度
時間: Sat Sep  3 18:01:30 2005

※ 引述《qlight (...)》之銘言:
: 請問一下 大大們
: 因為我的數值很大 變數必須用double來宣告才存放的下
: (其中包含 陣列也是宣告成 double)
: 因此 我的程式好像跑的特別的慢...
: 請問 有什麼改善的方法嗎?
: 如果用好一點的機器跑會不會 有一些些的幫助?
: thanks
關於程式執行的效能,最主要的關鍵,還是演算法和流程
當演算法流程都已經做得很好時,這時如果還要擠出更多的效能
就只能從一些小地方來加強

1.for回圈的遞增
    for(int i=0;i<n;i++){
        dosomething();
    }
    以這個例子來說i++應該改成++i
    因為i++會多出一個暫時的變數

2.無限回圈
    while(true){
        dosomething();
    }
    以這樣的無限回圈來說,應該改成
    for(;;){
        dosomething();
    }
    以while(true)來說,應該每次回圈都會檢查一次條件,這是多餘的

3.回圈的判斷式盡量以變數先算完
    for(int i=0;i<(int)pow(n,0.5f);++i){
        dosomething();
    }
    以這樣的回圈來說,for一般會每跑完一圈,就重新計算一次pow(n.0.5f)
    如果,這條件的值,沒有更動的必要,就先用一個變數,來存放結果
    int end = (int)pow(n,0.5f);
    for(int i=0;i<end;++i){
        dosomething();
    }

4.能在回圈外完成的東西,盡量擺到回圈外
    一個回圈,通常在越裡面執行的次數越多,所以
    很多東西如果能夠擺到圈外的話,就盡量擺到圈外去
    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            xxxx....

            if( pow( pow(A,2)+pow(B,2) ,0.5f) == R){
                dosomething();
            }else{
                doanotherthing();
            }
        }
    }
    以上,是假設圈內的動作,與判斷式無關
    所以,判斷式在圈外就能完成,應該改成
    for(int i=0;i<n;++i){
        if( pow( pow(A,2)+pow(B,2) ,0.5f) == R){
            for(int j=0;j<m;++j){
                xxxx....
                dosomething();
            }
        }else{
            for(int j=0;j<m;++j){
                xxxx....
                doanotherthing();
            }
        }
    }
    雖然說,幾乎同樣的程式碼被重複了兩次,但是換來的是省下好幾次的判斷

5.盡量避免使用* / 等等花時間的運算
    + - 的運算 速度遠比 * / 快
    所以,如果一個演算法是以+ -取代 * / 運算的話
    效能通常都會比用*和/快很多
    +比-快 而*又比/快

    但是,以上情況,是在整數適用
    當到了float等浮點運算時,情況相反
    * /比 + - 快,所以,如果必需用浮點的話,請盡量使用* or /

6.乘上或除上2的次方,用<<和>>取代
    當一個數乘上或除上二的次方,就可以用移位來做運算
    其速度遠比直接用乘除速度來的跨
    int SizeOfImage = (W*H)<<1;
    這行,就等於
    int SizeOfImage = W*H*2;

    以及除法
    int MidPoint = (X1+X2)>>1;
    就等於
    int MidPoint = (X1+X2)/2

    2的次方是指 2 4 8 16 32 64 128....等數
    只要是乘上或除上都適用,不過,當然,這也只適合整數

7.盡量運用Bit運算
    有很多計算,其實都可以用Bit的運算完成,因為Bit運算比一般的運算
    速度上快了很多
    例如,奇數偶數的運算,直觀的做法,當然是求除以二的餘數
    if(n%2 != 0){
        // 奇數
    }else{
        // 偶數
    }
    但是,以Bit運算來判斷,我們知道,只要最後一個Bit
    是1就是奇數,0就是偶數,於是,便可以利用這點來做運算
    if(n&0x1){
        // 奇數
    }else{
        // 偶數
    }

以上,是我個人的經驗,目前想到這裡,有想到再補上
這些很多做法,雖然能多擠出些效能,但是同時也會讓程式碼可讀性降低
程式碼也會增加,所以,在擠效能的同時,如果程式碼不是只有你要看的
請加上一些注解,來說明這是在幹麻的,否則很多東西真的是很難看懂

雖然,有些東西編譯器可能會幫你做,但是,我認為要擠效能就要明確的去做
不能全部依賴編譯器,因為你不能保證每個人用的都是和你一樣的編譯器
一樣的參數設定

如果有其它做法,也請Po上來

--
VICTOR工作室

URL : http://www.kinmen.info/vic/

C/C++
Visual Basic 6.0

--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.116.73.165
※ 編輯: StubbornLin     來自: 59.116.73.165        (09/03 18:03)
programming/speed_enhance.txt · 上一次變更: 2008/07/28 16:13 由 wenpei