終于講明白了!國外大神超詳細解讀:蘋果M1為什么比英特爾x86快了那么多?
2020-12-01 13:00:31 EETOP首先,M1 并不是一個簡單的 CPU。正如蘋果所解釋的那樣,它是一個系統級芯片,即一系列芯片都被安置在一個硅片封裝中。M1 容納了 8 核 CPU、8 核 GPU(部分 MacBook Air 機型為 7 核)、統一內存、SSD 控制器、圖像信號處理器、Secure Enclave 等大量模塊。這就是我們所說的片上系統 (SoC)。
M1 是芯片上的系統,這意味著組成計算機的所有部件都放在一個硅芯片上。
英特爾和 AMD 也在單一封裝中內置多個微處理器,但正如 Engheim 所描述的那樣,蘋果之所以有優勢,是因為蘋果沒有像競爭對手那樣專注于通用 CPU 核心,而是專注于處理專門任務的專用芯片。
計算機主板的示例。內存、CPU、顯卡、IO控制器、網卡等許多組件可以連接到主板進行相互通信。
然而,由于我們今天能夠將這么多晶體管放在硅芯片上,英特爾和AMD等公司開始將多個微處理器放在一個芯片上。今天,我們將這些芯片稱為 CPU 內核。一個核心基本上是一個完全獨立的芯片,可以從內存中讀取指令并執行計算。
我們今天能夠在一個硅芯片上放置如此多的晶體管,像英特爾和AMD這樣的公司開始在一個芯片上放置多個微處理器。我們將這些芯片稱為CPU核心。一個核心基本上是一個完全獨立的芯片,它可以從內存中讀取指令并執行計算。
很長一段時間以來,采用多核方式一直是提高性能的主要方法。但是現在CPU市場上有一家廠商正在背離這一趨勢,這就是蘋果公司。
蘋果并沒有增加更多的通用CPU核心,而是采取了另一種策略:他們開始增加更多的專用芯片來完成一些專門的任務。這樣做的好處是,專用芯片往往能夠在解決特定任務時比通用CPU核心耗電少的多,并且速度更快。
這并不是全新的知識。多年來已經有圖形處理單元(GPU)等專用芯片坐在Nvidia和AMD顯卡中執行與圖形相關的操作,速度比通用CPU快得多。
蘋果所做的只是朝著這個方向進行更徹底的轉變。M1并不只是擁有通用的核心和內存,而是包含了各種各樣的專用芯片:
這就是為什么很多人在M1 mac上進行圖像和視頻編輯時都看到了速度提升的部分原因。它們執行的許多任務都可以直接在特定的硬件上運行。這就是為什么一款便宜的M1 Mac Mini可以毫不費力地為一個大的視頻文件編碼,而另一款昂貴的iMac雖然所有的風扇都在全速運轉,但仍然跟不上。
藍色的是多個CPU核心訪問內存,綠色的是大量的GPU核心訪問內存
統一內存可能會讓你感到困惑。它和共享內存有什么不同?而且過去視頻內存與主內存共享難道不是一個糟糕的想法,性能很差嗎?沒錯,共享內存確實很糟糕。原因是CPU和GPU必須輪流訪問內存。共享就意味著要爭奪數據總線的使用權。基本上,GPU和CPU不得不輪流使用一個狹窄的管道來做數據交換。
但統一內存則并不是這樣的。在統一內存中,GPU核心和CPU核心可以同時訪問內存。因此在這種情況下,共享內存沒有開銷。另外CPU和GPU可以互相告知一些內存的位置。以前CPU必須將數據從其主內存的區域復制到GPU使用的區域。有了統一內存,更像是在說 :"嘿,GPU先生,我有30MB的多邊形數據,從內存位置2430開始"。GPU就可以開始使用該內存,而不需要做任何復制。
這意味著,通過使用相同的內存池,M1上的所有特殊的協同處理器都可以彼此快速交換信息,從而可以顯著提高性能。
在統一內存之前,Mac是如何使用GPU的?甚至還可以選擇使用Thunderbolt 3線纜將顯卡安裝在電腦之外。
如果蘋果所做的事情如此聰明,為什么不是每個人都這么做呢?在某種程度上,確實如此。其他ARM芯片制造商也在越來越多地投入專用硬件。
AMD也開始在他們的一些芯片上安裝更強大的GPU,并逐漸向SoC的某種形式發展,加速處理器(APU)基本上是CPU核心和GPU核心放在同一個芯片上。
AMD Ryzen加速處理單元(APU)將CPU和GPU(Radeon Vega)結合在一個硅片上。但不包含其他協處理器
然而,他們之所以不能做到這一點,有著重要的原因。SoC本質上是一個芯片上的整機系統。這使得它更自然地適合于真正的計算機制造商,比如惠普和戴爾。讓我用一個汽車類的比喻來說明,如果你的商業模式是制造和銷售汽車發動機,那么開始制造和銷售整車將是一個不尋常的飛躍。
相比之下,對于ARM公司來說,這并不是一個問題。計算機制造商(如戴爾或惠普)可以簡單地授權ARM IP,并購買其他芯片的IP,以增加他們認為其SoC應該具有的任何專用硬件。接下來,他們將設計完成后的產品送到GlobalFoundries或臺積電(TSMC)等半導體代工企業代工生產。
這里我們就會發現英特爾和AMD的商業模式存在很大的問題。他們的商業模式是建立在銷售通用CPU的基礎上的,人們只需將這些CPU插槽安裝到PC主板上即可。因此,計算機制造商可以簡單地從不同的供應商那里購買主板、內存、CPU和顯卡,并將它們整合成一個解決方案。
但在新的SoC世界里,你不會從不同的供應商那里組裝物理元件。相反,你從不同的供應商那里組裝IP。你從不同的供應商那里購買顯卡、CPU、調制解調器、IO控制器和其他東西的IP,并利用這些IP在內部設計一個SoC。然后找一個代工廠來制造這個東西。
現在你有一個很大的問題,因為無論是英特爾、AMD還是Nvidia都不會將他們的IP授權給戴爾或惠普,讓他們為自己的機器制造SoC。
當然,英特爾和AMD可能會簡單地開始銷售整個成品SoC。但這些要包含什么呢?PC制造商可能對它們應該包含什么有不同的想法。你可能會在英特爾、AMD、微軟和PC制造商之間就應該包含什么樣的專用芯片發生沖突,因為這些芯片需要軟件支持。
對于蘋果來說,這很簡單。他們控制著整個部件。他們可以給你例如Core ML的庫,讓開發者寫機器學習的東西。Core ML是在蘋果的CPU上運行還是在神經引擎上運行,這是一個開發者不必關心的實現細節。
讓任何CPU快速運行的基本挑戰
所以異構計算是一部分原因,但也不是唯一原因。M1上的快速通用CPU核心,叫做Firestorm,它確實非常的的快。這與過去的ARM CPU核心有很大的不同,過去的ARM CPU核心與AMD和Intel核心相比,往往性能非常弱。
相比之下,Firestorm擊敗了大多數英特爾核心,幾乎擊敗了最快的AMD Ryzen核心。傳統觀點認為這是不可能發生的。
在討論是什么使Firestorm如此快速之前,先了解一下設計更快速的CPU的核心思想到底有些什么?
原則上,你可以通過兩種策略的組合來實現:
在80年代,這是很容易實現的。只要提高時鐘頻率,指令就會更快完成。不過一條指令可能需要多個時鐘周期才能完成,因為它是由幾個小任務組成的。
然而,今天增加時鐘頻率幾乎是不可能的。這就是人們十多年來一直喋喋不休的“摩爾定律的終結”。
因此,它實際上現在更關心的是關于并行執行盡可能多的指令。
有兩種方法可以解決這個問題。一種是增加更多的CPU內核。從軟件開發人員的角度來看,這就像添加線程。每個CPU核心就像一個硬件線程。由于有兩個核心,CPU可以并發地執行兩個獨立的任務。這些任務可以被描述為存儲在內存中的兩個獨立的程序,也可以實際上是執行了兩次的同一個程序。每個線程都需要做一些記錄,比如線程當前在程序指令序列中的哪個位置。每個線程可以存儲臨時結果,這些結果應該分開保存。
原則上,一個處理器可以只有一個內核,運行多個線程。在這種情況下,它只需停止一個線程,并在切換到另一個線程之前存儲當前的進度。后來它又切換回來。這并不能帶來多大的性能提升,只有當一個線程可能會頻繁地停下來等待用戶的輸入、慢速網絡連接的數據等時才會使用。這些可能被稱為軟件線程。硬件線程意味著你有實際的額外的物理硬件,比如額外的內核,以提高速度。
這樣做的問題是,開發人員必須編寫代碼來利用這種優勢。有些任務,如服務器軟件,很容易這樣編寫。你可以想象單獨處理每個連接的用戶。這些任務彼此獨立,因此對于服務器,特別是基于云的服務,擁有大量核心是一個很好的選擇。
安培Altra Max ARM CPU 128核,專為云計算設計,有很多硬件線程是一個優勢
這就是為什么你會看到安培等ARM CPU廠商生產的CPU,比如Altra Max,它擁有瘋狂的128個核心。這種芯片是專門為云計算而生的。你不需要瘋狂的單核性能,因為在云計算中,每瓦都要有盡可能多的線程來處理盡可能多的并發用戶。
相比之下,蘋果則是完全相反的一端。蘋果制造的是單用戶設備。大量的線程并不是一個優勢。他們的設備用于游戲、視頻編輯、開發等。他們希望臺式機具有更快速的響應圖形和動畫能力。
臺式機軟件一般不是為了利用大量核心而制造的。例如,電腦游戲可能會從8個核心中受益,但像128個核心這樣的東西就完全是一種浪費。相反,你會想要更少但更強大的核心。
有趣的是,亂序執行是一種并行執行更多指令的方式,但不需要將這種能力暴露為多個線程。開發者不需要專門編寫軟件代碼來利用它。從開發者的角度來看,它只是看起來每個核心運行得更快。
要理解這個工作原理,你需要了解一些關于內存的事情。在一個特定的內存位置請求數據是很慢的。但是得到1個字節和得到比如說128個字節相比,在延遲上并沒有區別。數據是通過我們所說的數據總線發送的。你可以把它看成是內存和CPU不同部分之間的道路或管道,數據會被推送過去。如果數據總線足夠寬,你就可以同時獲得多個字節的數據。
這樣CPU每次都會得到一整塊指令來執行。它們被記錄下來,一個接一個地被執行。現代微處理器執行的是我們所說的亂序(OoO)執行。
這意味著它們能夠快速分析一個緩沖區的指令,并查看哪些指令依賴于哪些指令。請看下面的簡單例子:
01: mul r1, r2, r3 // r1 ← r2 × r3
02: add r4, r1, 5 // r4 ← r1 + 5
03: add r6, r2, 1 // r6 ← r2 + 1
乘法運算往往是一個緩慢的過程。假設它需要多個時鐘周期來執行。第二條指令必須等待,因為它的計算依賴于將被放入寄存器.r1的結果。
而第3條指令并不依賴于前面指令的計算。因此,亂序處理器可以開始并行計算這條指令。
然而,更現實的情況是,我們討論的是數百條指令。CPU能夠找出這些指令之間的所有依賴關系。
它通過觀察每條指令的輸入來分析這些指令。輸入是否依賴于一條或多條其他指令的輸出?我們所說的輸入和輸出是指包含以前計算結果的寄存器。
如:指令依賴于輸入由.產生的輸入。我們可以把這些關系串聯起來,形成一個復雜的長圖,CPU可以通過這個圖來工作。節點是指令,邊是連接它們的寄存器。
add r4,r1,5r1mul r1,r2,r3
CPU可以分析這樣的節點圖,并確定哪些指令可以并行執行,以及在執行之前需要在哪里等待多個依賴計算的結果。
很多指令會提前完成,但我們不能將它們的結果正式生效。并不能立即提交它們,否則會以錯誤的順序提供結果。指令的執行順序必須與指令發布的順序相同。
就像一個堆棧,CPU會不斷地從頂部彈出已完成的指令,直到碰到一條未完成的指令。
我們還沒有完全完成這個解釋,但這給了你一點線索。基基本上你可以有程序員必須知道的并行性,或那種CPU假裝好像一切都是單線程。然而,在幕后它卻在“亂施黑魔法”。
正是卓越的亂序執行力,讓M1上的Firestorm核心大放異彩,名聲大噪。事實上,它比英特爾或AMD的任何產品都要強得多。很可能比主流市場上其他任何處理器都要強。
為什么AMD和Intel的亂序執行不如M1?
在我對亂序執行(OoO)的解釋中,我跳過了一些重要的細節,這一點需要說明。否則就無法理解為什么蘋果走在前面,而英特爾和AMD未必能趕上。
我說過的那個大的“暫存器”實際上叫做“重新排序緩沖區”(ROB),它不包含正常的機器碼指令。不是CPU從內存中取出來執行的那些,而是CPU指令集架構(ISA)中的指令。也就是我們所說的x86、ARM、PowerPC等指令。
然而在CPU內部,它的工作原理是完全不同的指令集,程序員是看不到的。我們稱這些指令為微操作(micro-ops或μops)。ROB中充滿了這些micro-ops。
對于CPU來說這些微操作更加實用。原因是微操作非常寬(包含很多位),可以包含各種元信息。
你不能將此類信息添加到 ARM 或 x86 指令中,因為它會:
你可以把它想象成寫程序的時候。你有一個公共的API,需要穩定的,大家都在用。也就是ARM,x86,PowerPC,MIPS等指令集。微指令基本上就是用來實現公共API的私有API。
而且微操作對于CPU來說,通常比較容易操作。為什么這么說呢?因為它們每個都只做一個簡單的有限的任務。常規的ISA指令可能會比較復雜,導致一堆東西發生,因此實際上轉化為多個微操作。
對于 CISC CPU,通常別無選擇,只能使用微操作,否則大型復雜的 CISC 指令將使流水線和亂序幾乎不可能實現。
RISC CPU可以選擇。所以例如較小的ARM CPU根本就不使用微運算。但這也意味著它們無法做到OoO等。
但你想知道這些為什么重要嗎?為什么知道這些細節對理解為什么蘋果在AMD和Intel上占了上風很重要?
這是因為快速運行的能力取決于于你用微操作填滿ROB的速度和數量。你填滿的越快,它就越大,你就有更多的機會選擇你可以并行執行的指令,從而提高性能。
機器代碼指令被我們稱之為指令解碼器,解碼成微操作。如果我們有更多的解碼器,我們就可以并行解碼更多的指令,從而更快地填滿ROB。
這就是我們看到的巨大差異。最厲害的英特爾和AMD微處理器有4個解碼器,這意味著他們可以解碼4條指令并行輸出微操作。
但蘋果有一個瘋狂的 8 解碼器。不僅如此,ROB的體積是它的三倍。基本上可以容納3倍的指令。沒有其他主流芯片廠商的CPU里有那么多解碼器。
這是我們最終看到 RISC 可以“復仇”的地方,也是M1 Firestorm核心采用ARM RISC架構的事實開始變得重要的地方。
對于x86來說,一條指令可以有1-15個字節的長度。在RISC芯片上,指令的大小是固定的。為什么在這種情況下會有關系呢?
可以看到,對于x86來說,一條指令的長度可以是1-15字節。而在RISC芯片上,指令的大小是固定的。為什么這與本案相關?
因為如果每條指令都有相同的長度,那么將一個字節流分割成指令并行地輸入8個不同的解碼器就變得簡單多了!
但是,在 x86 CPU 上,解碼器不知道下一個指令從哪兒開始的。它必須實際分析每個指令,才能看到它有多長。
英特爾和AMD采用“粗暴”的方式來處理這個問題,首先它會簡單地嘗試在每一個可能的起點對指令進行解碼。這意味著我們必須處理大量的錯誤猜測和錯誤,而這些猜測和錯誤必須被丟棄。這就造成了一個錯綜復雜的解碼器階段,以至于很難再增加更多的解碼器。但對于蘋果來說,不斷增加更多的解碼器是很簡單的。
事實上增加更多的數量會導致很多其他問題,按照AMD自己的說法,4個解碼器基本上是他們能做到的上限。
這也是M1 Firestorm核心在同樣的時鐘頻率下,處理的指令數量基本上是AMD和Intel CPU兩倍的原因。
有人可以反駁說,CISC指令會變成更多的微操作,它們的密度更高,所以例如解碼一條x86指令更類似于解碼兩條ARM指令。
只是現實中并非如此。高度優化的x86代碼很少使用復雜的CISC指令。在某些方面它有RISC的味道。
但這對英特爾或AMD沒有任何幫助,因為即使那些15字節長的指令很少,也必須讓解碼器來處理它們。這就產生了復雜性,阻礙了AMD和Intel增加更多的解碼器。
但 Amds Zen3 核心仍然更快, 對嗎?
據我所知,最新的AMD CPU內核在性能測試中,被稱為Zen3的內核比Firestorm內核稍微快一些。但這里的關鍵是,這只是因為Zen3核心的時鐘頻率為5GHz,而Firestorm核心的時鐘頻率為3.2GHz。盡管Zen3的時鐘頻率比Firestorm高出近60%,但也只是勉強強過了Firestorm。
那么為什么蘋果不增加時鐘頻率呢?因為更高的時鐘頻率會使芯片更熱。這是蘋果的關鍵賣點之一。與英特爾和AMD的產品不同,他們的電腦幾乎不需要風扇。
從本質上說,人們可以說Firestorm內核確實優于Zen3內核。Zen3只是消耗更多功耗,才得以為此更高的性能。
未來
這并不意味著游戲結束。它們當然可以簡單地增加時鐘頻率,使用更多的冷卻,增加更多的核心,增強CPU緩存等等。但這些都處于劣勢。英特爾處于最糟糕的情況下,因為他們的核心已經被Firestorm徹底打敗了,而且他們有GPU也很弱。
添加更多核心的問題是,對于典型的桌面工作負載,過多的核心性能提升并不明顯。當然,大量的核心對于服務器來說還是非常有效的。