1、優化編譯器的能力和侷限性
(1)編譯器有自己能夠優化程式的能力,但會有侷限性。
●指標指向記憶體的同一位置:
例如:
void twiddle1(long *xp, long *yp)
void twiddle2(long *xp, long *yp)
函式twiddle1需要6次記憶體引用(2次讀*xp,2次讀*yp,2次寫*xp),而函式twiddle2只需要3次記憶體引用(讀*xp,讀*yp,寫*xp),所以twiddle2的執行會更加有效。
但是,考慮到xp和yp相等的情況(即記憶體引用同乙個地方,指標指向同乙個位址),兩個函式的執行結果將不相等。
twiddle1將執行以下計算:
void twiddle1(long *xp, long *yp)
計算結果為xp增加4倍。
twiddle2將執行以下計算:
void twiddle2(long *xp, long *yp)
計算結果為*xp增加3倍。
這時,編譯器不會知道xp和yp是否相等,所以會考慮它們可能相等的情況,便不會產生優化的版本,這限制了可能的優化策略。
●函式呼叫:
long f();
long
count = 0;
long func1()
long func2()
long f()
函式func1()和func2()似乎是相同的,但是,當呼叫的函式f()中對全域性變數進行了改變後,func1()和func2()得到的結果便會不一樣,避免不必要的函式呼叫,將計算過程改為如下:
long funclin()
編譯器可以統一對全域性變數的更新,產生函式的優化版本如下:
long funclopt()
2、消除迴圈的低效率
分析下面兩個函式的效率:
void lower1(char *s)
}void lower2(char *s)
}
很明顯,當字串長度逐漸變長時,lower2的效能便會成為瓶頸,而且,編譯器並不知道strlen(s)的結果是否會變化(當迴圈裡面有對於字串從零變成非零或是從非零變成零時,長度會變化),便不會進行優化,需要我們手動進行優化。
3、消除不必要的迴圈引用
將迴圈內的指標使用盡可能的放在迴圈外面,例如:
void combine1()
}void combine2()
*dest = acc;
}
上面兩個函式中,combine1()迴圈內每次對記憶體進行兩次讀一次寫(在機器**中,指標的位址是存放在暫存器中,需要通過暫存器中的位址找到相應的位置,再找到相應的數),而combine2()則減少為一次讀(對data陣列的訪問) 程式效能優化 深入理解計算機系統
對暫存器的訪問的優化 暫存器訪問優化的核心是盡量避免打斷流水線 a.指令之間資料依賴的時候 如存在對同乙個暫存器的讀寫依賴 b.指令之間存在控制依賴的時候 如條件轉移 注意的是,並不是只有兩條相鄰的指令才會存在依賴 只要是同時出現在流水線中任意兩條指令都可能出現依賴 以f fetch d decod...
優化程式效能 《深入理解計算機系統》
1 高階設計 適當的演算法和資料結構 2 基本編碼原則 使編譯器產生高效的 理解 編譯器 的能力和侷限性,消除不必要的內容 消除連續的函式呼叫 消除不必要的儲存器引用,要考慮是否為 同一位址 以上兩點,也是妨礙編譯器優化的主要因素,編譯器很難判斷以進行優化。3 低階優化 將乙個任務分成多個部分,利用...
深入理解計算機系統 優化程式效能學習筆記
迴圈展開 提高並行性 一些限制因素 理解記憶體效能 應用 效能提高技術 確認和消除效能瓶頸 當字串越長lower1與lower2的效率差距越大 不要過分關心可 的分支 錯誤的分支 影響可能會非常大,但是現代處理器中的分支 邏輯非常善於辨別不同的分支指令的有規律的模式和長期的趨勢。書寫適合用條件傳送實...