存儲器的層次結構

對於一個計算機小白來講,可能內存、硬盤、存儲卡的名詞都還有些模糊,今天來瞭解一下相關的概念。

在之前的學習中,我們始終假設這樣一個簡單模型:存儲器系統是一個線性的字節數組,CPU可以在一個常數時間內訪問每個存儲器的位置。然而實際的情況是,存儲器系統是一個具有不同容量、成本和訪問時間的存儲設備的層次結構。如下圖所示:

一般而言,從高層往底層走,存儲設備變得更慢、更便宜和更大。最高層L0,是少量的CPU寄存器,CPU可以在一個時鐘周期內訪問它們;接下來是基於SRAM的高速緩存存儲器(cache, 讀作“cash”),CPU可以在幾個時鐘周期內訪問它們;然後是一個大的基於DRAM的主存,CPU可以在幾十到幾百個周期內訪問它們;接下來是慢速但是容量很大的本地磁盤,訪問它們時延打到毫秒級;最後,有些系統會有遠程服務器磁盤,可以通過網絡來訪問它們。

當CPU準備訪問內存中的某個地址的數據時,會首先到L1cache中去查找,如果剛好數據在L1緩存中,那麼CPU就讀取瞭該數據,這就是緩存命中(cache hit)。如果L1cache中沒有對應的數據,這種情況稱為緩存不命中(cache miss),那麼L1cache就會到L2cache中去查找,將找到的數據返回到L1cache;如果L2cache中還是cache miss,就會到L3cache中查找,將找到的數據返回給L2cache。如果L3cache中還是miss,最終會訪問到主存中。

總之,每一層存儲設備都是較低一層的緩存。L1,L2和L3層的緩存完全由內置在緩存中的硬件邏輯來管理的。

常見的存儲介質

1、隨機訪問存儲器

隨機訪問存儲器(Random-Access Memory, RAM)分為兩類:靜態RAM和動態RAM。靜態RAM(SRAM)用來作為高速緩存存儲器(cache),可以在CPU芯片上,也可以在片外。動態RAM(DRAM)用來作為主存以及圖形系統的幀緩沖區。

SRAM:每一位都存儲在一個雙穩態的存儲器單元裡,每個單元是用6個晶體管來實現的。隻要有電,這樣一個電路可以無限期地保持在兩個不同的電壓配置或者狀態之一。即使有幹擾,當幹擾消除後,電路就會恢復到穩定值。

DRAM:每一位存儲都是對一個電容充電,隻不過電容很小,通常約30毫皮法(30 x 10^-15法拉)。很多原因導致漏電,使得DRAM在10~100毫秒時間內失去電荷,幸好CPU的時鐘通常在納秒級,因此相對而言DRAM電壓還是比較穩定的。由於要放電,因此內存系統必須周期性地通過讀出,然後重寫來刷新內存的每一位,這也是“動態”兩個字的由來。

2、非易失性存儲器

上面說的SRAM和DRAM在斷電的情況下都會丟失數據,有一種非易失性存儲器在斷電後,仍然可以保存原本的信息。由於歷史原因,雖然有的類型可以讀也可以寫,但是它們整體上被稱為隻讀存儲器(Read-Only Memory, ROM)。

PROM:Programmable ROM,可編程ROM,但隻能被編程一次。每個存儲器單元有一個熔絲(fuse),隻能用高電流熔斷一次。

EPROM:Erasable Programmable ROM,可擦寫可編程ROM, 被擦除和重編程的次數可達1000次。EPROM有一個透明的石英窗口,允許光到達存儲單元,紫外線照射過窗口,EPROM單元就被清0;對EPROM編程是通過使用一種把1寫入EPROM的特殊設備完成。

EEPROM:Electrically Erasable PROM,電子可擦除PROM,它不需要物理上的一個獨立編程設備,可以直接在電路板上編程。被編程次數可達10^5次。

閃存:flash, 基於EEPROM,已經成為一種重要的存儲技術。閃存無處不在,為大量的電子設備提供快速而持久的非易失性存儲,包括數碼相機、手機、MP3、筆記本等。

固件:存儲在ROM設備中程序通常被稱為固件(firmware)。例如,當我們自己的筆記本開機後,會首先進入BIOS,然後才會啟動windows操作系統,這裡BIOS的程序就是存放在啟動ROM中的固件。

3、磁盤存儲

磁盤被封裝成一個密封的包裝,整個裝置通常被稱為磁盤驅動器(disk drive),簡稱磁盤(disk),有時也稱為旋轉磁盤,或是更通俗的機械硬盤。

磁盤由一個或多個盤片(platter)構成,每個盤片有兩個表面,表面覆蓋著磁性記錄材料。盤片中央有個主軸(spindle),盤片可以繞它以固定速率旋轉,通常5400~15000轉每分鐘(RPM)。

盤片的每個表面由一組稱為磁道的同心圓組成,每個磁道被劃分為一組扇區,每個扇區包含相等數量的數據位(通常512字節),用戶數據存放在扇區中。扇區之間用間隙(gap)分隔開,這些間隙不存儲用戶的數據位,而用來標識扇區的格式化位。

磁盤制造商通常用術語柱面(cylinder)來描述多個盤片的構造,柱面是所有盤片表面上到主軸中心距離相等的磁道的集合,這些集合就像一個圓柱一樣。例如,如果一個驅動器有三個盤片和六個面,每個表面上的磁道的編號都是一致的,那麼柱面k就是6個磁道k的集合。

有一點需要留意的是,不同的磁道有數目相同的扇區,扇區數目是由最靠內的磁道能記錄的扇區數決定的。(PS:由最靠內的磁道扇區數決定的說法其實是不太準確的,現代大容量磁盤使用一種稱為多區記錄的技術,一個區內的每個柱面的每條磁道都有相同數量的扇區,由該區中最裡面的磁道所能包含的扇區數確定)。

例如,我們有個磁盤,有5個盤片,每個扇區512字節,每個面有20000條磁道,每條磁道平均300個扇區。那麼磁盤容量就是:

512字節×300扇區×20000磁道×2表面×5盤片=30.72GB

旁註:像K, M,G, T這樣的前綴的含義依賴於上下文。對於與DRAM和SRAM容量相關的計量單位,通常K=2^10, M=2^20, G=2^30,T=2^40。對於像磁盤和網絡這樣的I/O設備容量相關的計量單位,通常K=10^3, M=10^6,G=10^9,T=10^12。速率和吞吐量也使用這些前綴。幸運的是,我們通常依賴的是估計值,無論哪種假設在實際中都可以使用。例如,2^30與10^9之間相對差別不大,隻有約7%。

通常磁盤的訪問時間較長,為毫秒級。這是因為磁盤的讀寫操作是通過機械運動來實現的。

磁盤通過讀/寫頭來讀寫存儲在磁性表面的位,而讀寫頭連接到傳動臂一端,通過沿著半徑軸前後移動這個傳動臂,驅動器可以將讀寫頭定位在盤面上的任何磁道上。這一機械運動稱為尋道(seek),移動傳動臂所需的時間稱為尋道時間,現代驅動器的平均尋道時間大概3~9ms,最大尋道時間可達20ms。有多個盤片的磁盤針對每個盤面都有一個獨立的讀寫頭,讀寫頭垂直排列,一致行動,在任何時刻,所有的讀寫頭都位於同一柱面上。

讀寫頭一旦定位到瞭期望的磁道,驅動器就等待目標扇區的第一個位旋轉到讀寫頭下面。最壞的情況就是,讀寫頭剛剛錯過瞭目標扇區,需要等待磁盤轉一圈,最大旋轉延時就是磁盤轉一圈的時間,平均旋轉延時取其一半。

從開始讀目標扇區的第一個位到整個扇區讀完,稱為這個扇區的傳送時間。一個扇區的傳送時間依賴於磁盤旋轉的速度和每條磁道的扇區數目。

舉例,一個磁盤的旋轉速率7200RPM,平均尋道時間為9ms,每條磁道平均扇區數400,則有:

平均旋轉時間=60s/7200/2≈4ms

平均傳送時間=60s/7200RPM/400≈0.02ms

總之,磁盤平均訪問時間=9ms+4ms+0.02ms=13.02ms。

雖然上面介紹瞭盤面、扇區、柱面的概念,但是操作系統並不關心這些,這是因為磁盤控制器提供瞭一個簡單的抽象,呈現給操作系統的是一個扇區大小的邏輯塊的序列,編號為0,1,2,…。操作系統隻需要提供邏輯塊號,磁盤控制器則將邏輯塊號轉換成對應的實際物理扇區。

4、固態硬盤

固態硬盤(Solid State Disk,SSD)是一種基於閃存的存儲技術,是上述傳統旋轉磁盤的極有吸引力的替代產品。一個SSD封裝由一個或多個閃存芯片和閃存翻譯層(flash translation layer)組成,閃存芯片替代傳統旋轉磁盤中的機械驅動器,閃存翻譯層是一個硬件/固件設備,扮演與磁盤控制器相同的角色。

SSD的讀比寫快。一個閃存由多個塊組成,每個塊由多個頁組成。通常頁的大小是512字節~4KB,塊由32~128頁組成,塊的大小為16KB~512KB。註意,數據是以頁為單位讀寫的,隻有一頁所屬的塊被整個擦除後,才能寫這一頁(指塊中所有的位都被置1),一旦整塊被擦除瞭,塊中的每一頁都可以不需要再擦除就可以寫。在大約進行10^5次重復寫後,塊就會磨損壞,就不能再用瞭。

寫比較慢有兩個原因:

(1)擦除塊時間長,毫秒級的,比訪問頁的時間高一個數量級;

(2)如果寫操作視圖修改一個包含已經有數據的頁(該頁中不全為1),那麼這個塊中所有帶有用數據的頁都必須被復制到一個新的塊,然後才能繼續修改原來的頁。

SSD的有點很多,例如它沒有移動的部件,由半導體存儲器構成,隨機訪問時間比旋轉磁盤更快,能耗更低,也更結實。缺點主要有兩個:

(1)由於閃存會磨損,閃存翻譯層中的平均磨損邏輯試圖將擦除平均分佈在所有的塊上來最大化每個塊的壽命。實際上,平均磨損邏輯處理的非常好,通常SSD需要很多年才會磨損壞。

(2)SSD每字節要比旋轉磁盤貴30倍,因此常用的SSD容量也比旋轉磁盤要小。不過隨著技術發展,兩者的價格差也在縮小。

局部性

一個好的計算機程序通常有好的局部性,也就是說,他們傾向於引用鄰近的數據項或者最近引用過的數據項,這種傾向性被稱為局部性原理。引用鄰近地址的數據項體現的是空間局部性,使用引用過的數據項體現的是時間局部性。

這種局部性其實是依賴於上述的存儲器的金字塔般的層次結構,因為一個局部性好的程序通常會比局部性差的程序運行更快。例如,對於一個重復使用的變量或是代碼通常會保存在高速緩存存儲器(cache)中,而不必從主存中去讀取,要知道主存的訪問時間是cache的10倍多;此外,當訪問某個地址的變量時,一般鄰近地址的變量也會被加載到cache中。

局部性對於編程的啟示:

  • 重復引用相同變量的程序具有良好的時間局部性;
  • 對於具有步長為k的引用模式的程序,步長越小,空間局部性越好。在內存中,大步長跳來跳去空間局部性會很差;
  • 循環有好的時間和空間局部性,循環體越小,循環次數越多,局部性越好。

小結

(1)CPU訪問內存,會首先從cache中查找,然後才一層一層向下查找;

(2)如今的存儲器層次結構是性能和價格之間平衡的結果。


本文來自微信公眾號:阿管學習錄

持續更新學習的新知識,科學、哲學、社科……歡迎關註~

赞(0)