《CSAPP》優化程式效能 幫助編譯器讓程式更快

2021-07-07 10:00:13 字數 1902 閱讀 5808

前言:

我的github:

第五章:

準備工作:

一、高效程式的前提:

1. 合適的演算法與資料結構:這個其實是最重要的,有了乙個良好的資料結構與演算法,能把程式的時間空間複雜度降低很多。

2. 編寫編譯器能夠優化的高效源**:這裡實際上也就是不要給編譯器幫倒忙了,大部分編譯器已經能對源**進行非常好的優化了

3.使用多執行緒技術:這個就是在大量的計算的時候會用到。

二、編譯器的能力與侷限性:

1.編譯器只會很小心的對程式使用安全的優化:

這就意味著,許多在我們看來很明顯可以優化的行為,編譯器是不一定敢於優化的。這裡通常存在的不安全的原因是,如果出現了對同乙個儲存器的別名使用,就會有許多想不到的行為。所以在這裡,編譯器是沒法進行優化的。

2.選擇優化的級別:

在編譯時,可以通過-o1 -o2 -o3來選擇優化的級別,優化的級別依次遞增。

三、表示程式效能:

使用每元素週期數來表示程式的效能:這裡每個元素所用週期越長,那麼證明程式的速度越慢。

編寫優化的程式:

一、消除迴圈的低效率:

1.**移動:

把要在迴圈中計算多次,但是結果又不會改變的計算移動到迴圈之外。(對於編譯器來說,這是不安全的優化,因為不確定該計算**是否還有別的作用)

2. 減少呼叫過程:

在迴圈中呼叫函式,將會帶來壓棧與出棧的開銷,所以,對於簡單的返回值的函式,盡量使得其不需要使用函式來實現。

3.消除不必要的儲存器引用:

遇上累加等過程的時候,如果把每次操作的值都賦給儲存器,那麼必然效率不如使用乙個區域性變數。因此,應該讓區域性變數在迴圈中進行累加,最後再賦值給儲存器中的變數。

二、理解現代處理器:

1.指令並行與延遲界限:

在現代cpu中,如果幾個計算不會相互影響,那麼是可以同時在cpu中進行運算的。

延遲界限指一條指令,從開始到結束必須要經過的時鐘週期。該週期為最短週期,無法優化。

2.吞吐量界限:

由於處理器的並行,那麼存在有些運算是可以在處理器中同時進行的。比如說加法與乘法運算,那麼可以使用吞吐量界限來描述最多同時進行的運算操作所用時間。

3.關鍵資料流:

迴圈運算中,有些資料是不能同時並行運算的,他們必須乙個接乙個的運算,因為後一次運算依賴於前一次計算的結果。所以該計算流程就是該迴圈中的關節資料流。該資料流處理的必須用時,就成為了優化的界限。最好的優化也只能在這裡停止。

三、迴圈展開:

1. 迴圈展開是一種程式變換,通過增加每次迭代計算的元素數量,減少迴圈的次數。

該原理可以用來減少關鍵資料流的長度。

2. 提高並行性:

由於cpu是可以平行計算的,那麼對於累加和累乘,我們可以把結果儲存在多個變數中,在最後在合併結果。

3. 重新結合變換:

對於乙個計算表示式中,兩個連乘,我們可以使用括號,讓後一次乘法先進行,然後再進行前一次乘法。這樣做的能提公升程式速度的原理在於,如果使用順序乘法,第一次乘法結果與第二次乘法結果都會儲存在同乙個暫存器中,無形中增長了關鍵路徑。通過該優化方法,能使得關鍵路徑變短。雖然看起來什麼也沒做。

總結:

雖然針對編譯器優化有這麼多種的做法,但是實際上最重要的還是第一步,選擇合適的資料結構與演算法。畢竟只有選擇了合適方法,才能真正的在次方級別減少計算,而不是優化帶來的幾倍的效能提公升了。再完成了第一步之後,再來考慮更細緻的優化才有意義。

優化程式效能(CSAPP)

一 程式優化綜述 1 高效程式的特點 1 適當的演算法和資料結構。方法和資料的組織形式無疑是最關鍵的,是優化的基礎 2 能夠被編譯器轉化成高效的可執行 需要深入了解使用的編譯器的優化方法,和常見的優化策略 3 運用現代並行程式設計技術。多核以及硬體支援提供更大的加速可能,例如gpu 2 優化程式的一...

CSAPP 優化程式效能

1.選擇合適的演算法和資料結構。2.編寫出編譯器能夠有效優化以轉換為高效可執行的源 3.平行計算。當然重點還是第乙個,良好的演算法和資料結構大大減小了程式的時間複雜度。編譯器可以對程式進行不同程式的優化,在終端中,編譯時新增命令列選項 o1,o2等等可以進行不同級別的優化,這樣雖然提高了程式的效能,...

CSAPP 優化程式效能 二

程式示例 為了說明乙個抽象程式是如何被系統地轉換成更有效的 的,我們使用基於如下所示的向量資料結構的執行示例 向量由兩個記憶體塊表示,頭部和資料陣列,頭部宣告結構如下,data t代表基本資料型別 typedef struct vec rec,vec ptr 生成向量,訪問向量元素,確定向量長度的基...