在上一篇中,咱們談到過java
程序的CPU執行時間 = 指令數×CPI×Clock Cycle Time
要提高計算機的性能,能夠從上面這三方面着手。git
經過指令數/CPI,好像都太難了。github
所以工程師們,就在CPU上多放晶體管,不斷提高CPU的時鐘頻率,讓CPU更快,程序的執行時間就會縮短。算法
奔騰4的CPU主頻歷來沒有達到過10GHz,最終它的主頻上限定格在3.8GHz編程
並且奔騰4的主頻雖然高,可是實際性能卻配不上一樣的主頻數組
想要用在筆記本上的奔騰4 2.4GHz處理器,其性能只和基於奔騰3架構的奔騰M 1.6GHz匹配性能優化
因而不只讓Intel的對手AMD得到了喘息之機,更是表明着「主頻時代」的終結。架構
後面幾代Intel CPU主頻不但沒有上升,反而降低了。機器學習
到現在,2019年的最高配置Intel i9 CPU,主頻也不過是5GHz工具
相較於1978年到2000年,這20年裏300倍的主頻提高,從2000年到如今的這19年,CPU的主頻大概提升了3倍
奔騰4的主頻爲何沒能超3.8GHz?
就由於功耗.
一個3.8GHz的奔騰4處理器,滿載功率是130瓦
130瓦是什麼概念呢?機場容許帶上飛機的充電寶的容量上限是100瓦時
若是咱們把這個CPU安在手機裏面,不考慮屏幕內存之類的耗電,這個CPU滿載運行45分鐘,充電寶裏面就沒電了
而iPhone X使用ARM架構的CPU,功率則只有4.5瓦左右。
CPU,也稱做超大規模集成電路(Very-Large-Scale Integration,VLSI
由一個個晶體管組成
CPU的計算過程,其實就是讓晶體管裏面的「開關」不斷「打開」/「關閉」,組合完成各類運算和功能。
要想算得快
這二者,都會增長功耗,帶來耗電和散熱的問題!!!
能夠把CPU想象成一個工廠,有不少工人
就如CPU上面的晶體管,互相之間協同工做。
爲了工做快點完成,在工廠裏多塞一點人
你可能會問,爲何不把工廠造得大點?
這是由於,人和人之間若是離得遠了,互相之間走過去須要花的時間就會變長,這也會致使性能降低!
這就如若是CPU的面積大,晶體管之間的距離變大,電信號傳輸的時間就會變長,運算速度天然就慢了。
除了多塞一點人,還但願每一個人動做快點,一樣時間就可多幹活了
這就至關於提高CPU主頻,可是動做快,每一個人就要出汗散熱
要是太熱了,對工廠裏面的人來講會休克,對CPU來講就會崩潰出錯。
咱們會在CPU上面抹硅脂、裝風扇,乃至用上水冷或者其餘更好的散熱設備
就好像在工廠裏面裝風扇、空調,發冷飲同樣
可是一樣的空間下,裝上風扇空調可以帶來的散熱效果也是有極限的
所以,在CPU裏面,可以放下的晶體管數量和晶體管的「開關」頻率也都是有限的。
一個CPU的功率,能夠用這樣一個公式來表示:
功耗 ≈ 1/2 ×負載電容 × 電壓的平方 × 開關頻率 × 晶體管數量
爲了提高性能,要不斷地增長晶體管數量
一樣的面積下,想要多放一點晶體管,就要把晶體管造得小一點
這個就是平時咱們所說的提高「製程」
從28nm到7nm,至關於晶體管自己變成了原來的1/4大小
這個就至關於咱們在工廠裏,一樣的活兒,咱們要找瘦小一點的工人,這樣一個工廠裏面就能夠多一些人
咱們還要提高主頻,讓開關的頻率變快,也就是要找手腳更快的工人
但功耗增長過多,CPU散熱就跟不上
這時就須要下降電壓
這裏有一點很是關鍵,在整個功耗的公式裏面,功耗和電壓的平方是成正比的
這意味着電壓降低到原來的1/5,整個的功耗會變成原來的1/25。
事實上,從5MHz主頻的8086到5GHz主頻的Intel i9,CPU的電壓已經從5V左右降低到了1V左右
這也是爲何咱們CPU的主頻提高了1000倍,可是功耗只增加了40倍
雖然製程的優化和電壓的降低,在過去的20年裏,讓CPU性能有所提高
可是從上世紀九十年代到本世紀初,軟件工程師們所用的「面向摩爾定律編程」的套路愈來愈用不下去了
「寫程序不考慮性能,等明年CPU性能提高一倍,到時候性能天然就不成問題了」,這種想法已經不可行了。
因而,從奔騰4開始,Intel意識到經過提高主頻比較「難」去實現性能提高
開始推出Core Duo這樣的多核CPU,經過提高「吞吐率」而不是「響應時間」,來達到目的。
提高響應時間,就比如提高你用的交通工具的速度
本來你是開汽車,如今變成了高鐵乃至飛機
可是,在此之上,再想要提高速度就不太容易了
CPU在奔騰4的年代,就比如已經到了飛機這個速度極限
那你可能要問了,接下來該怎麼辦呢?
相比於給飛機提速,工程師們又想到了新的辦法,能夠一次同時開2架、4架乃至8架飛機,這就好像咱們如今用的2核、4核,乃至8核的CPU。
雖然從上海到北京的時間沒有變,可是一次飛8架飛機可以運的東西天然就變多了,也就是所謂的「吞吐率」變大了。因此,無論你有沒有須要,如今CPU的性能就是提高了2倍乃至8倍、16倍。
這也是一個最多見的提高性能的方式,經過並行提升性能。
這個思想在不少地方均可以使用
舉個例子,咱們作機器學習程序的時候,須要計算向量的點積,好比向量
$W = [W_0, W_1, W_2, …, W_{15}]$
和向量
$X = [X_0, X_1, X_2, …, X_{15}]$
$W·X = W_0 * X_0 + W_1 * X_1 +$
$W_2 * X_2 + … + W_{15} * X_{15}$
這些式子由16個乘法和1個連加組成。若是你本身一我的用筆來算的話,須要一步一步算16次乘法和15次加法。
若是這個時候咱們把這我的物分配給4我的,同時去算\(W_0~W\_3\), \(W\_4~W\_7\), \(W\_8~W_{11}\), \(W_{12}~W_{15}\)這樣四個部分的結果,再由一我的進行彙總,須要的時間就會縮短。
但並非全部問題,均可以經過並行提升性能來解決
要使用這種思想,須要知足如下條件:
這就引出了性能優化中一個經驗定律
具體能夠用這樣一個公式來表示:
優化後的執行時間 = 受優化影響的執行時間/加速倍數+不受影響的執行時間
在剛剛的向量點積例子裏,4我的同時計算向量的一小段點積,就是經過並行提升了這部分的計算性能
可是,這4我的的計算結果,最終仍是要在一我的那裏進行彙總相加
這部分彙總相加的時間,是不能經過並行來優化的,也就是上面的公式裏面不受影響的執行時間部分
好比上面的各個向量的一小段
總共須要120ns。這裏經過並行4個CPU有了4倍的加速度。那麼最終優化後,就有了100/4+20=45ns
即便咱們增長更多的並行度來提供加速倍數,好比有100個CPU,整個時間也須要100/100+20=21ns。
不管是簡單地經過提高主頻,仍是增長更多的CPU核心數量,經過並行提高性能,都會遇到相應的瓶頸
僅靠簡單地經過「堆硬件」的方式,在今天已經不能很好地知足咱們對於程序性能的指望了。
因而,工程師們須要從其餘方面開始下功夫了。
在「摩爾定律」和「並行計算」以外,在整個計算機組成層面,還有這樣幾個原則性的性能提高方法。
深度學習,整個計算過程當中,99%都是向量和矩陣計算
因而,工程師們經過用GPU替代CPU,大幅度提高了深度學習的模型訓練過程
原本一個CPU須要跑幾小時甚至幾天的程序,GPU只須要幾分鐘就行了
Google更是不知足於GPU的性能,進一步地推出了TPU
一般咱們使用 O 表示一個算法的好壞,咱們優化一個算法也是基於 big-O
可是 big-O 實際上是一個近似值,就比如一個算法時間複雜度是 O(n^2) + O(n)
這裏的 O(n^2) 是佔大比重的,特別是當 n 很大的時候,一般咱們會忽略掉 O(n),着手優化 O(n^2) 的部分
現代的工廠裏的生產線叫「流水線」。
咱們能夠把裝配iPhone這樣的任務拆分紅一個個細分的任務,讓每一個人都只須要處理一道工序,最大化整個工廠的生產效率。
咱們的CPU其實就是一個「運算工廠」
咱們把CPU指令執行的過程進行拆分,細化運行,也是現代CPU在主頻沒有辦法提高那麼多的狀況下,性能仍然能夠獲得提高的重要緣由之一
預測下一步該幹什麼,而不是等上一步運行結果,提早進行運算,也是讓程序跑得更快一點的辦法
在一個循環訪問數組的時候,憑經驗,你也會猜到下一步咱們會訪問數組的下一項
後面要講的「分支和冒險」、「局部性原理」這些CPU和存儲系統設計方法,其實都是在利用咱們對於將來的「預測」,提早進行相應的操做,來提高咱們的程序性能。
深度優先搜索算法裏面的 「剪枝策略」,防止沒有必要的分支搜索,這會大幅度提高算法效率
深刻淺出計算機組成原理