**
1.對暫存器的訪問的優化
暫存器訪問優化的核心是盡量避免打斷流水線.
a.指令之間資料依賴的時候(如存在對同乙個暫存器的讀寫依賴)
b.指令之間存在控制依賴的時候(如條件轉移)
注意的是,並不是只有兩條相鄰的指令才會存在依賴.只要是同時出現在流水線中任意兩條指令都可能出現依賴.
以f(fetch) d(decode) e(execute) m(access memory) w(write back) 模型為例.(任意兩個流水階段之前都有乙個cache,一般稱為流水線暫存器)
d階段任務中有一部分是要讀出指令中引用的應暫存器中的內容(例如要取srca暫存器).而暫存器的內容可能在e,m階段改變(寫).
假設d階段正常只要1個時鐘週期就可以結束,但是srca暫存器的內容,被前一條指令在e階段修改了(在流水線中相鄰的兩個階段對就**中相鄰的兩條指令).通過資料**(流水線中通過反饋迴路將各階段中對暫存器的修改直接送回給之後的流水線階段,這些值在延遲到w階段才會寫回到暫存器檔案.例如,e階段修改的值送回給d;m階段修改的值送回給e,d;w階段修改的值送回給m,e,d),要等到e階段執行結束後送回給d.
但是e階段有時候可能要多個指令周才能結束,比如浮點加法要3個時鐘週期.也就是說d必須要3個時鐘週期後才能完成.
對於控制依賴,最常見的就是分支**.
對應的如果在e階段之後,發現**的分支是錯誤的,就要將之後所有在流水線中的指令都"清空"(只要保證之後的指令沒有修改"程式設計師可見狀態"的前提下,將對應的流水線中的指令變成nop指令就可以)
2.對儲存器訪問的優化
核心是避免出現讀寫依賴.
方法:找到一小段程式的"關鍵路徑",畫資料流圖
關鍵路徑一般是資料流圖中
a.對同一暫存器讀寫.(比如下一步/迭代要讀取上一步/迭代修改過的暫存器)
b.對同一儲存器位置的讀寫.(比如下一步/迭代要讀取上一步/迭代修改過的儲存器)
特別的是對迴圈來說,確定兩次迭代之間有沒有這種資料依賴,可以計算出cpe(circle per execution)下界
常見優化
1. 確定對暫存器,儲存器的別名
別名一般是兩個指標,指向同一段記憶體,或者兩個指標儲存在同乙個暫存器中.
e.g. void swap(int *xp, int *yp){
*xp = *xp + *yp;
*yp = *xp - *yp;
*xp = *xp - *yp;
}這個函式,打眼一看你是操作兩個指標.
但是呼叫的時候,可以給兩個引數傳入相同的指標.
基於這種假設,編譯器認為這個指標變數可能對同乙個暫存器的操作.
void twiddle(int *xp, int *yp)
打眼一看,上面這個函式可能等於
void twiddle1(int *xp, int *yp)
但是如果xp,yp是相同的話,這個優化就是錯的.
2.確定函式的呼叫是不是有***
因為編譯器很能檢測出乙個函式呼叫是不是有***,所以它會假設所有的函式呼叫都有.
int f();
int func()
如果沒有***的話,可以優化成 int func()
但是如果f()有***的話,(例如每次呼叫都會修改某個全域性變數),那麼這個優化就是錯的.
3.減少函式呼叫(特別是在迴圈中)
4.消除不必要的儲存器引用
(通過增加臨時變數)
5.迴圈展開
6.提高並行性(使用多個臨時變數,只在必要的時候將多個臨時變數合併)
7.重新結合變換(基於結合律,改變計算順序,使得後續的計算不依賴前面計算的結果)
e.g.
acc = (acc op data[i]) op data[i+1];
每次迭代都要求前一次迭代必須結束才能開始,因為第乙個操作就要求讀取acc的值.
acc = acc op (data[i] op data[i+1]);
修改後,下一次迭代的開始可以先於當前迭代的結束,因為下一次迭代可以先計算data[i] op data[i+1]這個操作.
最後,再次強調amdahl定律
s=1/((1-a) + a/k);
s為加速比,
a為可加速部分的百分比
k為對a部分加速的倍數
這個定律告訴我們,在調優的過程中要關注"熱點"
優化程式效能 《深入理解計算機系統》
1 高階設計 適當的演算法和資料結構 2 基本編碼原則 使編譯器產生高效的 理解 編譯器 的能力和侷限性,消除不必要的內容 消除連續的函式呼叫 消除不必要的儲存器引用,要考慮是否為 同一位址 以上兩點,也是妨礙編譯器優化的主要因素,編譯器很難判斷以進行優化。3 低階優化 將乙個任務分成多個部分,利用...
深入理解計算機系統 優化程式效能(1)
1 優化編譯器的能力和侷限性 1 編譯器有自己能夠優化程式的能力,但會有侷限性。指標指向記憶體的同一位置 例如 void twiddle1 long xp,long yp void twiddle2 long xp,long yp 函式twiddle1需要6次記憶體引用 2次讀 xp,2次讀 yp,...
深入理解計算機系統 優化程式效能學習筆記
迴圈展開 提高並行性 一些限制因素 理解記憶體效能 應用 效能提高技術 確認和消除效能瓶頸 當字串越長lower1與lower2的效率差距越大 不要過分關心可 的分支 錯誤的分支 影響可能會非常大,但是現代處理器中的分支 邏輯非常善於辨別不同的分支指令的有規律的模式和長期的趨勢。書寫適合用條件傳送實...