?? ??相信各位一直會有相同疑惑:為何今天的x86 處理器市場,臺面上只剩下英特爾和AMD 兩家美國公司?頂多再加個存在感稀薄的臺灣VIA,和少人知悉的俄羅斯Elbrus?對技術(shù)有點基礎(chǔ)認知的人,多少會直接想到「x86 指令集很復(fù)雜很難搞,又有英特爾的授權(quán)問題,所以x86 處理器非常不好做」之類的標(biāo)準(zhǔn)答案。
當(dāng)然,更不乏某些夜郎自大的高論,像「就算x86 指令集再復(fù)雜,控制單元也還是很好設(shè)計」、「微指令轉(zhuǎn)譯早就克服了所有x86 指令集的瓶頸」等。拜托,「做出勉強能動的東西」和「開發(fā)出有市場競爭力的產(chǎn)品」完全是天差地別的兩件事,要不然你以為英特爾和AMD 天文數(shù)字般的產(chǎn)品開發(fā)經(jīng)費,都拿去填海了嗎?
總之,高效能x86 處理器之所以難做,混雜了諸多技術(shù)和商業(yè)因素,暗藏在臺面下的細節(jié)非外人足以道也。但我們可以回到x86 處理器最重要的歷史轉(zhuǎn)捩點:1993年P(guān)entium 處理器,抽絲剝繭一般人難以察覺到的蛛絲馬跡。 以「唯偏執(zhí)狂得以生存」(Only theParanoid Survive)留名于世的英特爾創(chuàng)辦人之一安迪·葛洛夫(Andy Grove) 曾經(jīng)說,2003 年的Centrino 是英特爾的「第二個兒子」與「十年來最重要的品牌」 ,那「第一個兒子」和「十年前最重要的品牌」,想當(dāng)然爾就是1993 年的Pentium 了。
Pentium 之名起源于希臘文的Penta(意思是「五」),再加上拉丁文的ium 結(jié)尾,意指「第五代x86 處理器」,英特爾自此也不再使用80×86 來定義處理器世代(要不然現(xiàn)在還真的講不出來到底是「幾86」)。而Pentium 也在不知不覺中,一步步轉(zhuǎn)型為入門級低價處理器品牌,更不再受限于1993 年的P5,進而橫跨歷代英特爾的超標(biāo)量(Superscalar)x86 微架構(gòu)。
原始Pentium 里的P5 處理器微架構(gòu),并沒有像后繼Pentium Pro 的P6 活得如此之長,影響又如此深遠(到2011 年Sandy Bridge 才結(jié)束)。但Pentium 問世的時機,卻是眾多歷史機運的集大成:
「x86 處理器走向高效能化」。
「x86 開始與RISC 正面競爭」。
「x86 指令集的缺陷讓廠商感到棘手」。
「x86 處理器進軍多處理器平臺」。
「個人電腦市場因Windows 95 的問世而蓬勃成長」。
「筆記本電腦即將逐漸普及」。
「英特爾默默埋下讓擅長改良的以色列海法研發(fā)團隊,主導(dǎo)x86 處理器技術(shù)發(fā)展」。
「x86指令集的兼容性,成為其他競爭者的潛在障礙,也造成軟件開發(fā)商的困擾」。
這些因素交錯,奠定了之后25 年技術(shù)演進與市場發(fā)展的基礎(chǔ)邏輯,連時下「AMD 處理器的核心太多,竟然造成Windows 操作系統(tǒng)的大麻煩」,也和Pentium 留下的遺產(chǎn),多少有些千絲萬縷的糾結(jié)。 既然連AMD Zen成功的背后,都有這么多不為人知的故事,了解英特爾「Landmark」芯片Pentium的軌跡,將有助跳脫琳瑯滿目的技術(shù)營銷名詞,重新建立屬于自己的「x86處理器世界觀」,值得各位細細品味。
x86 指令集先天不足后天失調(diào)的原罪
催生「計算機結(jié)構(gòu)」(ComputerArchitecture)一詞的「指令集架構(gòu)」(Instruction Set Architecture),為「電腦的基礎(chǔ)語言」與「軟硬件中間的接口」(Interface Between Hardware and Software),相同指令集的電腦理應(yīng)可執(zhí)行一樣軟件,具備彼此兼容性,對電腦與處理器微架構(gòu)(Microarchitecture)的未來發(fā)展有舉足輕重的影響力。
不同的時空背景,也會產(chǎn)生相異的指令集設(shè)計理念,沒有絕對的優(yōu)劣對錯──x86算是少見的例外,另一個則是DEC VAX,兩者的共同點只有「著毋庸議」的糟糕,英特爾IA-64(Itanium)和DEC Alpha的激烈反動,足以證明連生父都如此厭惡小孩。
? 說到指令集架構(gòu)如何影響處理器微架構(gòu)的設(shè)計,這幾年來最有名的實例,就是蘋果利用充分掌握封閉平臺的優(yōu)勢在「最短時間內(nèi)驅(qū)逐32位元應(yīng)用程序」,掌握ARM指令集邁向64位元的過程帶來的改革與機會,讓A7之后的自家ARM處理器,徹底為64位元的ARMv8-A量身訂做,研發(fā)出一系列能同時有效處理更多指令的先進微架構(gòu)。
所謂的CISC(復(fù)雜指令集電腦)出自存儲器容量稀少、缺乏成熟的高級語言編譯器、大多數(shù)人使用語言撰寫程序的時空背景,程序設(shè)計者寄望直接用透過微碼(Microcode)組成功能強大的單一指令,像十進位數(shù)字和復(fù)雜字串處理等,撰寫應(yīng)用程序。 相較之下,RISC(精簡指令集電腦)則是在「萬事皆備」的環(huán)境,追求更快更便宜的電腦,將晶體管預(yù)算砸在「最經(jīng)常被使用的簡單指令和運算元定址模式」的刀口上,盡量用硬件線路去取代微碼,并藉由強制僅載入(Load)/儲存(Store)指令可存取存儲器,搭配大型化的數(shù)據(jù)寄存器與快取存儲器,填補處理器和存儲器之間越來越大的效率鴻溝。
時過境遷,在x86 主宰云端數(shù)據(jù)中心、中低端服務(wù)器、工作站、桌面機一路到筆電的今日,可能已經(jīng)沒有多少人能回想起「RISC 與CISC 之爭」曾發(fā)生在1990 年代初期的史跡,但畢竟x86 指令集公認是充滿缺陷的產(chǎn)物,連當(dāng)代最偉大的計算機結(jié)構(gòu)教科書都「白紙黑字」并「燒錄」于無數(shù)莘莘學(xué)子的腦中,而AMD K5 的創(chuàng)造者更是用一句「毫無道理可循」(it just doesn'tmake a lot of sense)一錘定音,幾無爭議空間。 讓人滿臉黑線的,只有動輒揮出「逆向思考全壘打」的大恩大德,將x86 的市場勝利,視為「x86 指令集架構(gòu)優(yōu)良」佐證的天真論點,并時有所聞,連ARM 都比x86 更「存儲器存取密集」(Memory-Intensive)這種話都講得出口。
我們先來瞧瞧當(dāng)年AMD K5 的總工程師Mike Johnson 怎么評論x86 指令集,由設(shè)計x86 處理器的大師級人物(他本人的確是超標(biāo)量流水線技術(shù)的先驅(qū)者,那份變成首本超標(biāo)量技術(shù)專書的史丹佛大學(xué)博士論文非常有名,附錄更深度分析設(shè)計超標(biāo)量x86 處理器的困難點)寫出來的批評,特別有說服力,也一再被后人引述:
從這短短一段話,可看到幾個重點: 「毫無道理可循」(doesn't make a lotof sense):相較于指令編碼程度統(tǒng)──4 Bytes(32 bits)的多數(shù)RISC體系,x86指令集的格式和編碼極度混亂,長短粗細肥瘦不一,從1~17 Bytes都有可能。影響所及,遍及所有的環(huán)節(jié),從快取存儲器擷取指令、實作指令流水線化,到處理器發(fā)生中斷例外時要迅速儲存執(zhí)行狀態(tài)并盡快回復(fù)等,都造成非常嚴重的后遺癥,激增研制高效能x86處理器的門檻,也增加驗證產(chǎn)品的時間與成本。
「缺乏足夠的寄存器」(the lack ofregisters):一般RISC指令集都會定義32個通用數(shù)據(jù)寄存器(講的精確一點是31個)或浮點運算寄存器,但x86在64位元和AVX之前,怎么樣都只有少少的8個(因為要扣掉ESP和EBP,說6個或許比較貼切)。當(dāng)引進指令流水線化和更先進的超標(biāo)量流水線后,自然就激增了寄存器沖突的機率,這也是激發(fā)x86處理器擁有強大非循序指令執(zhí)行(寄存器重新更名)與高效率存儲器子系統(tǒng)的主因。
「讓人感到極度痛苦的定址模式」(extremelypainful addressing scheme):定址模式講得白話一點是「存取所需運算元(運算的目標(biāo),例如某個寄存器或某個存儲器位址)的方式」,歷經(jīng)多年疊床架屋的x86定址模式,尤其是惡名昭彰的節(jié)區(qū)存儲器(Segmentation),不只加重產(chǎn)生有效位址的工作負荷,也激增整數(shù)邏輯運算(ALU)和控制單元的復(fù)雜度,「副作用」跟第一項「毫無道理可尋」可謂不相上下。
這些燙手山竽,就是1980 年代末期和1990 年代初期,眾多企圖研制高效能x86 處理器的有志之士,包含不小心制造出這些「炸彈」的英特爾,不得不面對并設(shè)法克服的挑戰(zhàn),身為x86 世界首顆「超標(biāo)量(Superscalar)流水線」處理器的Pentium,則是第一個提出的「有效解決方案」,英特爾為此付出了不小代價。
一個時鐘周期執(zhí)行一個以上指令的「超標(biāo)量流水線」 近似近代工業(yè)生產(chǎn)線的概念,讓所有人都「閑閑有事做」的流水線化(Pipeline)一直是提高效率的最基本手段,80386 的預(yù)先指令擷取(Prefetch)已有雛型,而80486 是x86世界首款真正達成指令流水線化的處理器,為了確保存儲器跟得上運算需求,也配置指令/數(shù)據(jù)共用的第一階快取存儲器,雖然真正「每個時鐘周期都可穩(wěn)定輸出」者,也只限于簡單的整數(shù)邏輯運算指令。
「一個時鐘周期內(nèi)執(zhí)行一個以上指令」的超標(biāo)量流水線(Superscalar),早在1965 年發(fā)跡于RISC 始祖的CDC6600,1980年代陸續(xù)出現(xiàn)在RISC 處理器,如1985 年P(guān)ower 前身的IBM「America」計劃(也是「超標(biāo)量」一詞由來)、1988 年Motorola MC88100、1989 年英特爾i960CA、1990年AMD 29050 等。各位絕對沒看錯,英特爾、AMD 也做過RISC 處理器。 指令流水線化、超標(biāo)量流水線、非循序指令執(zhí)行、大型化快取存儲器等常見的效能加速手段,清一色優(yōu)先降臨RISC 處理器的原因,也很簡單:RISC 指令集的單純性與簡潔性,讓設(shè)計者更輕易導(dǎo)入這些技術(shù),并用更短的時間完成產(chǎn)品開發(fā)與驗證。
1990 年代上半期,一提到高效能處理器,幾乎都由RISC 獨領(lǐng)風(fēng)騷,像至今碩果僅存的IBM Power、HP 的PA-RISC、SGI 的MIPS、Sun 的UltraSPARC、Fujitsu 的SPARC64及充滿傳奇色彩的DEC Alpha 等,這也是「RISC 優(yōu)于CISC」的理論基礎(chǔ)。 但「理論」是一回事,不代表CISC 的x86「實務(wù)上」做不到,更何況又是擁有一整支龐大「研發(fā)軍隊」的英特爾,革命性的第五世代x86處理器Pentium 在1993年3 月22 日登上歷史舞臺,不只要迎擊來自AMD、Cyrix、NexGen(被AMD 購并,Nx686 變成K6)的競爭產(chǎn)品(之后還多出Centaur 和Transmeta),更要面對AIM 聯(lián)盟(Apple、 IBM、Mororola,不是美國的空對空飛彈)PowerPC 的挑戰(zhàn),后者享有威鎮(zhèn)四方的「RISC 王者」IBM Power 當(dāng)強大后盾,市面更不乏「專書」鼓吹PowerPC 相對x86 的優(yōu)越性,把Pentium批評得一文不值。
更扯的是,意圖搶奪英特爾勢力范圍的IBM 還開發(fā)了「腳位與Pentium 兼容,可以同等效率硬件執(zhí)行x86 程序碼,并兼具32 / 64 位元PowerPC 指令集兼容性」的PowerPC 615,要不是微軟可能覺得難搞,不符成本效益,拒絕支持這顆處理器,導(dǎo)致永遠無法量產(chǎn),英特爾的處境會更危險。至于PowerPC 615 取消后,研發(fā)團隊就投靠Transmeta,接著就無疾而終了。
也許各位難以想像「為什么x86 會受PowerPC 威脅,不是屬于不同市場嗎」,但此時此刻,沒半個正常人會將連服務(wù)器市場邊都沾不上的x86 和「高效能」三個字聯(lián)想在一起,甚至連那時候英特爾內(nèi)部,都很少人愿意相信x86 還有未來性,否則也不會出現(xiàn)IA-64 指令集和Itanium 處理器了。況且微軟1993 年7 月發(fā)表未來操作系統(tǒng)基礎(chǔ)的WindowsNT,打從一開始就同時支持x86、MIPS 和Alpha 三版本,之后還加碼PowerPC 和IA-64,「不將雞蛋放在同一個籃子里」意圖太明顯了。
換句話說,英特爾當(dāng)時的戰(zhàn)略地位,并不像今天如此牢不可破,更早在1990 年同步啟動第六世代Pentium Pro 研發(fā)案,完全沒有承受失敗的本錢與余裕。 天底下沒有白吃的午餐 Pentium 是如假包換的x86 世界首款超標(biāo)量處理器,可在同一個時鐘周期內(nèi)執(zhí)行最多兩個指令,整體結(jié)構(gòu)近似雙重流水線的「放大發(fā)展版」80486,但也因扛著x86指令集的原罪,由外到內(nèi)付出了不少代價。爬文至此,建議各位回頭復(fù)習(xí)一次Mike Johnson 評論的3 個重點,你一定會更有感觸。
我們光從初代Pentium(P5)的晶粒圖,即可清楚看到x86 兼容性的代價:大型化的快取存儲器(盡管實質(zhì)容量不高,但內(nèi)部結(jié)構(gòu)卻出奇復(fù)雜)、巨大的指令擷取單元、解碼與復(fù)雜指令微碼控制單元(Complex Instruction Support),這也是日后所有高效能x86 處理器的共同特色。
? 指令/數(shù)據(jù)分而治之的第一階快取存儲器:x86指令集因缺乏足夠的數(shù)據(jù)寄存器,且包含了大量「寄存器/存儲器互通有無」與直接以存儲器為運算目標(biāo)的指令,不像RISC的「載入/儲存」架構(gòu)「一次從存儲器抓了大量數(shù)據(jù)進來,算完后再一次性丟回存儲器」,特別需要強力的存儲器子系統(tǒng),所以采用指令/數(shù)據(jù)分開的第一階快取存儲器,確保兩邊足以喂飽個別的需求。而Pentium的指令快取和數(shù)據(jù)快取,更是各自大有文章。
前面有提及「x86 指令最大長度是17Bytes」,Pentium 第一階指令快取的內(nèi)部結(jié)構(gòu),是以兩個最小存取單位16Bytes 區(qū)塊,組成單一32Bytes 的快取線(Cache-Line),假若發(fā)生最糟糕的情況,17Bytes 長度的指令「橫跨」了兩條32Bytes 快取線,但仍希望一次擷取到指令流水線,那該怎么辦?Pentium 導(dǎo)入跨指令線分離式擷?。⊿plit Fetch),可連續(xù)讀取橫跨邊界的兩條16Bytes 最小區(qū)塊,而指令讀取緩沖區(qū)也是4 倍于80486 的128Bytes,以確保擷取指令的效率可「喂飽」兩條流水線的指令解碼器。
? 順便對照一下從NexGen Nx686 發(fā)展而來的AMD K6。AMD 取消了兩倍核心時鐘頻率的第一階快取存儲器,但除了既有的預(yù)先解碼位元(Pre-decoded Bits)用來標(biāo)定指令邊界,再追加第二個指令存取埠,以應(yīng)付這種狀況。反正各家廠商都各顯神通,直到可降低指令解碼器使用率的微指令快取(uOp cache)同時成為英特爾和AMD 的制式武裝為止。 數(shù)據(jù)快取亦不遑多讓,數(shù)據(jù)快取具備3 個存取埠,可同時應(yīng)付來自快取數(shù)據(jù)一致性協(xié)定與雙重執(zhí)行流水線的需要,更進一步將每條32Bytes 快取線,切成彼此交錯的8 個獨立4Bytes「Bank」,只要兩個數(shù)據(jù)存取需求不會同時使用同一個Bank,即可在單一時鐘周期內(nèi)搞定。
這是計算機工業(yè)史上的第一次嘗試,但這也大幅加重了快取存儲器的復(fù)雜度,也連帶不得不強化配置數(shù)據(jù)快取的虛擬/實體位址轉(zhuǎn)換緩沖區(qū)(TLB,Translation-Lookaside Buffer ),并新增判斷Bank 是否發(fā)生沖突的功能電路。 巨大的微程序只讀存儲器:基于「加速常用的簡單指令」的理念,Pentium 的指令解碼器可直接硬體解碼大多數(shù)「寄存器→存儲器」與「存儲器→寄存器」之類的「相對簡單」運算指令,但 x86 歷代累積下來的龐大復(fù)雜指令,還是需要動用微碼組成微程序產(chǎn)生控制訊號。 Pentium 的單一微碼字元長度是 92Bits,總共存放了 4K 數(shù)量。換言之,產(chǎn)生了高達 47kB 容量的只讀存儲器(ROM)空間,還遠多于第一級快取記憶體的容量(8kB+8kB),相當(dāng)驚人,老舊指令兼容性帶來的巨大負擔(dān),由此可見一斑,這就是維持回溯兼容性,所必須付出的昂貴代價。
4 個輸入的位址計算單元:一套所謂「復(fù)雜」的指令集,除了不規(guī)則的指令編碼長度,亂無章法的運算元定址模式和存儲器定址,更是必備的條件(可回顧一下 AMD Mike Johnson 講過的話)。實現(xiàn)高效能的超標(biāo)量流水線 x86 處理器,并非只需弄好流水線前端的指令擷取、解碼,與執(zhí)行階段的存取存儲器,高效率的有效位址計算(Address Calculation)能力,更是 x86 有別于 RISC 體系的一大差異點,坊間人云亦云、積非成是的「x86 處理器只有指令解碼器比較難做」完全是大錯特錯的誤解。
為了加速存儲器位址計算,讓執(zhí)行單位盡快得到「運算目標(biāo)」,Pentium 的兩條指令流水線個別有一套 4 個輸入值的加法器(4-Input Address Adder),對應(yīng) x86 指令集產(chǎn)生有效位址的 4 個數(shù)字: 節(jié)區(qū)描述器(Segment Descriptor)提供的基底值(Base)。 來自通用寄存器的基底位址(Base Address)。 取自通用寄存器的索引值(Index,再加上scale)。 指令編碼附上的的移位值(Displacement)。 因此部分僅支持 3 個輸出值的 486,需耗費兩個時鐘周期完成位址計算的復(fù)雜指令,Pentium 只需一個時鐘周期週期即可,更利于流水線化執(zhí)行指令。 ?
? 但慘劇尚未劃下句點,x86 的節(jié)區(qū)存儲器(Segment),必須強制檢驗每個節(jié)區(qū)的大小,確保存儲器運算元落在節(jié)區(qū)描述器所定義的存儲器范圍內(nèi)。80286 時代的保護模式,節(jié)區(qū)描述器會影響節(jié)區(qū)位置與體積的參數(shù),總計有:
32 位元基底值(Base)。
20 位元范圍值(Limit)。
范圍值單位Page 或Byte(前者上限4GB,后者則1MB)。
針對堆疊(Stack)數(shù)據(jù)結(jié)構(gòu)的向下擴展(Expand-Down)欄位。
處理器需采取不同的方式計算最高與最低位址,結(jié)果Pentium的兩條指令流水線,為此個別又得「再」加上一套4 個輸入值的加法器(4-Input Segment-Check Adder) ,為檢查節(jié)區(qū)正確性之用,而486的情況如上述位址產(chǎn)生器,須耗費更多時鐘周期做這件事。
? 為何「位址計算單元」一向是歷代x86 處理器增加執(zhí)行單元的重頭戲,原因就在此。Windows 95 刺激個人電腦普及的年代,「32 位元最佳化」的Pentium Pro 被批評「16 位元效能不佳」就因動到數(shù)據(jù)節(jié)區(qū)寄存器的指令,無法被非循序預(yù)測執(zhí)行,會讓隨后的指令上演大塞車,到了Pentium II 才修正。即使假以時日,這些老舊包袱的使用率只會越來越低,也早不再是改善效能的重點,但也沒人膽敢冒著犧牲軟件兼容性的風(fēng)險,根除這些歷史遺跡。
正面對決PowerPC 且落居下風(fēng) 相較于同時期且較早推出的超標(biāo)量RISC 處理器,就可明顯看出x86 指令集的復(fù)雜度造成的負面影響。 以1993 年秋季上市的IBM PowerPC 601 為例,晶體管數(shù)目僅280 萬,采用0.6um(600nm)制程時的晶粒面積僅121 平方公厘,卻有比晶體管310 萬的Pentium 更高的80MHz時鐘頻率、更大一倍的32kB 指令/數(shù)據(jù)共用式第一階快取存儲器,與1.5 倍的指令執(zhí)行能力,而采用0.8um(800nm)制程的初代Pentium是一顆16.7×17.6mm、294平方公厘的巨大芯片,完全瞠乎其后。英特爾當(dāng)時就表示,相較于同等級RISC 處理器,Pentium 有約30% 晶體管都「貢獻」給x86 指令集的兼容性。
不難想見那時候的「RISC 十字軍」有多high。 而Pentium 的雙重超標(biāo)量指令流水線也是限制重重,只有主流水線「U Pipe」可以執(zhí)行所有的x86 指令,副流水線「V Pipe」僅能負責(zé)比較簡單者,而要這兩條流水線一起動,還需要依循指令配對規(guī)則,講白了就是「兩邊都要跑簡單指令」,且涉及寄存器和存儲器兩邊數(shù)據(jù)互相搬移的指令也無能為力,就是要強迫其中一條流水線「發(fā)呆」兩個時鐘周期給你看。PowerPC 601「理所當(dāng)然」比較沒有這樣的煩惱。
? 80×87 浮點指令集更是x86 處理器追求高效能浮點運算的罩門,因「英特爾內(nèi)部溝通不良」(英特爾美國加州總部和以色列海法之間實在太遠了,1970 年代末期的聯(lián)絡(luò)手段又沒像今天這么方便)誕生的「極度愚蠢」堆疊式(Stack)寄存器架構(gòu)(附贈讓人摸不著頭緒的80 位元延伸雙倍精確度浮點格式),強迫多數(shù)浮點指令的運算元,其中一個非得指定放在堆疊寄存器的頂端不可。
? 英特爾在Pentium 加入FXCH 指令用來交換置頂寄存器,原本僅內(nèi)建一組浮點運算單元,流水線不能同時執(zhí)行兩個浮點運算指令的Pentium,簡單的浮點運算指令可和FXCH 一同塞進兩條指令流水線,但實際上也只有執(zhí)行一個有效浮點運算,況且后頭接連著的整數(shù)指令,都會被延誤最少一個時鐘周期。 判斷分支條件需「借用」整數(shù)運算通用寄存器與執(zhí)行單元,則是80×87 另一個弱點,從一個浮點運算設(shè)定條件碼、將浮點運算的執(zhí)行資訊搬移至通用寄存器、傳送至條件碼寄存器,再依據(jù)其結(jié)果,啟動正常的分支處理流程,Pentium 整整耗時9 個時鐘周期。
當(dāng)然可透過「插入」其他整數(shù)指令來降低效能損失,但無法彌補當(dāng)執(zhí)行條件判斷密集的程序,整數(shù)浮點單元之間反覆「踢皮球」的傷害。 這些在今天只會讓人覺得很荒謬的往事,讓Pentium 的浮點性能仍遠遠不及同時期的RISC 處理器,只能在x86 的世界當(dāng)大王,這宿疾到了新一代Pentium Pro 依舊無解,同期MIPS R10000 的SPECfp92 浮點效能還是Pentium Pro 的「3 倍」以上,還因為PowerPC「外掛」AltiVec 而一度被拉開差距到差點看不見車尾燈的程度。
直到Pentium III(Katmai)開始擴充SIMD(單一指令,多重數(shù)據(jù)流)浮點指令集SSE、初代Pentium 4(Willamette)的SSE2 新增雙倍精確度浮點格式,一路到Sandy Bridge 的AVX,引入VEX (VectorExtension)標(biāo)頭,一口氣解放了過去x86 指令編碼帶來的重重枷鎖,才算功德圓滿。
? 但即使看似出師不利,x86 指令集的沉重包袱,并未讓英特爾就此停下腳步,依然持續(xù)精進Pentium 處理器,就算沒有一鼓作氣打開天堂大門,卻也讓緊閉已久的門縫滲出充滿希望的曙光。 從企圖殺入很長一段時間內(nèi)「可遠觀不可褻玩焉」的服務(wù)器市場,預(yù)期Windows 95 激發(fā)個人電腦市場爆發(fā)性成長時,補足高效能桌機和筆記型電腦需要的基本功能,到迎合「多媒體」的新潮技術(shù)營銷名詞,無不是英特爾1990 年代初期念茲在茲的技術(shù)發(fā)展重點。這些努力的痕跡,統(tǒng)統(tǒng)一字不漏深深刻在Pentium和整個計算機工業(yè)的歷史上。
原汁原味的多處理器支持性
「多處理器支持性」是進入工作站與服務(wù)器市場的最低門檻入門票,而Pentium 則是x86 歷史上首度「原生支持(Glueless)多處理器」的先行者,但嚴格說來,這到了0.5 um 制程的第二代Pentium(P54C)才實現(xiàn),而在此之前,也并不是沒有「多處理器x86」的存在,只是需要外掛特制的系統(tǒng)芯片組,或連操作系統(tǒng)都要特殊版本。 一個便于實作的「無需外掛額外芯片」(Glueless)的多處理器(或多核心)環(huán)境,需具以下條件:
分配、協(xié)調(diào)各I/O 周邊裝置存取處理器需求的能力,發(fā)出中斷(Interrupt)時,知道該由哪個處理器負責(zé):標(biāo)準(zhǔn)化的中斷處理機制。
快取存儲器數(shù)據(jù)一致性協(xié)定(Cache ? ? Coherence Protocol):回寫式(Write-Back)快取存儲器常見的MESI(Modified, Exclusive, Shared, ? ? Invalid)協(xié)議。
低成本多處理器系統(tǒng)的根基:可讓多處理器共享的系統(tǒng)總線。
3 項條件之一,最重要者莫過于第一項。1983 年,17 名因英特爾極具野心的「32 位元微電腦大型主機」iAPX432 計劃失敗而離職的員工,創(chuàng)立的Sequent ComputerSystems(1999 年被IBM 購并,研發(fā)高階英特爾處理器的系統(tǒng)芯片組),就曾推出一系列采用80386 與80486 的多處理器產(chǎn)品線,但這些花費不菲的專屬方案,仰賴特制系統(tǒng)芯片組與定制化過的操作系統(tǒng),才能正確的將系統(tǒng)中斷(System Interupt)傳送到各處理器,多處理器x86 平臺仍缺標(biāo)準(zhǔn)化的中斷處理機制,并非可長可久的解決之道。
? 1993 年10 月27 日,也是初代Pentium 發(fā)表后的半年,英特爾首度公開第一版「多處理器規(guī)范」(MPS,Multi-Processor Specification)與最重要的「處理器本地端先進可程序化中斷控制器」(Local APIC,Local Advanced ProgrammableInterrupt Controller)與I/O 專屬的I/OAPIC,取代老舊的8259 PIC。 每個Pentium 或80486 處理器起碼要有一個Local APIC,與系統(tǒng)I/O 芯片組的I/O APIC,透過獨立于系統(tǒng)總線的3 位元APIC Bus,I/OAPIC 將周邊裝置的中斷需求傳遞給處理器的Local APIC,以決定中斷服務(wù)需求該指派給那些處理器,踏出了低成本多x86 處理器系統(tǒng)的第一步。
英特爾的競爭對手并非沒有替代方案,1996 年上市的Cyrix 6×86 依據(jù)OpenPIC規(guī)范,支持自家定義的SLiC,但也只有VIA 的Apollo 芯片組對應(yīng)此規(guī)格,基本上有跟沒有一樣,而AMD的x86 多處理器環(huán)境,更是要等到1999 年采用Alpha EV6 總線、理論上最多支持14 顆處理器的K7了。
不過初代Pentium 并未內(nèi)建Local APIC,同時期系統(tǒng)芯片組也沒有I/O APIC,要打造多顆Pentium 平臺,每一顆Pentium 需外掛一顆單價高達26 美元、兼具Local APIC 與I/OAPIC 兩者功能的82498DX,I/O 也需動用一顆。換句話說,雙處理器系統(tǒng)就需要用到3 顆,怎么看都不算便宜,還會占用不少主機板空間。 ? 后來0.5um 制程的第二代Pentium(P54C)變成史上第一顆整合Local APIC 的x86 處理器,對應(yīng)的系統(tǒng)芯片組也陸續(xù)在南橋(South Bridge)內(nèi)建I/O APIC(未內(nèi)建者,可選配專用的82093AA I/O APIC),總算讓雙Pentium 搖身一變,成為「Glueless」的多處理器平臺。
受制于缺陷重重的系統(tǒng)架構(gòu),如效率不足的系統(tǒng)總線、處理器缺乏非循序存儲器存取能力、處理器共享外部的第二級快取存儲器讓總線問題更加雪上加霜等等,并未讓Pentium 在服務(wù)器市場取得重大突破,到了Pentium Pro 面世后才迎刃而解,開啟Xeon 統(tǒng)治服務(wù)器市場之路,那又是另一段截然不同的故事了。
決定處理器核心/線程上限的Local APIC 與闖禍的操作系統(tǒng)支持性 處理器核心持續(xù)激增的今日,Local APIC 最重要的角色在于決定處理器的核心與線程上限。原先最早的APIC 上限是15,2000 年P(guān)entium 4 開始出現(xiàn)的xAPIC(將APIC 的3 位元專屬總線直接「融入」系統(tǒng)總線的通訊協(xié)定,避免APIC 運作時影響存儲器存取效能)增加到255,2008 年Nehalem 的x2APIC更多達4294967295,可視為「無限大」。 假如各位想多學(xué)些對親朋好友炫耀的「無用知識」,稍微花點腦筋,牢記一下這3 個數(shù)字的由來:
APIC:Pentium和Pentium Pro(與Pentium II、Pentium III、P6核心的Xeon)動用Local APIC的ID寄存器24-27四個位元,16進位的0xF(10進位制的15)用做廣播,所以2 4 ?1=15。
xAPIC:Pentium 4到Penryn用到Local APIC的ID寄存器24-31八個位元,16進位的0xFF(10進位制的255)用做廣播,所以2 8 ?1=255。
x2APIC:Nehalem開始使用存于MSR(Model-Specific Register)的32位元x2APIC ID,16進位的0xFFFFFFFF(10進位制的4294967295)用做廣播,所以2 32 ?1=4294967295。
但帳面上的「理論值」讓人看得很爽是一回事,微軟這些操作系統(tǒng)廠商是否乖乖買單又是另一回事。很不幸的,AMD Zen2 世代EPYC 與Threadripper將單顆處理器的實體核心術(shù)/邏輯處理器,一舉推進到64 核/128緒,就變成微軟Windows 的災(zāi)難了。
一臺2 顆EPYC 7742 或7702 的服務(wù)器,擁有128 個處理器核心和256 條線程,但是Windows Server 2016 和2012 R2 并不支持「AMD 新型平臺的x2APIC」,無法吃下這么多邏輯處理器。 事實上,根據(jù)微軟的EPYC 性能調(diào)校文件,Windows Server 2019 之前的舊版Windows Server,只能支持2 顆48 核心的EPYC 和192 個邏輯處理器。安裝2019 年9月前的Windows Server 2019,也需要事先在BIOS關(guān)閉x2APIC 和多線程,安裝完畢并裝完所有的系統(tǒng)更新檔,重新開機進BIOS 恢復(fù)功能,才能在工作管理員的效能選單看到全部CPU。
再次同場加映AMD。剛好前陣子Anandtech 有特別報導(dǎo)的EPYC 在Windows 10 發(fā)生的災(zāi)情(盡管這和APIC 沒有關(guān)系)。Windows 系統(tǒng)核心會預(yù)設(shè)64 個CPU組成一個「Windows Processor Group」,當(dāng)邏輯處理器超過64 個,會將多出余數(shù)包成另一群,像一顆64 核/128 緒的Threadripper,就會變成一顆實體CPU 有「兩包」64 個邏輯處理器。
? 但Windows 10 要企業(yè)版(Enterprise)才提供此功能,家用版(Home)和專業(yè)版(Professional)會將「滿出來的部分」,誤判為占用另一個處理器腳位的實體CPU,意思就是誤解成「兩顆」處理器的系統(tǒng),將誤導(dǎo)操作系統(tǒng)的線程排程,降低系統(tǒng)效能,這時關(guān)掉多線程,很可能表現(xiàn)還比較好。
在計算機的世界,任何「看起來很棒」的技術(shù)和功能,無不是「軟硬兼?zhèn)洹沟某晒?,?dāng)入手頂規(guī)的硬件時,也請多多關(guān)心手上的軟件環(huán)境是否可發(fā)揮最高效益。筆者現(xiàn)在都可以猜到花大錢買TR 3990X 的「長輩」急著升級Windows 10 企業(yè)版的畫面了。 「讓人比較有感」的指令集擴展 如果能讓筆者選擇,其實x86 指令集擴張史中最重要的一幕,絕對是邁向32 位元的80386、虛擬86 模式(Virtual 8086 Mode)與具備分頁表的虛擬存儲器。
但事隔多年,印象最深刻的,依舊對個人電腦市場規(guī)模爆炸式成長、使用者急速增加的1990 年代,英特爾在Pentium 家族干的一堆好事,包括極具歷史意義的第一次SIMD 擴張:MMX。
相信各位不可能不知道CPUID 這經(jīng)常用來辨識處理器廠牌、功能、版本與規(guī)格的好工具,但你們知道背后作這件事的「CPUID」指令,就是從Pentium 開始登場的嗎?眾多程序設(shè)計師計算指令執(zhí)行周期數(shù)的RDTSC(Read Time-Stamp Counter),也伴隨著Pentium 而生。用在操作系統(tǒng)避免不同線程同時對共用資源讀寫「互斥鎖」的CMPXCHG8B(Compare and Exchange 8 Bytes),也是小有名氣,WindowsXP 就是因這個必備指令,無法執(zhí)行于Pentium 之前的所有x86處理器。
前面有提到MSR(Model-Specific Register),意指在x86 架構(gòu)處理器中,一系列用于控制處理器執(zhí)行、功能開關(guān)、除錯、追蹤程序執(zhí)行、監(jiān)測處理器效能等功能的寄存器。MSR 的雛形始于80386 和80486,到了Pentium,英特爾新增RDMSR(ReadMSR)和WRMSR(Write MSR)指令用于讀寫MSR,使其真正的實用化。此外,軟件可透過前述的CPUID 指令,查詢處理器可支持的功能,并確認這些功能對應(yīng)的MSR 是否存在。 同時英特爾在Pentium「復(fù)刻」筆電專用的80386SL 和80486SL 處理器,那獨立于真實模式和保護模式,干了哪些好事,連操作系統(tǒng)都不知情的系統(tǒng)管理模式(SMM,System Management Mode)。
英特爾制定SMM 的初衷,在于讓筆電OEM 廠商自訂必備的電源管理與周邊裝置管理,如為了省電,動態(tài)關(guān)閉用不到的周邊設(shè)備,需要時再重新啟動等,將SMM 從「特殊武器」提拔成「制式裝備」,暗示英特爾認定筆電即將普及化的未來。 順道一題,相對于x86 指令集在節(jié)區(qū)定址定義4 層權(quán)限的Ring 0 到Ring 3(數(shù)字越小權(quán)力越大),SMM 的權(quán)限經(jīng)常戲稱為Ring -2,那Ring -1 跑到哪去了?答案是x86 硬件虛擬化技術(shù)用來攔截「在使用者模式仍會更動系統(tǒng)底層的危險指令」的Hypervisor 權(quán)限。
這些指令集擴張看似微不足道,遠不如那票SIMD(MMX、SSE、SSE2、SSE3、SSE4、AVX、AVX-512)「華麗壯大」,卻也是不可或缺的基本功,同為「高效能處理器不可被分割的一部分」。但Pentium 史上最知名的指令集MMX,就是一場歡樂異常的連續(xù)劇了。
為了MMX 讓Pentium 被迫大興土木、脫胎換骨 Windows 95 帶動個人電腦的多媒體需求,英特爾自然不能免俗,勢必要讓處理器跟「多媒體」沾上邊,試圖推動主機板加掛一顆來自第三方的數(shù)位訊號處理器(DSP),專門處理即時性影音應(yīng)用程序。但因為NSP 的運作模式是獨立于操作系統(tǒng)的化外之民,等于需要操作系統(tǒng)開后門,微軟為此拒絕買單,因此胎死腹中,才出現(xiàn)了MMX。
打從英特爾在1996 年,拋出MMX 這從未講清楚說明白的「無意義技術(shù)營銷商標(biāo)」,全名一直眾說紛紜、莫衷一是,還先后出現(xiàn)3 個版本:
MultiMedia eXtension
Multiple Math eXtension
Matrix Math eXtension
名稱怎樣不重要,各位只要記得一件事:為了操作系統(tǒng)兼容性,MMX指令集借用x87 浮點運算寄存器(80 位元中的64 位元)的SIMD「整數(shù)」運算,這樣就夠了。英特爾定義全新SIMD 寄存器,從Pentium III「Kaimai」的SSE(KNI,Katmai New Instructions)才開始。
指令集的編碼空間畢竟有限,英特爾要從哪里擠出這57 個指令的位置?英特爾將腦袋動到「0Fh」開頭的運算碼(Opcode),這卻造成前所未見的麻煩:過去0Fh 的主要用途「當(dāng)處理器的解碼器收到時,自動將該指令執(zhí)行流程跳到外掛的輔助處理器」,當(dāng)初英特爾就靠這招來處理8087 浮點輔助處理器,0Fh 開頭的x86指令都不是什么「需要追求效率」者,也因此,Pentium 的指令解碼器也沒有特別「關(guān)照」它們,意味著難以迅速完成解碼MMX 指令的重責(zé)大任。
主導(dǎo)Pentium MMX(P55C)研發(fā)的以色列海法團隊,不得不大興土木,將指令流水線深度從五階延長到六階,爭取足夠的指令解碼時間。多這一階并非有害無益,因為執(zhí)行單元將有更充裕的時間存取數(shù)據(jù)快取,并縮短電路的關(guān)鍵路徑,利于提高時鐘頻率,讓Pentium MMX 最終可到達300MHz,比前代P54C 多出整整50%。
? 但延長指令流水線也帶來更嚴重的分支預(yù)測錯誤代價,英特爾索性將「流水線深度長達12 階」的第六世代Pentium Pro 搭載的雙層動態(tài)分支預(yù)測與副程序返回位址緩沖區(qū)等先進技術(shù),原封不動的逆向移植到Pentium MMX,亦倍增快取存儲器和數(shù)據(jù)寫回緩沖區(qū),轉(zhuǎn)換虛擬和實體存儲器位址的TLB,也強化為可同時處理兩種不同分頁大小的版本,種種改進項目仿佛威而剛,讓吃下藍色小藥丸的Pentium MMX 搖身一變成「5.5 代」x86 處理器。
? 為了減少耗電與發(fā)熱,英特爾將MMX 執(zhí)行單元與實體寄存器獨立于x87 浮點運算器,執(zhí)行MMX 指令時,因指令集定義「邏輯上MMX 和x87 浮點無法同時執(zhí)行」,可關(guān)閉「吃電如喝水」般的浮點單元以節(jié)約電力,可是結(jié)合加倍的快取存儲器和種種增強方案,P55C 晶體管數(shù)從P54C 的330 萬激增到450 萬,制程從「不計多出10%芯片面積以追求最高時鐘頻率」的350 納米BiCMOS 改進為「自此英特爾轉(zhuǎn)向追求更低成本并降低耗電」的280 納米CMOS,芯片面積和制造成本仍足足比P54C 多50%。
Pentium MMX 在1997 年1 月上市沒多久,同年5 月同樣支持MMX的Pentium II 就以「塑膠大彈夾」外觀,現(xiàn)身于各地電腦賣場的玻璃柜,無論怎么看,Pentium MMX 都是過渡期強烈的尷尬產(chǎn)物。
(Source:Flickr/AndyRogers??CC BY 2.0) 但Pentium MMX 對英特爾在以色列海法的研發(fā)團隊而言,卻是極為重要的歷史里程碑,建立起「擅長精煉現(xiàn)有架構(gòu)壓榨更多價值」的名號,接連重塑P6 微架構(gòu)成為Centrino 心臟的PentiumM (Banias, Dothan)、當(dāng)英特爾在Pentium4(NetBurst)慘遭滑鐵盧的危急存亡之秋端出Core 2(Merom, Conroe, Woodcrest)救駕成功、融合P6 與NetBurst 之長的Sandy Bridge 終結(jié)AMD K8 的輝煌歲月、直到「奮六世之余烈」集大成的「終極x86 微架構(gòu)」Skylake,清一色都是出自以色列海法團隊的不朽杰作。
x86 指令集長期欠缺標(biāo)準(zhǔn)造成競爭對手與軟件開發(fā)商的困擾 Pentium 的「歷史地位」倒是值得另外添一筆:x86 指令集欠缺公開業(yè)界標(biāo)準(zhǔn),搞死不少人的陳年舊帳,終于正式浮上臺面。 Pentium Pro 總工程師之一的Robert Colwell 回憶錄《The Pentium Chronicles》說過,開發(fā)一顆x86 處理器,最艱巨的挑戰(zhàn)在于「如何保證可兼容所有舊程序」。特別早期x86 處理器,很多未定義的運算碼(Opcode)并沒有遮掉,被人發(fā)現(xiàn)又拿來用了,以后的處理器開發(fā)人員就只能乖乖想辦法「塞」進去,前提是你也要知道這些陷阱到底藏在哪里。
各位是否天真的以為所有x86 處理器廠商的產(chǎn)品,都保證彼此兼容,可執(zhí)行一模一樣的軟件?很遺憾的,這種好事從來就不存在英特爾統(tǒng)治的x86 世界(最起碼,前陣子讓Linus Torvalds 大暴走的AVX-512,AMD 現(xiàn)有產(chǎn)品也是付之闕如),英特爾在Pentium 時代的所作所為就是最好例證,讓初版使用者手冊描述新增指令的「附錄H」故意保持完全空白,英特爾的競爭者與軟件開發(fā)商紛紛變成倒霉的苦主。
英特爾并不像那票會定期推出版本演進與相關(guān)規(guī)范的RISC 指令集(有關(guān)心ARM 的讀者應(yīng)該很清楚)、積極推廣自家指令集給其他潛在競爭對手,而是完全不管其他人死活。想研發(fā)x86 兼容處理器的有志之士,假若沒有跟英特爾簽訂互相授權(quán)協(xié)議,只有兩條路可選:乖乖用電子顯微鏡默默研究英特爾處理器的晶粒,嘗試逆向工程,要不然就干脆不支持不顧兼容性,碰到就視為非法指令,剩下的爛攤子就丟給操作系統(tǒng)廠商傷透腦筋了。
像Cyrix 在被National Semiconductor 購并前,壓根沒有英特爾技術(shù)授權(quán),只能悶著頭逆向工程慢慢搞,自然也無法100% 兼容,讓號稱「第六世代」的6×86,連CPUID 和RDTSC都殘缺不全,指令集兼容水準(zhǔn)只有80486 等級,甚至還得逼迫軟件廠商撰寫修正程序。同時期的AMD 則是不計代價拼死拼活,都要藉由逆向工程擠出100% 兼容性,下場就是產(chǎn)品上市延誤,錯失商機,還虧當(dāng)初Compaq 傻傻不肯推出Pentium 個人電腦,寧愿癡癡等待AMD K5,更慘的是,撐到最后還是等不到。
英特爾競爭者也都不是省油的燈,不遑多讓搶著跳出來扮演「麻煩制造者」,自行定義「兄弟獨有之創(chuàng)見」的自家指令,不僅企圖爭奪x86 指令集的主導(dǎo)權(quán),并強化產(chǎn)品效能及營銷籌碼,像AMD K6 的3DNow!、AMD K8 的x86-64,Cyrix 6x86MX 的EMMI 與CyrixIII 的MMX-FP,Centaur 一度想不開的57 個SIMD 浮點指令和22 個自定義浮點寄存器,都是斑斑可考的歷史陳跡。 AMD 還一度想不開,搶先注冊「SSE5」,擺明跟英特爾AVX 打?qū)ε_,還好在2009 年5 月6 日緊急采煞車,宣布「皈依」AVX,但還是忍不住撈過界「補完」被英特爾廢除的四運算元指令格式(xmm1=xmm2×xmm3+m32)。AMD 要開始支持亂成一團的AVX-512并完全兼容,大概也是很久以后的未來了。
? 回顧這些年來的x86 指令集擴充戰(zhàn)爭,唯一從英特爾手上搶下先機的,也只有AMD x86-64 那次,還是微軟私下威脅「不打算支持兩種不同的64 位元x86」(英特爾本來有自己的Yamhill,但為了保護IA-64 遲遲不肯拿出來)強迫英特爾接受的結(jié)果。 最初英特爾多心不甘情不愿、打死都不承認 64 位元 x86 存在的「IA-32e」和 AMD x86-64 也并非一模一樣,英特爾獨占 CMPXCHG16B(Pentium 那個 CMPXCHG8B 的進階版)和 SSE3,AMD 多出分頁表 NX(No Execute)保護位元和 3DNow!。談到 x86 處理器廠商要彼此 100% 水乳交融,說有多麻煩就有多麻煩,說微軟有多火大就有多火大。
不過亂象還是持續(xù)延燒,還燒到虛擬化領(lǐng)域,近十多年來虛擬化應(yīng)用快速普及,然后 2005 年英特爾 VT-x(Vanderpool)和 2006 年 AMD AMD-V(Pacifica),雙方根本就是各搞各的,老死不相往來,讓 VMware vMotion 此類不停機的虛擬機動態(tài)遷移技術(shù),遲遲跨越不了不同 x86處理器廠商的邊界,無形中也侷限了 x86 處理器「向上發(fā)展」的潛力,目睹此景,IBM 應(yīng)該會繼續(xù)開心下去。
重塑x86 處理器世界觀的歷史認知
行文至此,想必各位看官臉上已掛著顫抖的嘴角與充滿劫后馀生的表情,或多或少逐步解構(gòu)并重組過往對個人電腦市場與 x86 處理器演進史的認知,有可能瞬間茅塞頓開,也有可能繼續(xù)滿頭問號。 本文并非教科書,而是經(jīng)由複習(xí)坊間甚少重視的歷史背景與不容易注意到的細節(jié),體認到平日陪伺在旁、習(xí)以為常的 x86 處理器,能走到今天是多麼不容易的一件事。羅馬不是一天造成,英特爾的霸權(quán)也不是平白從天上掉下來,這些年來我們一同擠過這麼多條牙膏,更不是毫無苦衷。 身為英特爾 1990 年代「Landmark」芯片與無數(shù)潛藏已久歷史暗流的縮影,Pentium 帶來 x86 世界太多「第一次」,承先啟后,奠定 25 年技術(shù)演進與市場發(fā)展的基礎(chǔ)邏輯。畢竟電腦是人類創(chuàng)造的東西,背后的人性和思維遠遠超越技術(shù)。
英特爾可靠開創(chuàng)新局的 Pentium 與繼往開來的 Pentium Pro,在眾多敵人環(huán)伺下殺出一條通往全新市場血路過程中「產(chǎn)生的價值」,如「技術(shù)領(lǐng)先無法保證商業(yè)勝利」和「成功的產(chǎn)品往往是折衷妥協(xié)后的產(chǎn)物」,統(tǒng)統(tǒng)很有意思,更值得各位細細品味。 關(guān)于Pentium,似乎筆者不小心遺漏了什麼,聽說跟浮點除法(FDIV)有關(guān)?算了,就當(dāng)作提醒世人吧。
編輯:黃飛
?
評論