x86架構無法變身低功耗CPU?

作者 : 黃燁鋒,EE Times China

Arm證明自己也能做高運算力之後,仍有不少人認定x86做不了低功耗。有這樣的想法並不奇怪,畢竟Intel此前幾度嘗試攻佔手機市場都未能成功,但真的是這樣嗎?

以前低功耗和高運算力處理器是涇渭分明的。如Arm前身Acorn起家的立身之本就是低功耗——在Arm指令集發展的早些年頭裡,應該不會去想跟x86或者POWER這種向來進行高運算力的指令集及其生態一較高下。 低功耗領域,就算2013年蘋果(Apple)在iPhone發佈會上說A7晶片(Cyclone核心)是桌上型電腦等級的架構,消費市場幾乎也沒人當回事。從直覺來看,手機處理器、基於Arm指令集,還「桌上型電腦等級架構」?不是在作夢吧!直到蘋果將M1變為現實,與此同時Arm本身在資料中心市場越來越有所斬獲,才讓更多的人驚覺,那個靠低功耗起家的Arm也能做高運算力。 另一方面在高運算力方向,早年HPC和真正的高運算力設備是不大在意能耗問題的,無非是多用幾度電的事。就好像桌上型電腦插電工作,其功耗再如何都不能跟空調比;唯有筆記型電腦這種偶爾需要靠電池運轉的裝置,才將功耗納入考量。 但從2009年開始,越來越多的文獻指出高運算力裝置耗電驚人的證據。那時候有人比較HPC耗電和核電廠的發電量,超級運算要省電、資料中心要節約電費被提上日程。蘋果說Mac Studio比高階桌上型電腦每年減少1,000kWh的能耗;Nvidia說要是全世界所有AI、HPC和資料分析工作都跑Nvidia GPU伺服器,那每年的節電量相當於200萬輛汽車1年的耗電。 原本的低功耗指令集走向高運算力,而高運算力裝置也開始追求能效。但歷史遺留思想還在:就是某種指令集是針對低功耗的——不適合高運算力,以及某種指令集天然適合做高運算力——功耗低不下去。 Arm證明自己也能做高運算力之後,仍有不少人認定x86做不了低功耗。有這樣的想法並不奇怪,畢竟Intel此前幾度嘗試攻佔手機市場都未能成功;且x86 CPU在筆記型電腦PC平台的續航,大方向暫時無法和蘋果、高通(Qualcomm)這樣的Arm陣營選手一較高下;加上早年還有IBM用於伺服器的POWER下放給筆記型電腦處理器徹底失敗的案例在先,更讓人感覺功耗還是跟指令集強相關。 但…真的是這樣嗎? x86無法低功耗的爭論 指令集自然就是指一組指令了。那指令是什麼?加減乘之類的操作就是指令,1+1就是一個具體的指令。指令集之所以重要,究其根本是因為指令集是一個「抽象層」。 處理器是一種硬體晶片,上面有一大堆的電晶體,電晶體構成邏輯閘,邏輯閘構成功能模組,功能模組構成執行單元,各種控制和執行單元合起來,構成完整的處理器微架構,最終實現操作和複雜運算。這裡有一個問題,就是處理器作為一種硬體,如何與軟體溝通,或者說軟體如何讓處理器知道、理解自己要做什麼。  

(來源:Intel)

  指令集作為軟體和硬體之間的「抽象層」,就躍然紙上了。指令集是一組指令,定義在硬體中可以執行哪些類型的操作。它就像是個字典,指導軟硬體的溝通。對硬體而言,設計CPU需要以指令集為規範;對軟體而言,編譯器透過ISA將各種高階語言(如C、Java)編寫的程式碼轉化為機器程式碼指令。 所以Arm、x86、RISC-V之類的指令集,本質上定義了自家處理器及其生態的規範。x86指令集陣營選手主要有Intel、AMD;Arm指令集陣營選手主要有蘋果、高通、Ampere Computing等。這麼複雜的東西,當然不大可能以「白盒」的方式一點點剖析指令集對功耗有多大影響,但可以說說有關x86做不了低功耗的一些主流爭論點。 首先是老掉牙的複雜指令集(CISC)和精簡指令集(RISC)之爭。x86被認為是CISC方面的某種經典代表,而Arm隸屬於RISC。有關CISC適合進行高運算力,RISC則擅長低功耗的說法由來已久。 第二個比較常見的說法是,Arm採用定長指令,而x86為變長指令(即指令長度是不定的)。變長指令就意味著,CPU首先得搞清楚這指令有多長,就讓指令的解碼工作變得更複雜。解碼作為處理器工作的重要環節,就讓x86指令集處理器天然有了功耗方面的弱勢。 還有一個說法,x86作為一種生態龐大、歷史悠久的指令集,必然是拖著相容性這個毒瘤致老態龍鍾,而顯得冗雜、低效,所以無法達到低功耗。 有關RISC的古老傳說 在RISC這個概念於1980年代由David Patterson首度提出時,最初理念是讓指令集簡化,實現絕大部分指令都能在一個時脈週期內執行完成,這樣也就確保了較短的週期時間,以及更簡單的設計——CPU設計起來更容易、成本更低、更快。其核心理念在於,當大家都有100萬個電晶體的時候,那麼應該用執行更多小型指令的方法,實現更高的管線效率,而不是浪費在一大堆大型的複雜指令上。 不過有關CISC與RISC的論戰實在太多,但指令集與功耗高低的強相關,CISC與RISC之爭的確是個中關鍵。Chips and Cheese去年寫過一篇文章談Arm和x86之間是否真的存在誰更適合做低功耗的問題,也首先談到了CISC和RISC之爭。 實際在歷史發展長河中,所謂的CISC和RISC是在不斷趨同。一個經常被人提起的例子是,Intel從Pentium Pro時代開始引入μop (微操作),就是在處理器拿到某個複雜指令時,會將其先拆解為多個μop,再後續做執行。舉例來說,CISC支援一個數字直接去加上某個記憶體位址(中的數字),但對RISC而言——這個操作要分3步,就是先從記憶體位址中load數字,然後將其與現有數字相加,最後將數字再存回到記憶體。其實對近代CISC處理器而言,也會將原本1個指令拆分成這樣的3個微指令。 或許x86走向部分RISC特性的時間會更早。相對的RISC指令集也在幾十年的發展中,不斷汲取x86世界的既有技術,這兩者間的界限早就越來越模糊。如果說CISC和RISC從早年就劃分出高運算力和低功耗之別,那麼IBM POWER作為RISC指令集一員,曾在HPC領域風光一時,就已經徹底粉碎了這一傳說。 但基於CISC的傳說,延伸出的一個問題是x86引入了μop,令其更向RISC靠攏。這是否意味著Intel需要在指令執行前多一個步驟、多一些電晶體、多一些能耗來執行μop的拆分操作呢?這是此前不少人談論CISC不行的一大論據。     Arm的解碼開銷也不小 從Chips and Cheese的解釋來看,現代Arm指令集CPU也需要執行切分μop的操作。而且對不少Arm處理器(如Marvell的ThunderX晶片)來說,對μop階段的各種調整是作為架構更新的重要組成而存在的。 還有比較典型的像是這兩年很紅的超級電腦Fugaku,其中來自富士通(Fujitsu)的A64FX超級運算晶片同樣基於Arm指令集。從其架構手冊來看,A64FX也會將大指令解碼為多個μop。所以μop並不是CISC或x86的「專利」。 更何況還有Arm SVE (Scalable Vector Extension)/SVE2這種擴展指令更是會拆分成一大堆的μop。比如FADDA指令會切成63個μop,其中有部分μop本身的延遲就達到了9個週期;A64FX也支援直接從記憶體載入一個值,並執行相加操作,以及將結果存回記憶體中(LDADD指令),這樣一個指令會被切分成4個μop。在這樣的背景下談論CISC、RISC不再有任何意義。 另一個依據是,如果說Arm架構的解碼開銷真的那麼低,Arm也不會在微架構中導入μop cache了。導入cache就是為了避免重複的指令讀取和解碼——x86很早也已經開始這麼做。 Cortex-A77微架構中加入了1.5k條目的op cache。據說Arm對此下了不少功夫,光是debug其中設計就花了至少半年時間。後續Cortex-A78、A710,以及更大的Cortex-X1/X2微架構均有此設計。 三星在Exynos M5微架構(應用於Exynos 990晶片,Galaxy S11手機)中也採用了μop cache,作為向後續管線提供μop的途徑之一,以此來節約取指和解碼的功耗。可見以CISC和RISC之分,來說取指-解碼階段RISC的優勢,並證明x86做不了低功耗,在當代一點也不可靠。     變長指令對x86的實際影響 還有個問題就是,CISC的變長指令特性終究使其解碼不夠高效,因為指令長度不定就意味著首先需要明確一條指令有多長的問題,也是要浪費電晶體和功耗的東西。 其實業界對此做評估的研究和實驗還不少。Chips and Cheese曾經嘗試將op cache禁用(以便取指解碼操作必須進行),發現在這種情況下,AMD Zen 2核心層面需要多消耗4~10%的功耗,如果是封裝等級的話則多消耗0.5~6%的功耗。理論上,如果只將其中的解碼階段拿出來,則功耗佔比會更低。 而且Chips and Cheese還強調他們所做的測試只相關於L1 cache,而不曾涉及L2、L3 cache,以及主記憶體——如果考慮更多層級的儲存系統,那麼解碼階段在此佔據的功耗將低到可以忽略不計,以及對於某些關掉op cache,功耗反而降低的測試專案,解碼佔據的功耗數值已經湮沒在處理器核心的其他組成裡。 可見在開啟op cache以後,變長指令這一特性對於解碼的影響實則根本就沒有多大。更多系統性研究也顯示,對於Intel的x86處理器而言,解碼從來不是造高能效處理器的障礙;早期的Haswell和Ivy Bridge架構均有人驗證過。不過或許,「低功耗」低到某種程度,大概還是需要在功耗構成裡去挖一些部分出來,畢竟佔比小也不是沒有。 生態的影響 談論指令集這個問題,實則還涉及到「擴展指令集」。擴展指令集可以理解成向字典中添加新詞——新的指令是為了更高效地執行某些特定的操作,利用微架構中新出現的處理單元來加強某些特定工作的效率。Intel x86處理器中的SSE/AVX,Arm處理器中的Neon/SVE都屬於擴展指令集。 不過,這往往牽扯到生態問題,就是在添加了新的指令以後,開發者有沒有即時地用到這些指令。如果沒有,則意味著新設計浪費了,且效率上不去。一般PC實測媒體喜歡用Cinebench這個跑分工具,來測試某顆處理器的性能;為什麼總是選擇更新版本的Cinebench?而不堅持一直用老舊的Cinebench R15呢?  

Intel過往新增的擴展指令。

(來源:Intel)

  這是因為Cinebench R15程式本身連x86的AVX/FMA/AVX2都不支援,這對做出更新的處理器而言,豈不是無法反映性能提升?即便是最新版的Cinebench R23都尚不支援Intel x86的AVX512指令。真正做出AVX512,甚至更早AVX2指令最佳化的應用都不算多,尤其在PC應用市場。 比較有趣的一個例子是,先前蘋果M1 Ultra在Cinebench R23測試中的跑分成績比不上Intel Core i9。大量蘋果使用者表示Cinebench R23程式跑Arm Neon,是基於對x86 SSE的「轉譯」,使得M1晶片跑分成績大打折扣。本文不評論這個說法對不對,起碼這足以說明某一個指令集陣營的生態發展水準,也就是軟體側的發展情況,對其高運算力、低功耗與否也有很大的影響。 更專用的指令似乎是這兩年資料中心CPU和其他處理器發展的顯學,如Intel Sapphare Rapids的AMX指令集,主要針對AI運算。這類新特性的加入實則讓不同處理器間的效率比拼顯得更為複雜。 脫離指令集,在更高層級,例如蘋果M1 Max/Ultra的GPU堆料如此充沛,對最佳化好的應用有爆發力十足的性能和能效表現。但同時由於蘋果GPU生態的發展水準不怎麼樣,以致大部分應用跑在M1的GPU上效率都很糟,連一半的能力都發揮不出來。前不久紐西蘭的一位元資料科學家發了一篇文章談蘋果GPU的問題,提到天生的TBDR架構,以及32MB TLB配置,使大部分未能充分利用蘋果GPU架構特點的應用跑起來堪稱災難。 這和指令集的關聯已經不是那麼大了,但生態發展水準對各層級效率的影響顯然是需要納入考量。 關鍵並不在指令集本身 去年Jim Keller接受AnandTech採訪時說,「爭論指令集是很悲劇的事,核心執行的很大一部分工作就6個指令:載入、儲存、加、減、比較、分支,指令集本身真的關係沒那麼大。」他也提到了有關變長指令之類的問題討論,強調了變長指令問題並不大,尤其在有好的指令預測機制的情況下。 對處理器性能、功耗、能效真正產生影響的是前端如何餵飽後端,cache設計、分支預測、資料預取這些微架構實施層面的問題。Jim Keller就特別談到現在限制電腦性能的關鍵在可預測性上,包括指令/分支預測和資料本地性問題。 十多年前陸續就有向HPC系統導入低功耗處理器核心的研究,都是忌憚於HPC越來越控制不住的功耗。而這段時間指令集與功耗相關性的研究更是不少,如Energy Efficiency Evaluation of Multi-level Parallelism on Low Power Processors這份2014年的文章著重考察了Intel Atom處理器(Bonnell核心)與Arm Cortex-A9核心的性能和功耗。測試中Bonnell的表現是在性能和能效方面都碾壓當時的Cortex-A9,當然這只是孤證。 更早的Power Struggles: Revisiting the RISC vs. CISC Debate on Contemporary ARM and x86 Architectures則明確指出,Arm和x86不同處理器在功耗和性能方面的差異主要源自設計目標差異,指令集本身從來不是什麼重要決定因素。「指令集的差異,雖然可能會產生最終晶片設計實施方案上的影響,但現代微架構技術幾乎消除了這種差異;並不存在某一種指令集從根本上更加高效。」 本文原刊登於EE Times China網站        

發表評論

  1. Wesley Ting表示:

    討論半天,啥也沒說。

  2. 噗嚕^ↀᴥↀ^表示:

    在未突破基礎科學系統之前,所有在系統下的應用流派,都會在這個系統的極限前殊途同歸。