計算機硬件的讀寫速度差異
?現代計算機系統
現代計算機系統與馮·諾依曼計算機差別不大,最大的區別馮·諾依曼計算機 是 以運算器為中心的,而現代計算機 以儲存器為中心:
我們主要來看一下其中與儲存相關的組件:
存儲器
存儲器是用來存放數據和程序。存儲器 包含主存和輔存
- 主存:直接與CPU交換信息,就是我們熟悉的內存。斷電后內存的數據是會丟失的
- 輔存:輔存可作為主存的后備存儲器,不直接與CPU交換信息,容量比主存大,但速度比主存慢。比如機械硬盤、固態硬盤等。斷電后硬盤的數據是不會丟失,硬盤是持久化存儲設備。
- 輔存、輸入設備、輸出設備? 統稱為IO設備;主機一般包含:CPU、主存
我們先來看看存儲器的層次結構,來初步對各個儲存器部件有所認識
我們可以發現存儲器速度越快的話,相應的價格也會越發昂貴!
寄存器
CPU中 還有一個常見的組件: 寄存器,是CPU內部用來存放數據的一些小型的存儲區域,用來暫時存放參與運算的數據以及運算結果。寄存器由電子線路組成,存取速度非常快,寄存器的成本較高,因而數量較少。
CPU時鐘周期
CPU時鐘周期:通常為節拍脈沖或T周期,即主頻的倒數,它是CPU中基本時間單位。平時我們打游戲常說的超頻,超的就是這個CPU主頻。
舉個例子,主頻為3.0GHZ的CPU,一個時鐘周期大約是0.3納秒,內存訪問大約需要120納秒,固態硬盤訪問大約需要50-150微秒,機械硬盤訪問大約需要1-10毫秒,最后網絡訪問最慢,得幾十毫秒左右。
這個大家可能對時間不怎么敏感,那如果我們把一個時鐘周期如果按1秒算的話,內存訪問大約就是6分鐘 ,固態硬盤大約是2-6天 ,傳統硬盤大約是1-12個月,網絡訪問就得幾年了!我們可以發現CPU的速度和內存等存儲器的速度,完全不是一個量級上的。
高速緩存
為了彌補 CPU 與內存兩者之間的性能差異,就在 CPU 內部引入了 CPU Cache?,也稱高速緩存。CPU Cache用的是 SRAM(Static Random-Access Memory)的芯片,也叫靜態隨機存儲器。其只要有電,數據就可以保持存在,而一旦斷電,數據就會丟失。
CPU Cache 通常分為大小不等的三級緩存,分別是 L1 Cache、L2 Cache 和 L3 Cache
部件 | CPU訪問所需時間 | 備注 |
L1 高速緩存 | 2~4 個時鐘周期 | 每個 CPU 核心都有一塊屬于自己的 L1 高速緩存,L1 高速緩存通常分成指令緩存和數據緩存。 |
L2 高速緩存 | 10~20 個時鐘周期 | L2 高速緩存同樣是每個 CPU 核心都有的 |
L3 高速緩存 | 20~60個時鐘周期 | L3 高速緩存是多個 CPU 核心共用的 |
我們可以發現越靠近 CPU 核心的緩存其訪問速度越快。
程序執行時,會先將內存中的數據加載到共享的 L3 Cache 中,再加載到每個核心獨有的 L2 Cache,最后 進入到最快的 L1 Cache,之后才會被 CPU 讀取。層級關系如下圖:
主存
主存,直接與CPU交換信息,就是我們熟悉的內存。它使用的是一種叫作 DRAM(Dynamic Random Access Memory)的芯片,也叫動態隨機存取存儲器。斷電后內存的數據是會丟失。DRAM 芯片的密度更高,功耗更低,有更大的容量,造價比 SRAM 芯片便宜很多,但速度比SRAM 芯片慢的多。
內存速度大概在 200~300 個 時鐘周期之間
固態硬盤
固體硬盤(Solid-state Disk, SSD),數據直接存在閃存顆粒中,并且由主控單元記錄數據存儲位置和數據操作,每一個閃存顆粒的存儲容量是有限的;
但是它相比內存的優點是斷電后數據還是存在的,SSD固體硬盤的讀寫速度雖然比內存的大概慢10~1000 倍,但比機械硬盤快多了,當然價格也昂貴很多。不過隨著時代的發展,固態硬盤的價格慢慢趨向接近機械硬盤。
機械硬盤
機械硬盤(_Hard Disk Drive, HDD_),它是通過物理讀寫的方式來訪問數據的,機械硬盤在盤面上寫數據、磁盤轉動,機械臂移動,比較原始的數據讀寫方式,就像近現代的留聲機發聲原理一樣。
由于受限于轉盤轉速與指針尋址的時間限制,因此它訪問速度是非常慢的,它的速度比內存慢 10W 倍左右。當然機械硬盤也是有其優點的:容量大,價格便宜,恢復數據難度低,因此數據放在機械硬盤中比較保險。
壓榨CPU性能帶來的問題
由于CPU速度非常快,且價格非常昂貴,我們必須得充分壓榨CPU,得像生產隊的驢一樣,讓它不停地工作
為了合理利用 CPU 的高性能,同時盡可能地節約成本,現代計算機將這些儲存器充分的結合起來,由于這些硬件的數據存取速度差異導致了計算機系統編程中的各種問題:
有序性問題
為了充分壓榨CPU的性能,CPU 會對指令亂序執行或者語言的編譯器會指令重排,讓CPU一直工作不停歇,但同時會導致有序性問題。
在CPU中為了能夠讓指令的執行盡可能地同時運行起來,采用了指令流水線。一個 CPU 指令的執行過程可以分成 4 個階段:取指、譯碼、執行、寫回。這 4 個階段分別由 4 個獨立物理執行單元來完成。
理想的情況是:指令之間無依賴,可以使流水線的并行度最大化。但是如果兩條指令的前后存在依賴關系,比如數據依賴,控制依賴等,此時后一條語句就必需等到前一條指令完成后,才能開始。所以CPU為了提高流水線的運行效率,對無依賴的前后指令做適當的亂序和調度。
還有一種情況編譯器會指令重排,比如java語言,JVM 的編譯器會對其指令進行重排序的優化(指令重排)。
所謂指令重排是指在不改變原語義的情況下,通過調整指令的執行順序讓程序運行的更快。JVM中并沒有規定編譯器優化相關的內容,也就是說JVM可以自由的進行指令重排序的優化。
無論是編譯期的指令重排還是CPU 的亂序執行,主要都是為了讓 CPU 內部的指令流水線可以“填滿”,提高指令執行的并行度,充分利用CPU的高性能。
可見性問題
為了平衡CPU的寄存器和內存的速度差異,計算機的CPU 增加了高速緩存,但同時導致了 可見性問題。我們知道當程序執行時,一般CPU會去從內存中讀取數據,來進行計算。CPU計算完之后,需要把數據重新放回到內存中。
當CPU的多個核心參與一個程序的運行,從內存中讀取一個共享變量的數據,當不同核心間進行了各自的計算,把計算后的值放入自己的緩存中而不選擇立即寫入內存中(CPU寫入內存的時機是不確定的)。那么在CPU的緩存中,這個共享變量有可能存放著不同的數據,這就導致了緩存的可見性問題。即一個線程對數據的修改無法對其他線程可見。
原子性問題
為了平衡CPU 與 I/O 設備?的速度差異,操作系統增加了進程、線程?概念,以分時復用 CPU,但同時導致了原子性問題。
原子操作就是不可分割的操作,在計算機中,就是指不會因為線程調度被打斷的操作。
當一個程序去I/O 設備讀取數據, 由于I/O 設備數據存入讀取速度,相比于CPU的執行速度來說度日如年,CPU這么牛逼這么昂貴的寶貝,怎么能讓它歇著,得讓它一直干活,去切換執行其他程序。也就是將CPU的時間進行分片,讓各個程序在CPU上輪轉執行。但被剝奪執行權的程序,等它從IO讀取完數據后,還是得讓CPU繼續執行的,這時需要一個數據結構來保存,以便之后恢復繼續執行,這個就是進程。
一開始進程中 只有一個"執行流",干活的人就一個。隨著任務越來越多,發現進程不夠用了,經常導致整個程序被阻塞,這時計算機讓進程有多個執行流,干活的人變多了,那程序就不會再被阻塞了,"執行流" 就是線程。
如何解決這3個問題,就是并發、多線程需要處理的事,當然這是后話。
參考資料:
《深入理解計算機系統》
《計算機組成原理》
《計算機組成原理》--唐朔飛
https://zhuanlan.zhihu.com/p/379947484
本文轉載自微信公眾號「 小牛呼嚕嚕」,作者「小牛呼嚕嚕」,可以通過以下二維碼關注。