1. 程式人生 > >免費午餐已經結束——軟體歷史性地向併發靠攏

免費午餐已經結束——軟體歷史性地向併發靠攏

譯文發表於《程式設計師》2006.11。

免費大餐不久就將結束。對此,你有何打算,做好下一步準備了麼?

對主要的處理器廠商以及架構,包括IntelAMDSparcPowerPC[譯註1]來說,改善CPU效能的傳統方法,如提升時鐘速度和指令吞吐量,基本已走到盡頭,現在開始向超執行緒和多核架構靠攏。而且這兩個特性(特別是多核)已經在部分晶片實現,如PowerPCSparc IVIntelAMD也將在2005年內趕上。2004In-Stat/MDR秋季處理器論壇[譯註2]的主題就是多核裝置,很多公司都展示了改進和新研發的多核處理器。不過,要將2004年稱為多核年,顯然還不夠理直氣壯。

多核將引領軟體研發發生基礎性變化,特別對接下來幾年裡那些面向一般應用、執行在

PC和低端伺服器上的應用軟體(在今天已經銷售出去的軟體裡佔有很大比例)而言。在這篇文章裡,我想就多核為何突然對軟體產生重要影響,以及併發鉅變如何影響我們和我們未來編寫軟體方式的問題展開討論。

我可以這麼說:免費大餐已經結束一兩年了,但我們現在才開始意識到這個問題。

免費的效能大餐

業界存在一個有趣的現象:“安迪送,比爾取。”[譯註3]無論處理器效能提升多少,軟體都有辦法迅速吞噬。CPU速度十倍於前,軟體就有十倍於前的活要幹(或者肆無忌憚猛增軟體的工作量,導致效能下降)。在過去幾十年裡,由於CPU、記憶體和硬碟特別是CPU廠商強力推進主流系統向更新更快的方向發展,大多數軟體不做版本升級,甚至原封不動,就可輕鬆而持續地享受處理器效能提升的成果。儘管時鐘速度不是衡量系統性能的唯一和最好的標尺,但其重要意義不容忽視。我們見證了

CPU的發展歷史:從500MHz1GHz,然後再到2GHz,不斷提高。今天,主流計算機已經進入3GHz時代。

不過,有一個很關鍵的問題:這種提升模式什麼時候會走到盡頭?儘管莫爾定律預言了歷史上的指數式增長,但我們很清楚指數式增長不可能永遠維持,因為硬體畢竟受物理極限約束;光速是不可能更快的[譯註4]。所以增長必然放緩,最後停滯。順便說明一點,莫爾定律的主要描述物件是電晶體整合密度,但在一些相關的領域,如時鐘速度方面,也出現了類似的指數式增長;甚至在別的領域有更快的增長速度,例如著名的資料儲存量爆炸。不過這些重要趨勢需要另一篇文章來分析了。

如果你是一個軟體開發人員,那麼你可能一直在免費享受桌面計算機效能提升的大餐。某些操作會成為應用程式效能的瓶頸?“你過慮了”,我們對這樣的回答耳熟能詳,“未來處理器將更為強勁,而現在的應用程式速度倒是日益被非

CPU吞吐量和記憶體速度因素扼殺,比如I/O、網路和資料庫等等。”真的是這樣麼?

要在過去,這的確沒錯。但在以後,就完全不對了。

我有兩個訊息要告訴大家。第一個是好訊息,處理器效能仍然會不斷提高。第二個則是壞訊息,至少在短時間內,處理器效能的提升,不再能像以往那樣讓現在的應用程式繼續免費獲益。

過去30年裡,CPU設計者主要從三個方面提高CPU效能,頭兩個就是從線性執行流程上考慮的:

1、時鐘速度

2、執行優化

3、快取

提升時鐘速度將增大單位時間的時鐘週期數。讓CPU跑得更快,就意味著能讓同樣工作或多或少更快完成。

優化指令執行,可以在每個時鐘週期內完成更多工作。目前的CPU中,一些指令被不同程度地做了優化,如管線、分支預測、同一時鐘週期內執行更多指令,甚至指令流再排序支援亂序執行等[譯註5]。引入這些技術的目的是讓指令流更好、更快執行,降低延遲時間,挖掘每一時鐘週期內晶片的工作潛能。

在這裡,有必要對指令再排序作個簡單說明。我剛才提到的部分指令優化手段,其實已遠非普通意義上的優化。這些優化可能改變程式原意,造成程式不響應程式設計師的正常要求。這可是個大問題。CPU設計師都是心智健全且經過嚴格訓練的好同志,正常情況下,他們連蒼蠅都不願傷害,自然也無意破壞你的程式。而在最近幾年裡,儘管知道指令重組有破壞程式語義的風險,但為了提升每個時鐘週期內的工作效率,他們已經習慣於積極開展這類有風險的優化工作。難道海德先生[譯註6]復活了?當然不是。這種積極性清楚表明,晶片設計師承受了交付速度更快CPU的巨大壓力;在這種壓力下,為了讓軟體跑得更快,他們不得不冒改變程式意思,甚至應用崩潰的風險。拿兩個有名的例子來說——寫操作再排序和讀操作再排序[譯註7]。允許處理器對寫操作再排序是非常令人吃驚的,讓大多數程式設計師意外,一般來說這個特性必須關閉,因為在寫操作被處理器武斷地再排序條件下,程式設計師很難保證程式正確執行。讀操作再排序也有明顯的問題,但大多數情況下這個特性是開啟的;因為相對來說它更容易把握一些,而且人們對效能的要求,讓作業系統和操作環境設計師只能選擇讓程式設計師在一定程度吃點苦頭,畢竟,這比直接放棄效能優化機會的罪責小一些。

第三個是增大與RAM分離的片內快取記憶體。RAM一直比CPU慢很多,因此讓資料近可能靠近處理器就很重要——當然那就是片內了[譯註8]。片內快取持續飈升了很多年,現在的主流晶片商出售的CPU都帶有2M甚至更高的二級快取。值得一提的是,今後,三種提升CPU效能的傳統手段裡,增加快取將碩果僅存。我會在後面更詳細說明快取的重要性。

我寫這麼多的意思是什麼呢?

最重要的是我們必須認識到,傳統效能提升方法與併發沒有直接關係。過去任何方法帶來的速度提升,無論是順序(非並行的單執行緒或單程序)、還是併發執行的程式,都能直接受益。這點很重要,我們目前大量的程式都是單執行緒的,而且在未來仍然有重要的存在價值。

當然,適當時候,我們重新編譯程式,可以利用CPU的新指令(如MMXSSE[譯註9])和新特性提升系統性能。但總的來說,即使放棄使用新指令和新特性,不做任何更改,老程式在新CPU也會跑得更快,讓人心花怒放。

曾經的世界是這般美好,可如今,她就要變了顏色。

為什麼我們今天沒有10GHz晶片

      

其實,CPU效能提升在兩年前就開始碰壁,但大多數人到了最近才有所覺察。

我這裡有份來自Intel的資料(當然你可以從其他廠商得到類似資料)。圖中反映了Intel晶片的時鐘速度和電晶體整合規模演變歷史。電晶體整合數至少就目前而言仍在繼續上升,但時鐘速度的情況就不同了。

我們從圖中可以看到,大概在2003年初,一路高歌猛進的CPU時鐘速度突然急剎車。受制於一些物理學問題,如散熱(發熱量太大且難以驅散)、功耗(太高)以及洩漏問題[譯註10]等,時鐘速度的提升已經越來越難。

你目前在工作站上用的CPU時鐘速度是多少?10GHz麼? 20018Intel晶片就達到2GHz,按照2003年前的CPU發展趨勢推算,到2005年初,我們就能擁有第一塊10GHzPentium晶片。但實際上沒辦到。而且情況好像越來越糟——我們根本就不知道到底在什麼時候這樣的晶片可以出現。

那麼放低期望,4GHz又如何呢?目前我們已到3.4GHz——那麼4GHz已經不遠了吧?唉,好像4GHz也遙不可及。可能你知道,Intel首先於2004年中將4GHz晶片的釋出時間推遲到2005年,而到了2004年秋季,則徹底取消了4GHz計劃[譯註11]。在本文寫作的同時,Intel宣佈計劃到2005年早期,實現到3.73GHz(即圖中的右上最高處)的微量提升。所以,至少就目前來說,時鐘速度的競賽實際上結束了,Intel和其他大多數處理器廠商將把旺盛的精力投入到多核等方向去。

也許,我們某天在主流PC裡能裝上4GHzCPU,但2005年別想。Intel實驗室裡的確已經有執行在更高速度的晶片——不過代價是驚人的,比如龐大數量的冷卻裝置。你想不久在你的辦公室裡就有這樣的冷卻裝置,坐飛機的時候,就把它們放在你膝蓋上?別做夢了!

莫爾定律與新一代處理器

“沒有免費的午餐。”——摘自R. A. Heinlein的小說《The Moon Is a Harsh Mistress》。

莫爾定律玩完了?這個問題很有趣,嚴格地講,還不能這麼說。儘管和所有的指數式增長方式一樣,莫爾定律總有一天會走到盡頭,但最近這些年,還沒有這樣的危險。晶片工程師在榨取時鐘週期內剩餘價值時的確碰了壁,不過電晶體整合量仍在暴漲,所以從這個角度說,CPU近期仍將遵循莫爾定律,系統吞吐量繼續提高。

關鍵的變化,即本文的中心,是今後幾代處理器效能提升所走的道路將完全不同。同時,大多數現在的應用軟體將不再可能不作大規模重構,就能像過去那樣從處理器免費獲益。

接下來數年裡,新型晶片的效能提升將主要從三個方面入手,其中僅有一個沿襲是過去的:

1、超執行緒

2、多核

3、快取

超執行緒,是指在單個CPU內,並行兩個或多個執行緒。超執行緒CPU已經發布了,支援並行執行一些指令。不過這種CPU還是存在短板,雖然給它增加了部分硬體如暫存器,但它和絕大多數普通CPU一樣,快取、整數和浮點運算器仍然是唯一的。有資料表明,寫得較好的多執行緒應用,在超執行緒CPU上能獲得5%15%的效能提升;假設趨於理想狀態,即多執行緒程式寫得好到極點,那麼效能可以提高40%。不錯了,不過還是做不到成倍提升,而且對單執行緒應用毫無幫助。

多核,主要是指在一塊晶片上執行兩個或多個處理器。部分晶片如SparcPowerPC目前已經推出了多核版本。IntelAMD也計劃在2005年內初步實現,具體時間取決於它們的系統整合水平,功能則是一樣的。AMD初期在效能設計可能更具優勢,如更好的支援功能單片內整合,而Intel基本上就打算將兩顆Xeon膠合在一塊片子上了事。所以剛開始的時候,這種雙核晶片與一個真正的雙CPU系統在效能幾乎沒有差別,僅僅在價格上前者更為便宜,畢竟它的主機板上不需要兩個插槽和額外膠合件;另外,即便理想狀態,這種架構也無法達到雙倍速度,且無益於單執行緒應用,而只有寫得較好的多執行緒應用能得到好處。

最後一個是片內快取,還能像預期那樣在近期繼續上升。三個方法中,僅有這個可以讓現有應用全面受益。片內快取有令人難以置信的重要性和對大多數現有應用的超高價值,原因很簡單,那就是“空間就是速度”。CPU和主存互動的代價是巨大的,如果能避免,那就儘量不要和它打交道。在目前的系統裡,從主存獲取資料所花時間,通常是從快取獲得資料的1050倍。很讓人吃驚吧,因為很多人都以為記憶體已經足夠快。其實這不過是與硬碟和網路相比,而不是執行在更高速度的片內快取。應用程式的工作與快取間的適配程度,和我們是榮辱與共的。很多年來,不重構程式,僅僅提高快取大小就拯救了現有應用,給它們帶來新生。軟體操縱的資料和為新增功能而加入的程式碼越來越多,效能敏感的操作必須繼續與快取適配。套用經濟大蕭條時期老人常唸叨的一句話:“快取為王。”

順帶說件發生在我的編譯器小組的趣事,算是“空間就是速度”的一個佐證。32位和64位編譯器將同樣的程式碼分別編譯成32位和64位程式。64CPU有多得多的暫存器和其他程式碼優化特性,因此執行其上的64位編譯器先天的獲得極大效能提升。這當然很好。而資料的情況又如何呢?換到64位平臺上,記憶體中絕大部分資料的大小並未發生變化,唯一例外的就是指標,指標佔用了兩倍於以前的空間。因此,我們的編譯器和絕大多數32位應用相比,揮舞指標就費力得多。現在的指標耗用8個而不是4個位元組,空間淨增加,結果我們發現64位編譯器的工作集[譯註12]大小顯著增加。工作集增大導致效能下降,差不多抵消了更快的CPU和更多暫存器帶來的效能優勢。就在我寫這篇文章的時候,6432位編譯器正以同樣的速度執行,儘管程式程式碼完全一樣而且64位處理器先天能力更強。這就是“空間就是速度”。

快取能,但超執行緒和多核CPU對現在的絕大多數應用,幾乎不會有任何影響。

綜上所述,硬體的變化到底會給軟體開發方式帶來怎樣的影響呢?你可能已經有了初步答案了。讓我們更深入研究,明白其厲害所在。

對軟體來說,這意味一次鉅變

上世紀90年代初,我們開始學著理解物件。在主流軟體開發領域裡,從結構化到面向物件程式設計是過去20甚至可以說30年來最重要的變革。這期間也發生了其他一些變化,例如近來誕生的的確讓人著迷的WebServices,但我們中絕大多數人在職業生涯裡從未有過見識像面向物件那樣基礎而深刻改變軟體開發方式的機會。

現在,機會來了。

也從現在開始,效能大餐就不再免費了。雖然託快取增大的福,我們還能在半路上撿到普通的效能提升丸,但如果你希望你的應用程式在新的處理器裡能繼續獲得爆炸性的效能提升,那就需要你好好編寫併發程式了(通常是多執行緒的)。說比做容易啊,也不是所有問題都天生可以通過並行解決,而且併發程式設計的難度也是很大的。

肯定有人嚷嚷開了:“併發?並不是什麼新鮮玩意嘛!人們不早就在寫這樣的程式了麼?”是的,小部分程式設計師的確寫過。

別忘了,至少從上世紀60年代晚期的Simula開始,人們就在寫面向物件程式。但到了90年代,面向物件才成功發動革命並奪取統治地位。為什麼呢?工業是受現實需求驅動的,為了解決越來越大的問題,必須編寫越來越大的系統,這樣的系統需要越來越強勁的CPU和儲存裝置支援,硬體系統也恰逢其時地逐步提供了這樣的支援。面向物件程式設計擅長抽象和依賴管理,所以成為了開發經濟、可靠和可重用的大型軟體的必備利器。

併發程式設計差不多也有同樣漫長的歷史可以追溯,很早的時候,我們就開始編寫協程、管程[譯註13]以及其他與併發有關的東西。近10年來,我們也發現有越來越多的程式設計師在編寫併發應用(有多執行緒的,也有多程序的)系統。但是發生整體轉向性的鉅變,目前還不具備條件,需假以時日。現有大量的單執行緒應用,仍然有巨大的存在價值,這點我會在後面說明。

說點題外話,當前“下一次軟體開發革命”這樣的詞語多如牛毛,讓大家眼花繚亂,其實這是商家宣傳自己新技術所作的廣告,不要理睬它。新技術通常都很吸引人,有時候也很有用,但軟體開發方式的重大變革必然來源於在真正得到爆發式廣泛應