一、引言
處理器(central process unit,簡(jiǎn)稱(chēng)CPU)是手機(jī)的核心部件,其主要功能是取指令并譯碼執(zhí)行。CPU主要包括控制器和運(yùn)算器兩個(gè)部件,它對(duì)在手機(jī)中的所有硬件資源(如存儲(chǔ)器,輸入輸出單元)進(jìn)行控制調(diào)配,執(zhí)行運(yùn)算。在系統(tǒng)中所有軟件層的操作,最終都將通過(guò)指令集映射為CPU的操作,因此,它的性能高低直接影響著用戶的體驗(yàn)。
得益于半導(dǎo)體工藝的進(jìn)步,架構(gòu)的演進(jìn),CPU的性能不斷地提升。然而,應(yīng)用程序(APP)的不斷發(fā)展對(duì)處理器性能有了更高的要求,要使得APP運(yùn)行的穩(wěn)定、流暢,軟件工作者要深入理解處理器的微架構(gòu),理解指令的執(zhí)行過(guò)程,做出一些更精細(xì)化的改善和優(yōu)化。
二、超標(biāo)量處理器簡(jiǎn)介
目前,手機(jī)處理器大部分是超標(biāo)量處理器(superscalar processor)。想要理解超標(biāo)量處理器,得先明白流水線技術(shù)。流水線技術(shù)是將一條指令分解為多個(gè)步驟(周期),并且每一個(gè)周期時(shí)間相同。
超標(biāo)量處理器的流水線中,允許多條指令同時(shí)存在。這樣一條指令不用等待它前面的指令執(zhí)行完畢,就有可能可以進(jìn)入處理器的后面得到執(zhí)行,這種方式提升了處指令并行性(ILP: instruction level parallelism),進(jìn)而提升性能。如上圖所示,當(dāng)處理器沒(méi)有使用流水線的時(shí)候,它的時(shí)間周期是D,在使用了n級(jí)流水線之后,一條指令的平均執(zhí)行周期變成了D/n+S,其中s表示為流水線中間的延遲。
如今,處理器的微架構(gòu)已經(jīng)趨于成熟,指令所經(jīng)過(guò)的部件和被處理的過(guò)程相似。一個(gè)典型的超標(biāo)量亂序處理器的組織結(jié)構(gòu)如下圖所示:
該處理器它包含了取指令(fetch),譯碼(decode),寄存器重命名(rename),發(fā)射(issue),執(zhí)行(execute),寫(xiě)回(write back),和提交階段(commit)。
三、處理器流水線介紹
前一小節(jié)介紹了超標(biāo)量處理器的組織結(jié)構(gòu),本小節(jié)將跟蹤指令的具體執(zhí)行過(guò)程,介紹處理器在每一個(gè)階段的行為。
1.分支預(yù)測(cè)/取指令
在取指令階段,除了需要從I-Cache中取出指令之外,同時(shí)還要決定下個(gè)周期指令的地址。而分支指令的結(jié)果只有在執(zhí)行階段才可以得出,因此,有必要對(duì)分支指令的行為進(jìn)行預(yù)測(cè),需要預(yù)測(cè)的內(nèi)容包含了跳轉(zhuǎn)方向和跳轉(zhuǎn)地址。
a.跳轉(zhuǎn)方向
分支指令可能是發(fā)生跳轉(zhuǎn)和不發(fā)生跳轉(zhuǎn),有些分支指令是無(wú)條件執(zhí)行的,它的方向總是發(fā)生跳轉(zhuǎn),其余分支指令則需要進(jìn)行預(yù)測(cè)。
對(duì)于分支指令方向的預(yù)測(cè),主要有以下4種方式:
首先,本文給大家介紹一個(gè)簡(jiǎn)單的分支預(yù)測(cè)
該方法直接使用上次分支的結(jié)果,相比于靜態(tài)分支預(yù)測(cè)在一些情況下可以獲得比較好的結(jié)果。如下圖,在10000次的for循環(huán)語(yǔ)句中,只有兩次預(yù)測(cè)失敗了,預(yù)測(cè)失敗率僅有2/10000=0.002%。
但是在一些情況下,預(yù)測(cè)的結(jié)果是不準(zhǔn)確的,如指令的方向不停的發(fā)生跳轉(zhuǎn),那么分支預(yù)測(cè)的預(yù)測(cè)失敗率可能接近100%.
i. 基于兩位飽和數(shù)的分支預(yù)測(cè)
兩位飽和數(shù)的預(yù)測(cè)方式在特定情況下有較好的預(yù)測(cè)結(jié)果,但其有一個(gè)極限值,因次后來(lái)處理器都放棄了這一做法。
ii. 基于局部歷史的分支預(yù)測(cè)
通過(guò)將它的每次跳轉(zhuǎn)或者不跳轉(zhuǎn)的結(jié)果記錄于BHR寄存器中作為歷史狀態(tài),然后通過(guò)PC值索引該表作為參考。如果一條分支指令的執(zhí)行結(jié)果很有規(guī)律,那么可以較好地預(yù)測(cè)正確率。
iii. 基于全局歷史的分支預(yù)測(cè)
與BHR相似,GHR寄存器記錄了最近所有的分支指令的執(zhí)行結(jié)果并作為預(yù)測(cè)。
i.競(jìng)爭(zhēng)的分支預(yù)測(cè)
基于BHR和GHR,在不同場(chǎng)景的應(yīng)用中,各有優(yōu)缺點(diǎn)。競(jìng)爭(zhēng)的分支預(yù)設(shè)計(jì)了一種自適應(yīng)的算法根據(jù)不同的場(chǎng)景自動(dòng)的選擇其中一種預(yù)測(cè)正確率較高的方法。
當(dāng)處理器預(yù)測(cè)了分支指令會(huì)跳轉(zhuǎn)之后,需要對(duì)目標(biāo)地址進(jìn)行預(yù)測(cè):
b. 目標(biāo)地址
i. 直接跳轉(zhuǎn):在指令中直接以立即數(shù)的形式給出了一個(gè)相對(duì)PC的偏移值。目標(biāo)地址是固定的,分支預(yù)測(cè)器可以準(zhǔn)確的找到地址;
ii. 間接跳轉(zhuǎn):分支指令的目標(biāo)地址在通用寄存器中,處理器通過(guò)獲取寄存器中的值,然后根據(jù)該值進(jìn)行跳轉(zhuǎn)。對(duì)于一些跳轉(zhuǎn)地址有規(guī)律情形,如call指令調(diào)用固定地址的函數(shù),return函數(shù)返回至函數(shù)調(diào)用的下一條指令,預(yù)測(cè)的結(jié)果比較準(zhǔn)確。其余一些不規(guī)律情形,預(yù)測(cè)它的跳轉(zhuǎn)地址則比較困難。
- 譯碼
指令解碼階段的任務(wù)是將指令中攜帶的信息提取出來(lái),這時(shí)候指令就變成了微操作(uop),處理器的后續(xù)階段將使用這些信息繼續(xù)執(zhí)行。對(duì)于CICS指令集,指令的長(zhǎng)度是不固定的,尋址方式也比較復(fù)雜,這增加了譯碼的難度。目前,在手機(jī)處理器中主要用的ARM系列處理器,其指令的長(zhǎng)度格式是格式固定的,如在32位處理器中:
- 寄存器重命名
接下來(lái),在超標(biāo)量亂序處理器中,指令將進(jìn)入寄存器重命名階段。首先,本文介紹關(guān)于相關(guān)性的概念。在處理器執(zhí)行過(guò)程中,指令之間存在一定的相關(guān)性,所謂的相關(guān)性是指一條指令的執(zhí)行依賴(lài)于另一條指令的執(zhí)行結(jié)果,指令之間的執(zhí)行順序不能夠改變,這制約了指令發(fā)射階段的選擇范圍。具體的依賴(lài)關(guān)系有如下三種:
先寫(xiě)后寫(xiě)(write after write):表示兩條指令都將結(jié)果寫(xiě)到同一個(gè)寄存器;
先讀后寫(xiě)(write after read):一條指令的目的寄存器和它前面某一條指令的源寄存器一樣;
先寫(xiě)后讀(read after write):一條指令的源寄存器來(lái)自于它前面某條指令的計(jì)算結(jié)果;
在采用亂序執(zhí)行的處理器中,寄存器重命名通過(guò)映射表將邏輯寄存器(指令中表示的寄存器)映射到物理寄存器(處理器中參與運(yùn)算的寄存器)解決了WAR 和WAW依賴(lài)關(guān)系,不存在依賴(lài)關(guān)系的指令可以同時(shí)執(zhí)行,提高了ILP(instruction level parallesim)。如下圖:
只有第二條指令的源寄存器r0依賴(lài)于第一條指令計(jì)算的結(jié)果,寄存器重命名之后,其余指令之間并無(wú)依賴(lài)關(guān)系。
- 發(fā)射
將符合一定條件的指令從發(fā)射隊(duì)列中選出來(lái),并送到FU(function unit)中去執(zhí)行。滿足發(fā)射條件是指指令的操作數(shù)準(zhǔn)備好了,F(xiàn)U數(shù)量充足。然而,對(duì)于訪存(load/store)指令,只有在執(zhí)行階段指令的地址被計(jì)算得出,它們之間的依賴(lài)關(guān)系才可以知道。處理器有一定的做法,來(lái)加速這種執(zhí)行方式。對(duì)于存儲(chǔ)指令加速的如下的三種方式,當(dāng)出現(xiàn)違例(memory vialotion)時(shí),在流水線的后續(xù)階段會(huì)進(jìn)行消歧處理。
- 完全的順序處理
- 部分的亂序指行,如下圖
- 完全的亂序指令
- 執(zhí)行
指令在執(zhí)行單元獲得執(zhí)行,典型的執(zhí)行單元有ALU,AGU,BPU。
- 寫(xiě)回
將FU計(jì)算的結(jié)果寫(xiě)到物理寄存器堆,并通過(guò)旁路網(wǎng)絡(luò)將這個(gè)計(jì)算結(jié)果送到需要的地方,喚醒依賴(lài)于這條指令計(jì)算結(jié)果的指令。如:
add r0, r1, r2 (1)
add r4, r0, r3 (2)
當(dāng)?shù)谝粭l指令的結(jié)果r0計(jì)算完成,它會(huì)通知第二條指令r0的值已近準(zhǔn)備好,那么這條指令才有可能變成準(zhǔn)備好的狀態(tài)并獲得發(fā)射執(zhí)行。
- 提交
程序的指令流順序進(jìn)入處理器,亂序執(zhí)行,并按照指令進(jìn)入ROB(Reorder Buffer,重排序緩存)的順序進(jìn)行提交這保證了程序執(zhí)行正確性。保留提交信息的關(guān)鍵部件是ROB,它的結(jié)構(gòu)如下圖:
當(dāng)一條指令到達(dá)流水線的這個(gè)階段時(shí),ROB會(huì)將這條指令標(biāo)記為complete狀態(tài),但是并不意味著可以提交了,比如異常,分支預(yù)測(cè)失敗等,一條已經(jīng)完成狀態(tài)的指令可能從流水線中抹掉。所以,在一條指令沒(méi)有退休(retire)之前,他的狀態(tài)都是推測(cè)的(speculative),
ROB本質(zhì)上是一個(gè)FIFO器件,存儲(chǔ)了一條指令的相關(guān)信息。如這條指令的類(lèi)型、結(jié)果、目的寄存器、和異常的類(lèi)型等。ROB的容量決定了流水線中最多可以同時(shí)執(zhí)行的指令的個(gè)數(shù)。每一個(gè)ROB的表項(xiàng)可以包括的內(nèi)容如下:
(1)complete, 表示一條指令是否已經(jīng)執(zhí)行完畢;
(2)Areg: 在原始程序中指定的目的寄存器,它以邏輯寄存器的形式給出;
(3)Preg:指令的Areg經(jīng)過(guò)寄存器重命名之后,對(duì)應(yīng)的物理寄存器編號(hào);
(4)Opreg: 指令的Areg被重命名為新的Preg之前,對(duì)應(yīng)的舊的Preg, 當(dāng)指令發(fā)生異常(exception), 而進(jìn)行狀態(tài)恢復(fù)的時(shí)候,會(huì)使用這個(gè)值;
(5)PC:指令對(duì)應(yīng)的PC值,當(dāng)一條指令發(fā)生中斷或者異常的時(shí),需要重新保存這個(gè)值;
(6)Exception,如果指令發(fā)生了異常,會(huì)將這個(gè)異常的類(lèi)型記錄,當(dāng)指令要退休的時(shí)候,會(huì)對(duì)這個(gè)異常進(jìn)行處理;
(7)Type:指令的類(lèi)型會(huì)被記錄到這里,當(dāng)指令退休的時(shí)候,不同類(lèi)型的指令會(huì)有不同的動(dòng)作,例如store指令要寫(xiě)入D-cache。
處理器的執(zhí)行過(guò)程中,錯(cuò)誤的分支預(yù)測(cè)也需要處理,這個(gè)執(zhí)行過(guò)程如下:
(1) 回滾:將在錯(cuò)誤路徑上的后續(xù)指令從流水線中“沖刷”;
(2) 重新取指:"正確的路徑上取出合適的指令執(zhí)行;
四、處理器性能建模
處理器的執(zhí)行過(guò)程中,理想狀況下,處理器運(yùn)行在穩(wěn)定的狀態(tài),沒(méi)有停頓和“汽泡”。然而總會(huì)有各種缺失(miss)事件導(dǎo)致性能的下降。根據(jù)區(qū)間模型理論,處理器的CPI(cycles per instruction)可以根據(jù)硬件PMU參數(shù)的值和參考硬件手冊(cè)中缺失事件的代價(jià),并通過(guò)公式進(jìn)行擬合。這些擬合的結(jié)果可以作為應(yīng)用負(fù)載的特性給處理器的調(diào)度作為參考。
五、影響處理器發(fā)展的三堵墻
- 功耗墻
功耗是影響處理器性能發(fā)揮的重要因素,尤其在是嵌入式設(shè)備如手機(jī)領(lǐng)域,手機(jī)通過(guò)電池供電,電池容量有限,所以處理器功耗不能過(guò)高。
Post-Dennardian(處理器供電電壓不變),系統(tǒng)增加S倍,但是因?yàn)楣╇婋妷翰蛔儯?a href="http://ttokpm.com/tags/電容/" target="_blank">電容減少了S倍,所以總功耗增大了S^2倍。為了保持總功耗不變,chip利用率將減小為以前的1/S^2。
- 訪存墻
處理器的性能在發(fā)展過(guò)程中有大量的提升,然而內(nèi)存受限于工藝,價(jià)格,帶寬和延遲等發(fā)展緩慢。處理器運(yùn)算速度和內(nèi)存訪問(wèn)速度不匹配。
- 編譯墻
不同處理器有不同的指令集,需要通過(guò)二進(jìn)制翻譯技術(shù)將一種處理器上的二進(jìn)制程序翻譯到另一種處理器上的可執(zhí)行程序,這可以擴(kuò)大了硬件、軟件的適用范圍,提高了兼容性。
六、總結(jié)
超標(biāo)量處理器是手機(jī)平臺(tái)的核心,處理器的微架構(gòu)在不斷地變化和演進(jìn)中,軟件工程師如何利用硬件特性,寫(xiě)出高質(zhì)量、高性能的代碼成為了一個(gè)難點(diǎn)和痛點(diǎn)。
本文詳細(xì)介紹了超標(biāo)量處理器的微架構(gòu),跟蹤了一條指令在處理器每一階段的具體執(zhí)行過(guò)程,讓讀者深刻理解了硬件行為。同時(shí),結(jié)合性能采樣分析工具如perf, vtune, simpleperf,讀者可以獲取程序的熱點(diǎn)(hotspot)或者性能瓶頸。然后,軟件工作人員可以通過(guò)讀取硬件數(shù)據(jù)PMU(Performance Monitor Unit),深刻理解處理器的性能瓶頸,對(duì)代碼做出針對(duì)性的調(diào)整、優(yōu)化。這可以充分發(fā)揮具體處理器的性能,進(jìn)而提升整個(gè)手機(jī)應(yīng)用的體驗(yàn)。此外,深刻理解處理器執(zhí)行方式,通過(guò)建模的方式,可以獲悉軟件應(yīng)用的負(fù)載大小,這為操作系統(tǒng)的調(diào)度提供了進(jìn)一步的思考。
處理器,特別是在手機(jī)平臺(tái)上的處理器,它的性能發(fā)揮受限于存儲(chǔ)墻,功耗墻,如何克服這些不利因素,提高未來(lái)手機(jī)的整體體驗(yàn),讀者可以進(jìn)一步思考。
-
處理器
+關(guān)注
關(guān)注
68文章
18930瀏覽量
227290 -
寄存器
+關(guān)注
關(guān)注
31文章
5254瀏覽量
119217 -
CICS
+關(guān)注
關(guān)注
0文章
3瀏覽量
5467 -
cache技術(shù)
+關(guān)注
關(guān)注
0文章
41瀏覽量
1033 -
for循環(huán)
+關(guān)注
關(guān)注
0文章
61瀏覽量
2472
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論