CPU的時間觀

2021-09-24 13:43:30 字數 4191 閱讀 5443

最為我們熟知的關於計算機不同元件速度差異的圖表,是下面這種金字塔形式:越往上速度越快,容量越小,而**越高。這張圖只是給了我們乙個直觀地感覺,並沒有對各個速度和效能做出量化的說明和解釋。而實際上,不同層級之間的差異要比這張圖大的多。這篇文章就讓你站在 cpu 的角度看這個世界,說說到底它們有多慢。

目前電腦主頻是2.6g,也就是說每秒可以執行 2.6*10^9 個指令,每個指令只需要 0.38ns(現在很多個人計算機的主頻要比這個高,配置比較高的能達到 3.0g+

我們假設乙個指令時間比作人類能夠感知的一秒鐘來對比資料

一級快取

一級快取讀取時間為0.5ns,換算**類時間大約是1.3s,大約一次或者兩次心跳的時間。

這裡能看出快取的重要性,因為它的速度可以趕上 cpu,程式本身的 locality 特性加上指令層級上的優化,cache 訪問的命中率很高,這最終能極大提高效率。

分支**

分支**錯誤需要耗時5ns,換算**類時間大約是13s,相當於成年男子100公尺奔跑

指令形成流水線以後,就需要一種高效的調控來保證硬體層面併發的效果:最佳情況是每條流水線裡的十幾個指令都是正確的,這樣完全不浪費時鐘週期。而分支**就是幹這個的

分支**器猜測條件表示式兩路分支中哪一路最可能發生,然後推測執行這一路的指令,來避免流水線停頓造成的時間浪費。但是,如果後來發現分支**錯誤,那麼流水線中推測執行的那些中間結果全部放棄,重新獲取正確的分支路線上的指令開始執行,這就帶來了十幾個時鐘週期的延遲,這個時候,這個 cpu 核心就是完全在浪費時間。

幸運的是,當下的主流 cpu 在現代編譯器的配合下,把這項工作做得越來越好了。

還記得那個讓 intel cpu 效能跌 30% 的漏洞補丁嗎,那個漏洞就是 cpu 設計的時候,分支**設計的不完善導致的。

二級快取

二級快取時間大約在7ns,換算**類時間大約是18.2s,相當於成年男100公尺跨欄。

如果一級快取沒有命中,然後去二級快取讀取資料,時間差了乙個數量級。

tips:為什麼需要多層cpu快取

互斥鎖的加鎖和解鎖

互斥鎖的加鎖和解鎖時間需要25ns,換算**類時間大約是65s,首次達到了一分鐘。

併發程式設計中,我們經常聽說鎖是乙個很耗時的東西,因為在微波爐裡加熱乙個東西需要一分鐘的話,你要在那傻傻地等蠻久了。

記憶體

每次記憶體定址需要100ns,換算**類時間是 260s,也就是4分多鐘,相當於閱讀乙個章節的網路**。

看起來還不算壞,不過要從記憶體中讀取一段資料需要的時間會更多。到了記憶體之後,時間就變了乙個量級,cpu 和記憶體之間的速度瓶頸被稱為馮諾依曼瓶頸。

究竟什麼是馮諾依曼瓶頸(von neumann bottleneck)?

效能之殤:從馮·諾依曼瓶頸談起

cpu 上下文切換

一次 cpu 上下文切換(系統呼叫)需要大約1500ns,也就是 1.5us(這個數字參考了這篇文章,採用的是單核 cpu 執行緒平均時間),換算**類時間大約是65分鐘,嗯,也就是乙個小時。

我們也知道上下文切換是很耗時的行為,畢竟每次浪費乙個小時,也很讓人有罪惡感的。上下文切換更恐怖的事情在於,這段時間裡 cpu 沒有做任何有用的計算,只是切換了兩個不同程序的暫存器和記憶體狀態;而且這個過程還破壞了快取,讓後續的計算更加耗時。

在 1gbps 的網路上傳輸 2k 的資料

需要20us,換算**類時間是14.4小時,這麼久都能把《星球大戰》六部曲看完了!

可以看到網路上非常少資料傳輸對於 cpu 來說,已經很漫長。而且這裡的時間還是理論最大值,實際過程還要更慢一些。

ssd 隨機讀取

耗時為150us,換算**類時間大約是4.5天。換句話說,ssd 讀點資料,cpu 都能休假,報團參加周邊遊了。

雖然我們知道 ssd 要比機械硬碟快很多,但是這個速度對於 cpu 來說也是像烏龜一樣。i/o 裝置 從硬碟開始速度開始變得漫長,這個時候我們就想起記憶體的好處了。儘量減少 io 裝置的讀寫,把最常用的資料放到記憶體中作為快取是所有程式的通識。像 memcached 和 redis 這樣的快取記憶體系統近幾年的異軍突起,就是解決了這裡的問題。

從記憶體中讀取 1mb 的連續資料

耗時大約為250us,換算**類時間是7.5天,這次假期公升級到國慶七天國外遊。

同乙個資料中心網路上跑乙個來回

需要0.5ms,換算**類時間大約是15天,也就是半個月的時間。

如果你的程式有段**需要和資料中心的其他伺服器互動,在這段時間裡 cpu 都已經狂做了半個月的運算。減少不同服務元件的網路請求,是效能優化的一大課題。

從 ssd 讀取 1mb 的順序資料

大約需要1ms,換算**類時間是1個月

也就是說 ssd 讀乙個普通的檔案,如果要等你做完,cpu 乙個月時間就荒廢了。儘管如此,ssd 已經很快啦,不信你看下面機械磁碟的表現。

磁碟定址時間

10ms,換算**類時間是10個月,剛好夠人類創造乙個新的生命了。

如果 cpu 需要讓磁碟泡杯咖啡,在它眼裡,磁碟去生了個孩子,回來告訴它你讓我泡的咖啡好了。機械硬碟使用 rpm(revolutions per minute/每分鐘轉速) 來評估磁碟的效能:rpm 越大,平均定址時間更短,磁碟效能越好。定址只是把磁頭移動到正確的磁軌上,然後才能讀取指定扇區的內容。換句話說,定址雖然很浪費時間,但其實它並沒有辦任何的正事(讀取磁碟內容)。

從磁碟讀取 1mb 連續資料

20ms,換算**類時間是20個月

io 裝置是計算機系統的瓶頸,希望讀到這裡你能更深切地理解這句話!如果還不理解,不妨想想你在網上買的東西,快遞送了將近兩年,你的心情是怎麼樣的。

從世界上不同城市網路上走乙個來回

平均需要150ms(參考世界各地 ping 報文的時間),換算**類時間是12.5年

不難理解,所有的程式和架構都會盡量避免不同城市甚至是跨國家的網路訪問,cdn就是這個問題的乙個解決方案:讓使用者和最接近自己的伺服器互動,從而減少網路上報文的傳輸時間。

虛擬機器重啟一次

大約要4s時間,換算**類的時間是3百多年

對於此,我想到了賈伯斯要死命優化 mac 系統開機啟動時間的故事。如果機器能少重啟而且每次啟動能快一點,不僅能救人命,也能救 cpu 的命。

物理伺服器重啟一次

需要5min,換算**類時間是2萬5千年,快趕上人類的文明史了。

5 分鐘人類都要等一會了,更別提 cpu 了,所以沒事不要亂重啟伺服器啊,分分鐘終結乙個文明的節奏。

參考資料

what every programmer should know about memory

getting physical with memory

準確獲取CPU時間

include stdafx.h include include include include const char tmpfilename tmptestfile const char teststr 0123456789 const int teststrlen 10 const double...

觀把時間做朋友有感

今天開始看 把時間當做朋友 這本書,書中說人類所有的原罪都歸結於 懶惰 想想的確是的,為什麼你沒去做,又在抱怨呢,一切只是因為太懶罷了。並不是所有的事情都是因為有興趣才可以做好,而是因為做好了所以產生了興趣,學習的時候不是這樣嗎?因為在學習英語的時候覺得很難,所以不去學習,但是只要你嚐到的甜頭,建立...

中斷占用CPU的時間分析

本篇從一道題目出發理清楚這類題目想表達的意思。這類題目很有趣的一點在於,從不同的角度思考,複雜度是不一樣的。也就是,用正確的思路去想,就很簡單且自然。假設乙個計算機系統具有如下效能特徵 處理一次中斷平均需要500us,一次程序排程平均需要花費1ms,程序的切換平均需要花費2ms。若該計算機系統的定時...