Intel, AMD及VIA CPU的微架構(4)

2021-08-07 22:03:55 字數 3545 閱讀 3177

用於p1的分支**機制與其他處理器差異極大。在intel文件及別處找到的,關於這個主題的資訊是誤導性的,遵循這些文件中給出的建議很可能導致次優的**。

p1有乙個分支目標緩衝(btb),它可以儲存最多256條跳轉指令的資訊。btb被組織為乙個4路組相連快取,每路64項。這意味著btb不能持有超過4個組值相同的項。不像資料快取,btb使用乙個偽隨機替換演算法,它意味著乙個新項不一定替換相同組值的最近最少使用項。

每個項包含乙個圖3.1所示的飽和計數器。顯然,設計者負擔不起乙個表示btb項是否被使用的額外位元。取而代之,他們同等對待狀態「強不採用」與「項未使用」。這是合理的,因為在p1中,乙個沒有btb項的分支被**為不採用。乙個分支不會得到乙個btb項,直到它第一次被採用。不幸的是,設計者決定第一次採用的分支,應該去到狀態「強採用」。這使得**器的狀態圖看起來像這樣:

圖3.4. p1中的分支**器

這當然是乙個次優的設計,我有充分證據,這是乙個設計缺陷。在乙個具有不超過4對指令的緊湊迴圈中,這時迴圈控制分支在btb有時間被更新之前再次被看到,飽和計數器的輸出被直接**到預取器。在這個情形中,狀態可以從「強不採用」變到「弱不採用」。這表示最初的預期行為正如圖3.1。intel工程師沒有注意這個缺陷,直到我在該手冊之前的版本裡發布了我的發現。

這個缺陷的後果是,一條大多數時間失敗的分支指令將比大多數時間被採用的分支指令,誤**率高出3倍。在組織分支時,你可以將這個不對稱性考慮在內,使得它們更多被採用。

p1裡btb機制是統計指令對,而不是單條指令,因此你必須知道指令如何組對(參考頁),以分析乙個btb項儲存在**。

;example 3.1. pentium 1 btb mechansim

shreax, 1

movebx, [esi]

cmpeax, ebx

jbl這裡shr與mov組對,cmp與jb成對。jb l的btb項附加在shreax, 1指令的位址上。。在遇到這個btb項,並**要採用該分支時,p1將從該btb項讀入目標位址,將l後的指令載入流水線。這發生在分支指令被解碼前,因此,在這樣做時,pentium單純依賴btb中的資訊。

在第一次執行時,指令偶爾成對(參考41頁)。如果上面的指令沒有成對,那麼btb項應該附加到cmp指令的位址上,在下一次執行,當指令成對時,這個項將是錯誤的。不過,在大多數情形裡p1足夠聰明,當還有未使用的成對機會時,不會製作btb項,因此直到第二次執行才會得到乙個btb項,因而直到第三次執行,才會得到**。(在很少見的情形裡,其中每隔一條指令是單位元組指令,可能在第一次執行就得到乙個在第二次執行無效的btb項,不過因為它所附著的指令將進入v-管道,它將被忽略且沒有損害。如果附著到一條u管道指令位址上,btb項是唯讀的)。

btb項通過組值(set-value)來識別,它等於附著位址的0-5位元。位元6-31儲存在btb中作為乙個標籤。相隔64位元組整數倍的位址具有相同的組值,相同的組值可以有不超過4個btb項。

這不是連續控制轉移指令的唯一問題。另乙個問題是,在乙個btb項及它所屬控制轉移指令間,可以有另乙個分支指令。如果第一條分支指令跳轉到別處,奇怪的事情可能發生。考慮這個例子:

; example 3.2. p1 consecutivebranches

shr eax, 1

mov ebx, [esi]

cmp eax, ebx

jb l1

jmp l2

l1:    mov eax, ebx

inc ebx

在jb l1失敗時,我們將得到jmpl2的乙個附著到cmpeax, ebx位址上的btb項。但當後面jbl1被採用時,將發生什麼?在讀jmpl2的btb項時,處理器不知道下一對指令不包含跳轉指令,因此它將事實上**指令對moveax, ebx / inc ebx跳轉到l2。**非跳轉指令為跳轉的懲罰是3時鐘週期。jmp l2的btb項將遞減其狀態,因為這適用於不跳轉。如果我們一直跳到l1,那麼jmpl2的btb項將遞減到狀態1或0,這樣直到jmpl2下一次執行,都沒有問題出現。

**非跳轉指令跳轉的懲罰,僅在**跳轉到l1時發生。在這個情形裡,jbl1被誤**為跳轉,流水線得到沖刷,l2的false目標沒有載入,因此在這個情形中,我們將看不到**非跳轉指令跳轉的懲罰,但jmpl2的btb項被遞減。

現在,假設我們以另乙個跳轉指令替換上面的incebx。這第三個跳轉指令將使用與jmpl2相同的btb項,**錯誤的目標可能會有懲罰。

總而言之,連續跳轉在p1中會導致以下問題:

·        當流水線被乙個前導誤**跳轉沖刷時,不能載入跳轉目標。

·        btb項被錯誤應用到非跳轉指令,並**跳轉。

·        上述的次要後果是,錯誤應用的btb項將被遞減,可能導致所屬跳轉的後續誤**。因為這個原因,無條件跳轉也會**為失敗。

·        兩條跳轉指令可能共享同乙個btb項,導致對乙個錯誤目標的**。

這一切可能帶給你諸多懲罰,因此在p1中,你絕對應該避免在乙個指令對中包含,緊跟著另乙個可**性差的控制轉移指令或者其目標的跳轉。另乙個展示例子:

; example 3.3a. p1 consecutivebranches

call p

test eax, eax

jz l2

l1:    mov [edi], ebx

add edi, 4

dec eax

jnz l1

l2:   call p

首先,我們可能注意到函式p從兩個不同的位置交替呼叫。這意味著從p返回的目標將一直變化。結果,從p返回將總是被誤**。

現在,假設eax是0。跳轉到l2將不會載入其目標,因為誤**的返回導致流水線沖刷。接著,第二個callp也不會載入其目標,因為jzl2導致流水線沖刷。這裡,我們處於由於第乙個跳轉被誤**,連續跳轉使得流水線不斷沖刷的狀態。jzl2的btb項儲存在t的返回指令位址處。現在這個btb項將錯誤應用於第二個callp之後,但這不會造成懲罰,因為誤**的第二個返回沖刷了流水線。

現在,讓我們看一下如果eax下一次有乙個非零值會怎麼樣:因為沖刷,jzl2總是**為失敗。第二個callp在testeax, eax位址處有乙個btb項。這個項將被錯誤應用到mov/add對,**跳轉到p。這導致乙個沖刷,阻止jnzl1載入其目標。如果我們之前已經在這裡,那麼第二個callp將在deceax位址處有另乙個btb項。在迴圈的第二次與第三次迭代時,這個項也將錯誤應用到mov/add對,直到它的狀態遞減到1或0。在第二次迭代時,因為來自jnzl1的沖刷,這不會導致懲罰,但在第三次迭代會。迴圈的後續迭代沒有懲罰,但在它退出時,jnzl1被誤**。現在,沖刷將阻止callp載入其目標,假如不是因為callp的btb項已經被多次錯誤應用所摧毀了。我們可以通過放置一些nop分隔開所有連續的跳轉來改進這個**:

; example 3.3b. p1 consecutivebranches

call p

test eax, eax

nopjz l2

l1:     mov [edi], ebx

add edi, 4

dec eax

jnz l1

l2:     nop

nopcall p

額外nop的代價是2時鐘週期,但它們節省更多。另外,jzl2現在移到u-管道,將誤**時的懲罰從4降到3。僅有的問題是從p返回總是被誤**。這個問題只能通過乙個內聯巨集替換對p的呼叫來解決。

Intel, AMD及VIA CPU的微架構(2)

從ppro開始的第六代intel微處理器,在微架構實際上,提供了乙個重要的,稱為亂序執行的改進。思想是,如果由於輸入資料尚不可用,一條特定指令的執行被推遲,那麼處理器將嘗試在後續指令中找出它可以執行的第一條,如果該指令的輸入資料已就緒。顯然,微處理器必須檢查後續指令是否需要前面指令的輸出。如果每條指...

intel AMD平台主機板等級分類

intel平台的主板晶元組 市面上常見的有x z b h 4個等級 不同等級搭配的cpu也有所不同 x 級定位發燒級 一般搭配的cpu效能十分強悍,例如目前在售的x299主機板有2066個針腳,可搭配i9 7920x i9 7980xe等處理器使用,昂貴。z 級定位高階級別 是民用級別裡面最高的,支...

mysql三大正規化及資料約束及查詢及儲存過程

資料約束 連線查詢 多表查詢 儲存過程 引數型別 會話變數 變數只在當前連線會中有效 區域性變數 帶有輸入輸出引數的儲存過程 帶有判斷條件的儲存過程 帶有迴圈條件的儲存過程 接收表中的資料的儲存過程 觸發器create table student id int,name varchar 20 gen...