原文:What every programmer should know about memory, Part 1
1.簡介
早期的計算機(jī)比較簡單。各種各樣的系統(tǒng)組件食寡,例如CPU熄捍,內(nèi)存烛恤,大容量存儲,網(wǎng)絡(luò)接口余耽,是一起開發(fā)的缚柏,所以它們的性能比較均衡。例如碟贾,在給CPU提供數(shù)據(jù)的時候币喧,內(nèi)存并不比網(wǎng)絡(luò)接口快(很多)。
當(dāng)計算機(jī)的基本結(jié)構(gòu)固化袱耽,硬件開發(fā)者開始專注優(yōu)化各個子系統(tǒng)時杀餐,這種情況發(fā)生了改變,某些計算機(jī)組件的性能顯著落后而且出現(xiàn)瓶頸朱巨。特別的史翘,由于成本原因,相對于其他組件冀续,大容量存儲跟內(nèi)存子系統(tǒng)提高的更慢琼讽。
大容量存儲的性能問題主要靠軟件來改善:操作系統(tǒng)將最常用(跟最有可能被使用)的數(shù)據(jù)放在主存中,因為其訪問速率比硬盤要快幾個數(shù)量級洪唐。將緩存添加到存儲設(shè)備本身钻蹬,這樣就可以在不更改操作系統(tǒng)的情況下提高性能(然而,為了使用緩存時凭需,保證數(shù)據(jù)的完整问欠,改變還是需要的)。研究該內(nèi)容不是本文的目的粒蜈,我們不涉及過多的介紹大容量存儲訪問的軟件優(yōu)化顺献。
與大容量存儲不同,解決內(nèi)存的瓶頸被證明更為困難薪伏,幾乎每種方案都需要對硬件作出修改滚澜。目前,這些變更主要有以下這些方式:
- RAM(隨機(jī)存取存儲器)硬件的設(shè)計(速度與并發(fā)度)
- 內(nèi)存控制設(shè)計
- CPU緩存
- 設(shè)備的直接內(nèi)存訪問(DMA)
本文主要介紹CPU緩存和內(nèi)存控制器設(shè)計的一些影響。在這些主題的擴(kuò)展過程中设捐,我們將研究DMA跟進(jìn)入更大的場景借浊。我們從現(xiàn)代的商用硬件設(shè)計開始,這將有助于我們理解使用內(nèi)存子系統(tǒng)的問題跟局限萝招。我們將詳細(xì)介紹RAM的分類蚂斤,說明為什么會存在這么多不同類型的內(nèi)存。
本文不會包括所有方面槐沼,也不會有最終性質(zhì)的內(nèi)容曙蒸。我們的討論范圍僅限于商用硬件,并且進(jìn)一步限于該硬件的一部分岗钩。此外纽窟,討論更多的主題,本文以達(dá)到目標(biāo)為止兼吓。對于這些主題臂港,建議讀者查找更詳細(xì)的文檔。
當(dāng)本文提到操作系統(tǒng)特定的細(xì)節(jié)和解決方案時视搏,說的都是Linux审孽,不會包含任何有關(guān)其他操作系統(tǒng)的信息。作者無意討論其他操作系統(tǒng)的情況浑娜,如果讀者不得不使用別的操作系統(tǒng)佑力,那么必須去要求供應(yīng)商提供其操作系統(tǒng)類似于本文的文檔。
如果讀者認(rèn)為他/她不得不使用別的操作系統(tǒng)筋遭,那么必須去要求供應(yīng)商提供其操作系統(tǒng)類似于本文的文檔打颤。
1.1 文檔結(jié)構(gòu)
本文主要為軟件開發(fā)者而寫的,不會涉及太多硬件細(xì)節(jié)漓滔,所以可能對抱著閱讀硬件知識而來的讀者不是很有用瘸洛。但是我們在開始為開發(fā)人員提供有用的信息之前,必須先為他們奠定足夠多的基礎(chǔ)內(nèi)容次和。
本文的第二章節(jié)將描述RAM的技術(shù)細(xì)節(jié)∧欠ィ看懂該章節(jié)的內(nèi)容很好踏施,但是此部分的內(nèi)容并不是懂得其后內(nèi)容所必須掌握的。我們會在之后需要的地方適當(dāng)引用該章節(jié)的內(nèi)容罕邀,所以心急的讀者可以先跳過該章節(jié)的大部分內(nèi)容去讀他們認(rèn)為有用的部分畅形。
第三章節(jié)會談到很多關(guān)于CPU緩存行為的細(xì)節(jié)。我們會使用一些圖表诉探,避免你們覺得太枯燥日熬。第三章節(jié)對于理解整篇文章非常重要。第四章節(jié)將簡要的描述如何實現(xiàn)虛擬內(nèi)存肾胯,這也是理解全文其他部分的必要基礎(chǔ)竖席。
第五章節(jié)會談到很多關(guān)于非統(tǒng)一內(nèi)存訪問架構(gòu)(NUMA)的細(xì)節(jié)耘纱。
第六章節(jié)是本文最主要的內(nèi)容,該部分將回顧前面章節(jié)中的信息毕荐,并且我們將給程序員提供如何寫出在各種情況下都能表現(xiàn)良好的代碼的建議束析。心急的讀者可能會直接閱讀該章節(jié),在必須的情況下憎亚,建議去了解之前章節(jié)的知識员寇。
本文的第七部分將介紹一些能夠幫助程序員更好的完成任務(wù)的工具。即便在徹底理解了某一項技術(shù)的情況下第美,距離徹底理解在非測試環(huán)境下的程序還是很遙遠(yuǎn)的蝶锋。我們需要借助一些工具。
第七章節(jié)介紹了可以幫助程序員更好地完成任務(wù)的工具什往。即使對該技術(shù)有了全面的理解扳缕,在一個實際的軟件項目中,問題在哪里仍然是不明顯的恶守,有些工具是必要的第献。
在第八章節(jié)中,我們將給出了在不久的將來可以預(yù)期的技術(shù)展望兔港。
1.2 反饋問題
作者打算在一段時間內(nèi)持續(xù)更新本文檔庸毫。這包括技術(shù)進(jìn)步所需的更新,以及糾正錯誤衫樊。歡迎報告問題的讀者發(fā)送電子郵件飒赃。
1.3 致謝
我想感謝Johnray Fuller,特別是Jonathan Corbet科侈,他們承擔(dān)了將作者的英語轉(zhuǎn)化成為更為規(guī)范的形式的艱巨任務(wù)的一部分载佳。Markus Armbruster對文本中的問題和遺漏提供了許多有價值的意見。
1.4 關(guān)于本文
這篇論文的標(biāo)題是對David Goldberg的經(jīng)典論文《What Every Computer Scientist Should Know About Floating-Point Arithmetic》[goldberg]的致敬臀栈。Goldberg的論文至今尚未廣為人知蔫慧,盡管它應(yīng)該是任何敢于接觸鍵盤來進(jìn)行嚴(yán)格編程的人的先決條件。
2.商用硬件現(xiàn)狀
理解商用硬件是很重要的权薯,因為專業(yè)硬件逐漸退出」枚悖現(xiàn)如今的擴(kuò)展通常是水平而不是垂直實現(xiàn)的,使用許多較小的互聯(lián)的商用計算機(jī)而不是幾個非常大且異趁蓑迹快速(但昂貴)的系統(tǒng)更具成本效益黍析。這是因為快速和廉價的網(wǎng)絡(luò)硬件已經(jīng)普及。大型專用系統(tǒng)仍然占有一席之地屎开,這些系統(tǒng)仍然是有商機(jī)的阐枣,但整體市場與商用硬件市場相形見絀。2007年Red Hat公司預(yù)計,對于未來的產(chǎn)品蔼两,大多數(shù)數(shù)據(jù)中心的“standard building blocks”將是一臺有多達(dá)四個插槽的計算機(jī)甩鳄,每個插槽上都有一個四核CPU,對于英特爾CPU來說宪哩,它將是超線程的(超線程允許使用單個處理器核進(jìn)行兩個或多個并發(fā)執(zhí)行娩贷,只需少量額外的硬件)。這意味著數(shù)據(jù)中心的標(biāo)準(zhǔn)系統(tǒng)將有多達(dá)64個虛擬處理器锁孟。當(dāng)然彬祖,更大的機(jī)器也是可以的,但四端口插槽品抽,四CPU核心的搭配被認(rèn)為是最佳配置储笑,大多數(shù)優(yōu)化是針對這樣的配置。
商用計算機(jī)的結(jié)構(gòu)之間存在著巨大的差異圆恤。即便如此突倍,我們專注于最重要的差異,可以覆蓋超過90%的此類硬件盆昙。需要注意的是羽历,這些技術(shù)細(xì)節(jié)往往會迅速變化,因此建議讀者考慮撰寫本文的日期淡喜。
這么多年來秕磷,個人計算機(jī)和小型服務(wù)器被標(biāo)準(zhǔn)化到了一個芯片組上,它由兩部分組成: 北橋和南橋炼团,見圖2.1澎嚣。
計算機(jī)中所有的CPU通過總線(FSB)連接到北橋。北橋包含內(nèi)存控制器瘟芝,它的實現(xiàn)決定了用于計算機(jī)的RAM芯片的類型易桃。不同類型的RAM(如DRAM、Rambus和SDRAM)需要不同的內(nèi)存控制器锌俱。
為了能夠訪問其他系統(tǒng)設(shè)備晤郑,北橋必須與南橋通信,南橋通常被稱為I / O橋贸宏,通過各種不同的總線處理與設(shè)備之間的通信贩汉。目前,PCI锚赤,PCI Express,SATA和USB總線是最重要的褐鸥,但南橋也支持PATA线脚,IEEE 1394,串口和并口。比較老的系統(tǒng)上有連接北橋的AGP槽浑侥。這么做是性能的原因姊舵,北橋和南橋之間連接速度不夠快。然而寓落,現(xiàn)在的PCI-E插槽都是連接在南橋上的括丁。
這種系統(tǒng)結(jié)構(gòu)有許多值得注意的地方:
- CPU之間的數(shù)據(jù)通信必須通過用于與北橋通信的同一總線。
- 與RAM的所有通信都必須通過南橋伶选。
- RAM只有一個端口史飞。(在本文檔中,我們將不討論多端口ARM仰税,因為這種類型的RAM不存在于商用硬件中构资,至少程序員無法訪問到。它可以在網(wǎng)絡(luò)路由器等專用硬件中找到陨簇,這些硬件需要很快的速度吐绵。)
- CPU和連接到南橋的設(shè)備之間的通信通過北橋進(jìn)行。
在這種設(shè)計中河绽,有兩個瓶頸立即顯現(xiàn)出來己单。第一個瓶頸涉及訪問設(shè)備的RAM,早期的PC耙饰,設(shè)備之間的通信(通過南/北橋)必須通過CPU纹笼,這對整體系統(tǒng)性能產(chǎn)生了負(fù)面的影響。為了解決這個問題榔幸,一些設(shè)備能夠直接訪問內(nèi)存(DMA)允乐。DMA允許設(shè)備在北橋的幫助下,無需通過CPU介入(及其固有的性能成本)便能存儲數(shù)據(jù)到RAM中或訪問RAM的數(shù)據(jù)削咆。今天牍疏,所有連接到任何總線上的高性能設(shè)備都可以使用DMA。雖然這大大減少了CPU上的工作負(fù)載拨齐,卻占用了北橋的帶寬鳞陨,與CPU形成了爭用。因此瞻惋,必須考慮到這個問題厦滤。
第二個瓶頸來自從北橋到RAM的總線〖呃牵總線的詳細(xì)細(xì)節(jié)取決于安裝的內(nèi)存類型掏导。在較舊的系統(tǒng)上,只有一條總線連接到所有RAM芯片羽峰,因此無法進(jìn)行并行訪問趟咆。最近的RAM類型需要兩個獨立的總線(或稱為DDR2的通道添瓷,見圖2.8),它使可用帶寬加倍值纱。北橋?qū)?nèi)存訪問交錯地分配到兩個通道上鳞贷。最近的內(nèi)存技術(shù)(例如FB-DRAM)增加了更多的通道。
在可用帶寬有限的情況下虐唠,我們需要以一種使延遲最小化的方式來對內(nèi)存訪問進(jìn)行調(diào)度搀愧。正如我們將要看到的,盡管使用了CPU緩存疆偿,處理器的速度比內(nèi)存要快得多咱筛,必須等待才能訪問內(nèi)存。如果多個超線程內(nèi)核或處理器同時訪問內(nèi)存翁脆,則訪問內(nèi)存的等待時間甚至更長眷蚓。對于DMA操作也是如此。
然而反番,除了并發(fā)以外沙热,訪問模式本身也對存儲子系統(tǒng)的性能有很大的影響,特別是在多個存儲通道的情況下罢缸。有關(guān)RAM訪問模式的詳細(xì)信息篙贸,請參閱2.2節(jié)。
在一些更昂貴的系統(tǒng)上枫疆,北橋?qū)嶋H上并不包含內(nèi)存控制器爵川。相反,北橋可以連接到許多外部內(nèi)存控制器(在下面的示例中息楔,其中四個)寝贡。
該體系結(jié)構(gòu)的優(yōu)點是存在多個內(nèi)存總線,因此總帶寬增加值依。此設(shè)計還支持更多的內(nèi)存圃泡。并發(fā)內(nèi)存訪問模式通過同時訪問不同的內(nèi)存區(qū)來減少延遲。當(dāng)多個處理器直接連接到北橋時尤其如此愿险,如圖2.2所示颇蜡。對于這樣的設(shè)計,最主要的限制是北橋的內(nèi)部帶寬辆亏,這對于這個體系結(jié)構(gòu)(來自Intel)來說是非常明顯的风秤。(為了完整起見,應(yīng)該指出扮叨,這種內(nèi)存控制器可用于其他用途缤弦,如“memory RAID”,與熱插拔內(nèi)存結(jié)合使用彻磁。)
使用多個外部存儲器控制器并不是增加存儲器帶寬的唯一方法碍沐。另一種日益流行的方法是將內(nèi)存控制器集成到CPU中惦费,并將內(nèi)存連接到每個CPU。這種體系結(jié)構(gòu)在基于AMD的Opteron處理器的SMP系統(tǒng)中得到了廣泛的應(yīng)用抢韭。圖2.3顯示了這樣一個系統(tǒng)。Intel則會從Nehalem處理器開始支持通用系統(tǒng)接口(CSI)恍箭;這基本上是相同的方法:集成內(nèi)存控制器刻恭,,為每個處理器提供本地內(nèi)存扯夭。
有了這樣的體系結(jié)構(gòu)鳍贾,可用的內(nèi)存庫( memory banks)就可以像處理器一樣多。在四CPU機(jī)器上交洗,內(nèi)存帶寬是四倍的骑科,而不需要復(fù)雜的具有巨大帶寬的北橋。將內(nèi)存控制器集成到CPU中還有一些額外的優(yōu)點构拳;我們不會在這里更深入地研究這一技術(shù)咆爽。
這種架構(gòu)也有缺點。首先置森,由于機(jī)器仍然必須使所有處理器都可以訪問系統(tǒng)的所有內(nèi)存斗埂,因此內(nèi)存不再是統(tǒng)一的(NUMA即得名于此)。處理器能以正常的速度訪問本地內(nèi)存(連接到該處理器的內(nèi)存)凫海。訪問連接到另一個處理器的內(nèi)存時呛凶,情況會有所不同。在這種情況下行贪,必須使用處理器之間的互連通道漾稀。要從CPU1訪問連接到CPU2的內(nèi)存,需要跨一個互連通道進(jìn)行通信建瘫。如果它需要訪問CPU 4的內(nèi)存崭捍,那么需要跨越兩條互聯(lián)通道。
每個這樣的通信都有相關(guān)的成本暖混。當(dāng)我們描述訪問遠(yuǎn)程內(nèi)存所需的額外時間時缕贡,我們用「NUMA因子」這個詞。圖2.3中的示例體系結(jié)構(gòu)對于每個CPU有兩個級別:相鄰的CPU和兩個互連之外的CPU拣播。更加復(fù)雜的系統(tǒng)中晾咪,層級也更多。還有一些機(jī)器體系結(jié)構(gòu)(例如IBM的x 445和SGI的Altix系列)贮配,其中有多種類型的連接谍倦。CPU被組織成節(jié)點;在節(jié)點內(nèi)泪勒,訪問內(nèi)存的時間可能是一致的昼蛀,或者只有很小的NUMA因子宴猾。但是,節(jié)點之間的連接可能代價很大叼旋,NUMA因子可能相當(dāng)高仇哆。
目前,商用的NUMA機(jī)器已經(jīng)存在夫植,將來可能會發(fā)揮更大的作用讹剔。預(yù)計從2008年底開始,每臺SMP機(jī)器都將使用NUMA详民。每個在NUMA上運行的程序都應(yīng)該認(rèn)識到NUMA的代價延欠。在第5節(jié)中,我們將討論更多的架構(gòu)沈跨,以及Linux內(nèi)核為這些程序提供的一些技術(shù)由捎。
除了本節(jié)中所介紹的技術(shù)之外,還有幾個其他因素影響RAM的性能饿凛。它們不能被軟件控制狞玛,這就是為什么本節(jié)沒有討論它們的原因。有興趣的讀者可以在2.1節(jié)中了解其中一些因素笤喳。介紹這些技術(shù)为居,僅僅是因為它們能讓我們更全面地了解內(nèi)存技術(shù),或者是可能在大家購買計算機(jī)時能夠提供一些幫助杀狡。
以下的兩節(jié)主要介紹一些入門級的硬件知識蒙畴,同時討論內(nèi)存控制器與DRAM芯片間的訪問協(xié)議。這些知識解釋了內(nèi)存訪問的原理呜象,程序員可能會得到一些啟發(fā)膳凝。不過,這部分并不是必讀的恭陡,心急的讀者可以直接跳到第2.2.5節(jié)蹬音。
待續(xù)。休玩。著淆。