楔子
提起1994,你會想起那時在世界電影史上都大放異彩的一年的,那一年國外影壇神仙打架,【阿甘正傳】、【肖申克的救贖】、【這個殺手不太冷】等等橫空出世,中國也有【重慶森林】、【活著】這樣的佳作。
而2004年在你印象裏有什麽記憶深刻之處呢?好像沒有,2004年在大多人眼裏是平平無奇的一年。然而卻消無聲息地開始改變了後來很多程式設計師的命運,一直影響到現在,盡管當中的很多人都不自知。這一切的源頭都是CPU。
莫耳定律與登納德微縮定律
莫耳定律(Moore's Law),我們都很熟悉。雖然名為定律,但並不是什麽科學定律。這是Intel創始人Gordon Moore於1965年提出的一個觀點:
積體電路上可以容納的晶體管數目在大約每經過18個月便會增加一倍。由於莫耳定律只是經驗之談,所以其中描述的翻倍時間並不總是準確,也有說法是18個月到24個月之間。另外還有一些延伸出來的解讀指導著半導體行業的發展:比如每過N個月,芯片的效能就翻一倍。每過N個月,芯片的價格就降一倍。等等。
除了莫耳定律以外還有一個名氣小一點的登納德微縮定律(Dennard Scaling):
晶體管的尺寸在每一代技術中都縮小了30% (0.7倍),因此它們的面積A減少了50%。這意味著電路減少了30% (0.7倍)的延遲,因此增加了約40% (1.4倍)的工作頻率。最後,為了保持電場恒定,電壓降低了30%,能量降低了65%,功率降低了50%。因此,在每一代技術中,晶體管密度增加一倍,電路速度提高40%,功耗(晶體管數量增加一倍)保持不變。在莫耳定律與登納德定律提出之後的相當長的時間內,事情的發展都十分順遂。CPU的效能在穩步的提升翻倍。在2000年前,CPU的更新換代,主要是提升時脈,而非增加核數。而且那時CPU的每次升級,軟體可以自動地獲得大幅效能提升。程式設計師們並不需要花費過多的學習成本,只需要更換新的處理器就可以了。那真是一段快樂的時光,直到2004年。
免費的午餐結束了!
當時人們早早地獲得了2GHz的CPU,3GHz也很快成為主流。按照發展速度,4GHz、5GHz甚至10GHz的的CPU都應該能如期而至。但是從3GHz以後,4GHz卻遲遲不至。受限於諸多物理問題,登納德定律走向終結。
提高CPU主頻變得越來越困難,因為這不僅僅是一個而是幾個物理問題造成,特別是熱、功耗過大、當前的電流泄露問題。這是2007年,C++大牛Herb Sutter發表的文章【The Free Lunch Is Over】中的一句。
文中還有詳細描述:
主要的處理器設計生產商,從Intel和AMD到SPARC和PowerPC,已經幾乎窮盡了所有的傳統方法來提高CPU效能。 大多數套用在幾十年內都可以獲得免費規律的效能提升,甚至不需要發行新版本或做其他任何特殊的事情,因為CPU制造商(主要)和硬碟制造商(次要)擁有可靠的更新更快的主流系統。時脈不是衡量的唯一標準,甚至不是好效能的必要標準,但卻是有指導意義的標準: 我們已經習慣看到500MHz的CPU被1GHz的替代,1GHz的被2GHz替代等等。今天主流電腦的主頻可以達到3GHz的範圍。為了能讓CPU繼續穩步地提升效能,給莫耳定律的18個月效能翻一倍的說法續命,CPU「被迫」朝向多核發展。當然CPU這麽多年的技術發展不僅僅是時脈以及多核帶來的,還有緩存,指令最佳化等等。但不得不說的是時脈和多核帶來的提升更多些。
The Free Lunch Is Over ,直譯就是「免費的午餐結束了」。自此CPU發展的重點從強調不斷提高時脈轉移到了利用並列性的架構特效上。這意味著程式設計師們沒辦法在不感知硬體變化的情況下,繼續享受硬體升級帶來的紅利了。並且需要編寫不僅正確而且還要優秀的程式碼才能吃掉CPU新增的效能。當然前面這些話有些絕對,畢竟後來CPU緩存之類的最佳化,也可以讓程式設計師免費享受到一些效能增益,只是還不夠多而已。
盡管在2004年以前就有涉及到並列的技術。比如pthread與openMP。但對於大多數程式設計師而言,這其實是可有可無的非必修技能,而2004年以後,程式設計師們的技能樹上則必須把多執行緒與並行編程的技能點滿。然而這還是不是全部,並行與並列並非完全對等的概念。真正的平行計算還有很有更多的技術接踵而至,越來越多的程式設計師們將無法獨善其身。
在許多年以後,隨著一場世紀圍棋大戰,人民對於並列算力的要求達到頂峰,顯卡之上的GPU逐漸成為人們追逐的焦點。又因為數位貨幣引發的挖礦熱,導致顯卡一卡難求!當然這是另外一個故事了。
C++失去的10年
C++11的出現在一定程度上盤活了陷入僵局的C++,被稱為C++的「文藝復興」。然而在2011年向前倒推10年,可謂C++失去的十年。這期間C++只頒布了C++03這一個版本,並且並不是大版本,只能說是C++98基礎上的一次小增補。在2003年往後,2011年之前的7年之間更是一個新版本都沒有正式釋出。其實C++11之前的版本代號是C++0x,確實是計劃在2010年之前頒布的,中途曾定檔為2009年,但最終仍然跳票。直到2011年才最終釋出。
2000年前程式語言發展的重點,大抵體現在如何組織程式碼的軟體工程學上,比如從程序導向到物件導向,又比如C++中的樣版。這些都是編程範式上的探索。而自2003年之後,2011年之前的這段C++的晦暗時光中,Java、C#都一度攻城掠地,甚至PHP也贏來黃金期。這個時間段,C++的低落自然和Web的發展有關,但我感覺和CPU時脈陷入僵局,開始朝向多核發展也有著千絲萬縷的聯系。C++必須要針對多核有所作為!在此期間C++並非不能使用多執行緒,但那都是C語言的。C++只不過是相容C語言而已,並且由於是系統級API,不同作業系統有著不同的實作。Java早早在官方標準中就定義好了多執行緒的API,因為虛擬機器這一中間層,使得Java程式設計師可以輕松享受到便利。而這是C++的劣勢。作為一門不是某個廠商把持的、面向系統的程式語言,C++還是需要統一各平台的多執行緒和並行的API,而這也不是那麽容易。這並不是把pthread改成物件導向的介面那麽簡單,C++11做得也不僅僅是一個std::thread。還有統一記憶體模型、執行緒同步API、std::future、甚至lambda運算式等等等等。
當然C++失落的200x年與CPU遭遇2004年之間的因果聯系大多僅代表我個人觀點。畢竟前面提到的那篇【免費午餐結束了】是由C++大神撰寫的。
閑談時脈
前文的思緒有些飄,來點務實的。CPU執行在哪種頻率下是有幾種模式可以選擇的。如果你是Linux系統的,可以嘗試用cpupower frequency-info 命令檢視一下。可能展示是結果是powersave(節能模式)、performance(效能模式)或其他模式。我還真聽說過有線上機器沒有開啟performance模式,而是powersave模式跑了很長時間,改成performance以後,啥程式碼都不用改,就獲得了幾十毫秒的效能提升的事。當然這種問題可能相對低階,專業的運維或基礎架構團隊應該都能保障,不需要程式設計師操心。
回頭再提一下CPU時脈的瓶頸。時至今日,我在公司的伺服器機器上,查詢CPU的頻率的,基本也顯示為3GHz。但咨詢運維說機器CPU實際達不到滿滿的3GHz,只能到2.8GHz。我說怎麽可能?他說用turbostat命令檢視,那個顯示的執行頻率更真實。好吧。我試了一下還真是。
當然伺服器和個人電腦的CPU是不同的。即使都是Intel家的,個人電腦一般是酷睿(Core)系列,而CPU是至強(Xeon)系列。自Herb Sutter發文的2007年,到如今也已經14年了。Intel其實也打造出來4GHz的產品。雖然比預期的時間晚了很多。然而畢十年之功於一役,後續穩步提升頻率依舊艱難。所以程式設計師們,還是好好學習多執行緒編程和平行計算吧。
後記
我曾在一篇知乎問答中回答過類似主題的內容:
但感覺可以說的並不暢快,遂將其拓展一下發成文章。這篇文章也將作為我後續其他並列與多核內容的引子。謝謝大家!另外也歡迎你對本文提出一些意見建議,大家共同交流進步!