效能工程

週期、指令與 IPC(每週期指令數)

/ IPC: eye-pee-SEE /

CPU 隨著一個時脈的節拍執行,每一拍就是一個週期(cycle)——一顆 3 GHz 的晶片一秒跳三十億拍。關於一段程式碼有兩個很自然的問題:它花了多少拍(週期),又完成了多少條機器指令(指令)?把一個除以另一個,你就得到一個極富資訊的單一數字:每週期指令數,IPC。

IPC 就是退役指令數除以經過的週期數,兩者都直接從 PMU 讀出。「退役」指真正完成並計入的指令,而非被丟棄的推測指令。現代 CPU 是超純量(superscalar)的,意思是它每週期能完成不只一條指令,所以好程式碼可以達到 2、3 甚至 4 的 IPC;IPC 遠低於 1 代表 CPU 大多數週期都在「停滯」——等記憶體、等它預測錯的分支、或等一條相依鏈——而不是在做事。倒數,每指令週期數(CPI),講的是同一件事的反面。關鍵洞見是:總時間 = 指令數 x CPI / 頻率,這把效能拆成三根獨立的槓桿:做更少指令(更好的演算法或更少工作)、降低 CPI(移除停滯,讓每條指令花更少週期)、或提高頻率(多半是硬體的事)。兩支程式可以跑相同的指令數,時間卻差 5 倍,純粹因為一支在停滯而另一支沒有。

它之所以重要,是因為 IPC 告訴你該拉哪根槓桿。IPC 很高卻還是太慢?你純粹是做太多工作了——去換更好的演算法,因為硬體每個週期都已經很忙。IPC 很低?CPU 在挨餓——去追停滯,通常是快取未命中或分支預測失敗。誠實的提醒:IPC 本身不是目標。把四條便宜指令換成一條昂貴的除法,可能「提高」IPC 卻讓程式更慢;而一個做事少很多的精簡演算法,可能 IPC 較低卻更早完成。要為總時間最佳化;用 IPC 去理解時間「為什麼」是這樣。

迴圈 A:10 億指令、5 億週期 -> IPC 2.0(忙碌,受運算束縛) 迴圈 B:10 億指令、40 億週期 -> IPC 0.25(大多停滯在快取未命中) 指令數相同,B 慢 8 倍。

指令數相同,時間卻天差地別:IPC 揭露迴圈 B 把週期花在停滯,而非運算上。

IPC 較高不必然較好:一條融合或向量指令在每個槽位做更多事,而用一條慢指令換掉好幾條便宜指令,可能提高 IPC 卻拖慢程式。永遠以總時間判斷,讓 IPC 去解釋它。

又称
instructions per cycleCPI (cycles per instruction)每週期指令數每指令週期數