什麼是指令飢餓?

在做性能測試的時候有個指令飢餓的指標,比如(Vtune),請問能否通俗地解釋一下什麼是指令飢餓?

另外想問問,這個指標比較高的時候,程序應該如何優化?


指令飢餓更多的是硬體上的概念. 它指處理器核心中, 前端取址解碼的速度小於後端執行的速度, 造成了處理器空有執行單元等待, 卻沒有指令供其執行的狀態.

為了講清前後端的問題, 貼一張Core處理器架構的簡圖: (取自Intel架構優化手冊)

簡化的說, 綠色部分是前端, 主要包括"取址", "解碼", "重命名"這麼幾個單元. 它最重要的特徵是指令在此是順序執行的, 且指令寬度一般大於1. 以這個Core架構為例, 解碼器每個周期最多可以翻譯4條指令, 並順序送給後端.

而橙色部分是後端, 主要包括"保存站", "重排序", "執行命令"這麼幾個單元. 它最重要的特徵是指令在這裡是亂序執行的. 亂序執行非常顯著的提升了處理器的運行效率. 如上圖所示, 這裡的Core架構有5個執行單元, "ALU Branch", "ALU FAdd", "ALU FMul", "Load", "Store", 因此Core結構的後端每個周期允許5個指令並行執行.

指令飢餓, 就是說後端比前端執行的更快.

簡單的說, 假設有一段代碼在Core架構上運行. 前端每個周期只能翻譯出來2條指令, 而後端每個周期卻能執行5條指令. 那麼很快前端的輸出就無法滿足後端的需求了. 後端有一些執行單元處於無事可做的狀態, 於是就發生了"指令飢餓".

指令飢餓的原因我想到的有二

一個是頻繁的Taken Branch. 由於每次分支預測失敗都會刷新全部前端流水線, 所以造成前端效率急劇下降, 甚至ICache Miss. 頻繁的預測失敗會導致後端無事可做.

另一個是指令格式, 比如非對齊的指令就會執行的很慢. 比如Core架構如果遇到改變操作數長度的指令(OS/AS前綴), 前端就會執行的很慢. 根據處理器前端設計的不同, 有處理器會對特殊指令敏感, 比如有處理器每一個周期只能翻譯一條Branch指令.

其中, 指令格式的問題, 更應該由編譯器來解決.

為了從軟體上解決Taken Branch的問題, 我想應該注重優化Branch相關指令. 比如減少不必要的分支; 將頻率高的代碼放在if而不是else; 盡量把冗餘的條件判斷條件提到for循環的外面等等. 這裡僅知一二, 還請各位高人補充.

===============================(完)================================

另提一句, 指令飢餓之所以是一種異常狀態, 是因為大部分情況下, 處理器核心的後端效率是小於前端的. 一個好處理器應該盡量讓後端滿載, 而不是前端.

2011年AMD發布的Bulldozer處理器架構, 就是因為2核心共用一個4發射的前端, 才使得後端空有性能卻無事可做.


Ricky Li 寫的很好,我來補充一下。

造成流水線前後端停頓的原因是很多的,分支預測只是其中一個,現在停頓最多的原因公認在memory hierarchy,也就是cache和memory上面。大約30%左右的指令需要訪存,在理想情況下(比如不考慮bank衝突),訪問一次L1 cache需要3~4個周期,L2 cache需要大概10個周期,L3 cache需要30~40個周期,Memory需要200個周期乃至更多。

所以訪問一次L1 cache,就需要在接下來的3~4個周期里調度一些不相關的指令來餵給後端,否則執行寬度就不能填滿,現在的4-issue結構下,如果要保證這一次L1 cache訪問期間處理器完全不停頓,就需要12~16條不相關指令,這要求處理器的亂序執行調度器在自己的調度範圍內拿出12~16條不相關指令來執行,亂序執行調度器所能控制的調度範圍是有限制的,這個調度窗口大概在一兩百條指令上下,比如Haswell是192.

訪存的代價太大,而亂序調度的窗口有限制,大部分情況下訪存的延遲是沒辦法完全蓋住的,cache和memory能夠同時接受的訪問請求也有限制,所以現在的4-issue處理器上,實際上每周期完成指令只有1.x左右,低的只有0.2不到,最高我也只見過2.0出頭。


pipeline stall ?

Instruction Starvation

Instruction Starvation


Ricky說的不錯,就是有一點不是太同意: 「 將頻率高的代碼放在if而不是else」。第一, 編譯器會任意安排代碼 第二 taken並不影響分支預測的結果。只有無規則的taken/not taken才影響預測器 但開發者做不了啥。 profilng guided optimization (PGO)或許有用


簡而言之就是CPU餓了想吃指令但是卻沒有指令給他吃!

譬如說一台機器8個CPU運行8個線程結果7個都在block。


推薦閱讀:

如何相对客观地衡量不同CPU/GPU之间的性能差异?(主要讨论arm和x86)?
英特爾 i 系列處理器二代、三代、四代有什麼改進?性能提升大嗎?
多核 CPU 和多个 CPU 有何区别?
為什麼有這麼多人歧視 AMD?
為什麼沒有128位甚至更多位的處理器呢?用不著?還是做不出來?

TAG:中央處理器CPU | Linux |