介紹


    AMD承諾在今年的八月末九月初推出采用K10微架構(gòu)的新型四核處理器。而采用新的微架構(gòu)的第一批處理器將是服務(wù)器Opteron芯片,它構(gòu)建在代碼名為Barcelona的基礎(chǔ)之上。令人遺憾的是,AMD還無法將當(dāng)前高頻版本的芯片投入大規(guī)模生產(chǎn)。目前,繼續(xù)提升四核處理器工作頻率遇到的障礙是高速度引起的高能耗,而這要比TDP(技術(shù)成套數(shù)據(jù))平臺實際允許的功耗高得多。隨著每次版本的更新以及更先進(jìn)生產(chǎn)工藝的出現(xiàn),工作頻率將不斷提高,而功耗不斷降低。到目前為止,AMD必須立即展開處理器的銷售活動來改善其財政狀況,因此,開始銷售的第一種芯片將是四核處理器,工作頻率為2.0GHz。


    AMD表示在2007年第4季,將提高Opteron的工作頻率至2.4~2.5GHz,同時發(fā)布K10架構(gòu)的桌面處理器,具體如下:


    • Phenom FX (代碼名Agena FX)  C 4 核,2MB L3高速緩存,時鐘頻率初始速度2.2~2.4GHz,AM2+插座,F(xiàn)+;


    • Phenom X4 (代碼名Agena)  C 4 核,2MB L3高速緩存,時鐘頻率初始速度2.2~2.4GHz,AM2+插座;


    2008年初,AMD將對新處理器進(jìn)行微小改動后推出新品,如:


    • Phenom X2 (代碼名為Kuma)  C 2 核,2MB L3高速緩存,時鐘頻率初始速度2.2~2.6GHz,AM2+插座;


    • Phenom X2 (代碼名為Rana)  C 2 核,未配置L3高速緩存,時鐘頻率初始速度2.2GHz,AM2+插座;


    • Sempron (代碼名為Spica) C 單核,時鐘頻率初始速度2.2~2.4GHz,AM2+插座。


    當(dāng)然,這些都還在醞釀之中,只是AMD將來的計劃。我們還是先了解一下AMD新型微架構(gòu)到底有哪些創(chuàng)新點。通過這篇文章,我會將新架構(gòu)的所有細(xì)節(jié)盡量全部展現(xiàn)給大家,讓大家了解它們到底有什么實際意義。


    獲取指令


    處理器對代碼的處理將從取指令開始,即從L1I指令的高速緩存和解碼開始。由于x86的指令長度并不相同,因此在開始解碼之前很難確定各指令的分界線。為了確保指令長度的識別不會影響解碼速度,當(dāng)指令行裝載入L2I高速緩存的時候,K8/K10處理器就開始對指令進(jìn)行解碼。而指令的標(biāo)簽信息則被存儲在L1I高速緩存的特殊字段中(指令的每個字節(jié)都有3bit的預(yù)解碼信息)。將指令載入高速緩存的過程中就進(jìn)行了預(yù)解碼,這樣各指令的邊界無需通過解碼信道就能確定,不受指令格式、長度的影響,保證了穩(wěn)定的解碼率。


    處理器從高速緩存裝載指令塊,然后取出并發(fā)送需要的指令進(jìn)行解碼。K10微架構(gòu)的CPU從排列成32字節(jié)塊的L1I高速緩存取出指令,而K8和Core 2處理器則是從16個字節(jié)塊中取出指令。在每個時鐘周期,K8和Core 2處理器都能快速從16個字節(jié)塊中取出指令,并發(fā)送3條平均長度為5個字節(jié)的指令進(jìn)行解碼。但是,有些x86指令可能長達(dá)16個字節(jié),而且在某些算法中幾個相鄰指令的長度也可能會超過5個字節(jié),因此,在這些情況下,就無法在每個時鐘周期內(nèi)對3個指令進(jìn)行解碼(見圖1)。
 




Pic 1: A few adjacent long instructions limit the decoding speed
during instructions fetch 16-byte blocks.


1


   換句話說,SSE2是個很簡單的指令,操作符為寄存器-寄存器類型,長度只有4個字節(jié)(如movapd xmm0, xmm1)。但是,如果指令提出了利用地址寄存器和偏移量進(jìn)行尋址存儲器的請求(如movapd xmm0, [eax+16]),那么指令的長度就要隨著偏移量的大小提高到6~9個字節(jié)。如果輔助寄存器涉及到64bit模式,就會給指令代碼附加一個字節(jié)的REX前綴。通過這種方式,64bit模式的SSE2指令長度就變成了7~10字節(jié)。如果它是個矢量指令(也就是說,如果它是4個32bit的值),那么SSE1指令還會再減少一個字節(jié)。但是如果它是個標(biāo)量指令(在一個操作對象上),那么在同等條件下,它的長度將是7~10個字節(jié)。


   在這種情況下,取出最大16字節(jié)塊指令并不是對K8處理器的限制,因為它無論如何也不能在2個時鐘周期內(nèi)對3個以上的矢量指令進(jìn)行解碼。但是,對于K10微架構(gòu)來說,16個字節(jié)塊指令就可能成為其瓶頸,因此將最大取出的塊大小提高到32個字節(jié)絕對是個正確的方向。


   順便說一下,Core 2處理器取16字節(jié)指令塊的情況與K8處理器一樣,這也是當(dāng)指令的平均長度不超過4個字節(jié)時,Core 2處理器能在每個時鐘周期有效地解碼4條指令的原因。否則,解碼器根本無法在每個時鐘周期內(nèi)有效地處理4條指令,有時甚至3條指令也不能有效完成。但是,Core 2處理器有一個專用的內(nèi)置64字節(jié)緩沖器可以存儲請求中最后4個16字節(jié)的指令塊。指令可以從緩沖器中以每個時鐘32個字節(jié)的速度取出。這個緩沖器允許指令儲存的周期很短,取消了取指令速度的限制,而且每次推測到周期開始時指令可以儲存一個時鐘周期。但是在每個時鐘周期內(nèi)不應(yīng)超過18條指令,也不應(yīng)該超過4個條件轉(zhuǎn)移,也不能包括任何返回指令。


   轉(zhuǎn)移預(yù)測


   如果一組指令發(fā)生了轉(zhuǎn)移,那么CPU就應(yīng)試著去推測程序下一個方向,以避免解碼發(fā)生中斷,同時繼續(xù)對大多數(shù)可能的轉(zhuǎn)移進(jìn)行解碼。在這種情況下,就要用到轉(zhuǎn)移預(yù)測運(yùn)算來取出下一個指令塊。K8處理器采用了兩級可調(diào)節(jié)運(yùn)算進(jìn)行轉(zhuǎn)移預(yù)測。這種運(yùn)算會考慮到預(yù)測歷史,不僅把包括當(dāng)前的指令而且還包括之前的8條指令。K8轉(zhuǎn)移預(yù)測運(yùn)算的主要缺點是無法動態(tài)地交替地址來預(yù)測間接轉(zhuǎn)移。


   間接轉(zhuǎn)移時要用到一個指針,在程序代碼執(zhí)行過程中通過它動態(tài)運(yùn)算。通常這些間接轉(zhuǎn)移會被編譯器插入變換格結(jié)構(gòu)中。在面向?qū)ο蟮某绦蛑姓{(diào)用尋址功能和虛擬功能時也會使用它們。K8處理器總是使用最后的轉(zhuǎn)移地址來獲得下一步取用的代碼塊。如果地址已經(jīng)發(fā)生了改變,那么該信道就會被清除。如果轉(zhuǎn)移地址偶爾發(fā)生了交替,那么處理器就會始終出現(xiàn)預(yù)測錯誤。間接轉(zhuǎn)移的動態(tài)改變地址的預(yù)測最先會在Pentium M處理器中推出。因為在K8 CPU中還沒有哪個運(yùn)算法則會比面向?qū)ο蟮拇a中的效率還低。


   正如我們所希望的那樣,K10改進(jìn)了條件轉(zhuǎn)移預(yù)測運(yùn)算:


   • 它能夠?qū)討B(tài)變化的間接轉(zhuǎn)移地址進(jìn)行預(yù)測運(yùn)算。這個運(yùn)算法則使用了512個元素的表。


   • 共用歷史寄存器從8bit提高到12bit。用它可確定之前的轉(zhuǎn)移指令的歷史。


   • 返回地址堆棧的深度也從12個位置提升到24個位置。利用這個堆??梢匝杆偃〉梅祷氐刂返暮瘮?shù),從而使得取指令能夠持續(xù)下去,而且也不用等待返回指令就可以接受堆棧返回地址。


   這些性能的改進(jìn)都會幫助K10能更快速地執(zhí)行由高級面向?qū)ο蟮拇a編寫的程序。但是遺憾的是,很難客觀地估算出K10轉(zhuǎn)移預(yù)測單元的效率。在某些情況下,它處理一些數(shù)據(jù)的效率可能會比Intel處理器低。


   解碼


   從指令高速緩存接收到的數(shù)據(jù)塊會被復(fù)制到Predecode/Pick Buffer中,在這里指令被選出,定義其類型,然后被發(fā)送到相應(yīng)的解碼通道中。可以用一個或兩個微運(yùn)算指令解碼的簡單指令會被發(fā)送到“DirectPath”解碼器中。那些需要三個或更多運(yùn)算指令才能解碼的復(fù)雜指令,則被發(fā)送給微程序解碼器,即VectorPath。




2:解碼器


   每個時鐘周期最多可以有3個微操作(MOP)離開解碼器信道。每個時鐘周期解碼器會處理3個簡單的單個MOP指令,或2 MOP指令和1個單獨的MOP指令,或1.52 MOP指令(在兩個周期執(zhí)行32 MOP指令)。要對復(fù)雜的指令進(jìn)行解碼可能需要3個以上的MOP操作,這也是他們需要幾個時鐘周期才能完成指令的原因。為避免在離開解碼器信道時產(chǎn)生沖突,K8K10處理器的簡單和復(fù)雜的指令可能會同時發(fā)送進(jìn)行解碼。


MOP由兩個微操作(micro-ops)構(gòu)成:一個是整數(shù)或浮點運(yùn)算操作,另一個是存儲器地址請求。微操作會由日程安排程序從MOP中選出發(fā)送后,彼此各自獨立地執(zhí)行。


每個時鐘周期離開解碼器的MOP會被組合成3MOP的小組。但是有時解碼器會產(chǎn)生由2MOP甚至只有1MOP的組,這是由于在選擇要解碼的指令過程中,DirectPathVectorPath指令發(fā)生了交替或各種延遲。像這樣不完整的組會被填上一個空的MOP后再發(fā)送執(zhí)行。


K8處理器中的矢量SSE, SSE2SSE3指令被分割成MOP對,由他們分別處理64bit設(shè)備中128bit SSE寄存器的上層和下層64bit數(shù)據(jù)。解碼的指令減少了一半,調(diào)度程序隊列中的指令數(shù)量也減少了一半。


好在K10處理器中有強(qiáng)大的128bit FPU單元,因此不需要再將矢量SSE指令再分割成2 MOP。K8過去解碼作為DirectPath Double的大多數(shù)SSE指令,現(xiàn)在在K10中解碼為1 MOP DirectPath。不僅如此,過去通過K8微程序VectorPath解碼器解碼的SSE指令,現(xiàn)在通過簡單的DirectPath解碼器就能解碼成較少的MOP1個或2個,這取決于具體的操作。


現(xiàn)在,堆棧指令的解碼也被簡化了。通常被CALL-RETPUSH-POP函數(shù)使用的大多數(shù)堆棧指令,現(xiàn)在也能由簡單的解碼器在單一的MOP中處理。而且,特殊的Sideband Stack Optimizer(邊帶堆棧優(yōu)化器)計劃會將這些指令轉(zhuǎn)換成相互獨立的、能同時執(zhí)行的微操作序列。


 


邊帶堆棧優(yōu)化器


 


新的K10處理器的解碼方案需要一個特殊的Sideband Stack Optimizer(邊帶堆棧優(yōu)化器)塊。它的工作原理與Core處理器中使用的新的Stack Pointer Tracker(堆棧指針追蹤器)單元相似。那么我們需要做些什么呢?x86系統(tǒng)使用CALL, RET, PUSHPOP指令來調(diào)用某函數(shù)、撤銷某函數(shù)、傳送某函數(shù)的參數(shù),同時還節(jié)省了寄存器的容量。所有這些指令雖然不是直接使用的,但是ESP寄存器卻會指出當(dāng)前堆棧指針的值。如果在K8處理其中調(diào)用某一函數(shù),你就能跟蹤些指令的執(zhí)行情況,只需將他們的解碼表示為連續(xù)的修改堆棧寄存器指令和裝載/保存指令的同等基本操作。















Instructions


Equivalent operations


// func(x, y, z);
push X
push Y
push Z
call func



sub esp, 4; mov [esp], X
sub esp, 4; mov [esp], Y
sub esp, 4; mov [esp], Z
sub esp, 4; mov [esp], eip; jmp func


push esi
push edi
mov eax, [esp+16]
……..
pop edi,
pop esi
ret


sub esp, 4; mov [esp], esi
sub esp, 4; mov [esp], edi
mov eax, [esp+16]
…………..
mov edi, [esp]; add esp, 4
mov esi, [esp]; add esp, 4
jmp [esp]; add esp, 4


add esp, 12


add esp, 12


 

從這個例子可以看出:調(diào)用函數(shù)時,指令會按照順序修改ESP寄存器,因此,下一個指令實際上取決于上個指令的執(zhí)行結(jié)果。在這個序列中的指令不能被重新排序,這也是以mov eax, [esp+16]開頭的程序不能執(zhí)行的原因,直到執(zhí)行了最后的PUSH指令。Sideband Stack Optimizer單元會追蹤堆棧狀態(tài)的變化,并將指令序列更改成獨立的指令序列。而這都是在指令直接與堆棧寄存器工作之前,通過為每個指令調(diào)整堆棧的偏移量,同時進(jìn)行同步MOP操作實現(xiàn)的。能與堆棧直接處理的這種指令可以重新排序,而不受任何限制。



















Instructions


Equivalent operations


 


// func(x, y, z);
push X
push Y
push Z
call func


mov [esp-4], X
mov [esp-8], Y
mov [esp-12], Z
mov [esp-16], eip; jmp func


 


push esi
push edi

mov eax, [esp+16]
……..
pop edi,
pop esi
ret


mov [esp-20], esi
mov [esp-24], edi
sub esp, 24
mov eax, [esp+16]
…………..
mov esi, [esp]
mov edi, [esp+4]
jmp [esp+8]




sync-MOP



add esp, 12


add esp, 12
add esp, 12


sync-MOP


 

在本例中,程序主體中開始運(yùn)算的mov eax, [esp+16]指令只取決于同步MOP操作?,F(xiàn)在,這些操作能與其他前面的指令同時運(yùn)行。通過這種方式加快了傳送參數(shù)、寄存器存儲的速度,而且程序主體也能開始裝載這些參數(shù),并進(jìn)行處理,即使所有的參數(shù)還未被成功傳送而寄存器也未完成存儲。


因此,更快速的堆棧操作解碼、Sideband Stack Optimizer單元、更深的返回地址堆棧以及成功地預(yù)測間接交替轉(zhuǎn)移,使得K10在處理多函數(shù)代碼方面效率更高。


每個時鐘周期,K10處理器解碼器無法象正常條件下Core 2解碼器那樣對4條指令進(jìn)行解碼。但是這不會成為執(zhí)行程序的障礙。在一個時鐘周期內(nèi),指令的平均處理速度很難達(dá)到3條指令,因此,K10解碼器對于隊列中不缺少任何指令的計算單元的處理效率很高,因此不會出現(xiàn)空閑狀態(tài)。

分享到

多易

相關(guān)推薦