俗語說的好:過猶不及。從一個極端激烈反動到另一的極點,不見得是最好的選擇,時下存活在市場上的產品與技術,也往往不是看起來「最具進步色彩」的那個。DEC在研發Alpha指令集時,過度重視效能,將大量的工作和複雜度,從硬體「轉嫁」到軟體,也為此復出了不少代價。
先從中斷 (Interrupt) 說起。在我們所熟知的「精確中斷 (Precise Interrupt)」,若處理器發生中斷,如外部I/O發出存取需求,將標定下一個要被執行指令的記憶體位址的程式計數器 (PC,Program Counter) 存入已知的位址,在此之前的所有指令都將被執行完畢,而在後面的指令都不可以被執行。換言之,處理器處於被「明確定義」的狀態,中斷不會影響程式執行的結果。
但Alpha浮點運算的中斷卻是「不精確」的,如發生中斷,需要另外塞一個 TRAPB (Trap Barrier,設陷邊界) 指令讓處理器停擺,強制完成前面的指令,將控制單元的部份複雜度轉移到軟體,犧牲掉處理器的中斷例外嚴謹度。如果少了這個TRAPB,浮點程式碼的運算結果將無法完全符合IEEE754規範。
然後Alpha打從一開始就是貨真價實的純種64位元指令集架構,其原始設計者也很偏執的不想看到像8位元和16位元長度的小量資料存取,所以一次只能存取32位元或64位元,再用位元組處理指令去擷取所需要的那一小塊,變相增加指令的數量與程式碼的體積。背後付出的代價是:這提高了從其他32位元指令集架構移植到Alpha的困難度。後來DEC才在1995年10月的Alpha 21164A (EV56) 才補回六個可直接處理8位元和16位元的BWX (Byte-Word eXtension) 指令。
Alpha為了方便指令管線化,也不支援整數除法,32位元單精確度浮點數在暫存器內會被自動轉換成64位元雙倍精確度格式。到頭來,一切都是為了效能而生。
筆者在上集說到DEC的VAX有「二十種」運算元定址模式,但Alpha就衝到極端的「一種」,只有暫存器加上位移值 (Register + Offset),根本精簡過頭了,這也會理所當然的「增肥」程式碼需要的指令數量與體積。
拜指令編碼預留了大量擴充空間,Alpha一開始就支援條件搬移 (Conditional Move,或稱引述執行) 指令,將「分支相依性轉化為資料相依性」。當可在分支發生之前,確認分支條件的結果,編譯器即可使用引述碼取代分支,來控制指令執行流程,可避開分支預測,利於指令管線化。
以一個簡單的條件判斷為例:
beq ra, label //ra = 0,就跳到’label’
or rb, rb, rc //否則就把rb的資料搬移到rc
Alpha可以一個指令就打死:
cmovne ra, rb, rc
乍看一下一行指令很漂亮,但這東西其實也是高效能多重指令派發非循序指令執行的緊箍咒,64位元的ARMv8指令集,最重要的成就就在於取消了這個棘手的限制,也直接促使了Apple A11之後的絕對效能優勢。
這些神奇的特色,後來也可在Intel的IA-64指令集上看到神似的鬼影,但唯一共同點就是都被IBM罵翻了。
回顧消失在歷史洪流的Intel旗艦處理器Itanium(上)
回顧消失在歷史洪流的Intel旗艦處理器Itanium(中)
回顧消失在歷史洪流的Intel旗艦處理器Itanium(下)
最後,Alpha也甚少增加新指令。總觀近代處理器發展史,Intel隨便來一次指令集擴充,都比Alpha的歷代總和來得多。(53個MMX,70個SSE,144個SSE2,47個SSE4.1,數不完的AVX和AVX-512)
結合一切可以想的到的有利條件,Alpha的性能表現一直相當的出色,從1992年的初代21064 (EV4) 就靠著200MHz的時脈,創下浮點運算的世界紀錄,接連數代主宰了1990年代的「效能賽豬公」,尤其是當時的業界指標SPEC CPU。在第一次波斯灣戰爭大出風頭的愛國者飛彈,據傳其系統的運算心臟也是Alpha。
1995年:時脈高人一截的21164痛宰Intel Pentium Pro。
2000年:五年後,時脈較低的21264還是在浮點運算屠殺Intel Pentium III。
Intel Pentium Pro三位總工程師之一的Robert Colwell曾在其回憶錄The Pentium Chronicle提及「Alpha比我們曾經擁有過的任何東西都來得好」,但現實很殘酷,天底下任何產品的背後都是「技術、商業、政治」交相影響後的產物,也註定Alpha只能在一連串的併購案後,默默的淹沒於歷史的洪流。