1. 引言
早期的電腦簡單許多。由於系統中的眾多元件,如 CPU、記憶體、大容量儲存裝置(mass storage)、以及網路介面(network interface),是一同被發展出來的,也因此在效能上相當平衡。舉例來說,在提供資料時,記憶體與網路介面並不比 CPU 來得快(非常多)。
這個情況隨著電腦基礎結構的穩定、以及硬體開發者專注於最佳化獨立的子系統而改變了。某些電腦元件的效能突然大幅地落後並成為了瓶頸。尤其是大容量儲存裝置與記憶體––由於成本的緣故––相比於其他系統,進步得十分緩慢。
大容量儲存裝置的效能問題主要由軟體技術解決:作業系統(operating system)在主記憶體(main memory)––其在存取上比硬碟(hard disk)快了幾個數量級––中保存了最常使用(並且最有可能被使用)的資料。快取亦被加到儲存裝置中,其不需對作業系統作任何改變就能提升效能。1由於偏離本文的主旨,我們就不繼續深入針對大型儲存裝置存取的軟體最佳化細節了。
不若儲存子系統一般,解決主記憶體的瓶頸已被證實更加困難,而且幾乎所有的解決方法都必須改變硬體。現今這些改變主要有以下這些方式:
- RAM 的硬體設計(速度以及平行度〔parallelism〕)。
- 記憶體控制器(controller)的設計。
- CPU 快取。
- 裝置的直接記憶體存取(Direct Memory Access,DMA)。
本文主要涉及 CPU 快取以及記憶體控制器設計的一些影響。在探索這些主題的過程中,我們將對 DMA 有更深入的理解。不過,我們要先概觀地從現今商用硬體的設計開始。這是理解有效使用記憶體子系統的問題與限制的必要條件。我們也會––稍加詳細地––學到不同類型的 RAM,並闡述為何這些差異依舊存在。
這篇文件絕非最終且完整的。本文僅止於商用硬體,而且僅限這類硬體的一個子集。同時,許多主題的討論僅點到為止,以能達到本文目的為主。對於這些主題,建議讀者去尋找更詳盡的文件。
當提及特定作業系統的細節與解法時,本文僅特指 Linux。無論何時都不會涵蓋其他 OS 的任何資訊。作者無意著墨於其它的 OS。假如讀者認為他/她必須使用不同的 OS,那麼他/她得去尋求供應商撰寫與本文相似的文件。
開始前的最後一點說明。本文包含許多「通常」以及其他類似的修飾語。在這裡討論的技術在現實世界中存在著非常非常多不同的變種,而本文僅針對最常見、最主流的版本。這些技術很少能下定論,是故以此言之。
文件結構
本文主要寫給軟體開發者,不會深入對硬體導向的讀者有用的硬體技術細節。但在我們能夠討論對開發者實用的資訊之前,有許多基礎得打。
為了達到這個目標,第二節會以技術細節面描述隨機存取記憶體(Random-Access Memory,RAM)。這一節的內容值得一讀,但對於理解後面幾節並非必要。在需要此節內容之處都會加上合適的引用(back reference),所以心急的讀者可以先略過本節的大部分內容。
第三節描述了許多 CPU 快取行為的細節。本節會用上一些圖表以避免文字變得枯燥乏味。本節內容是理解本文後續章節所不可或缺的。第四節簡述了虛擬記憶體(virtual memory)如何實作。這也是其餘部份的必要基礎。
第五節描述了非均勻記憶體存取(Non-Uniform Memory Access,NUMA)系統的諸多細節。
第六節是本文的核心章節。其將先前幾節的資訊總結在一起,並給予程式設計師如何能在不同情境中撰寫良好運作的程式建議。非常不耐煩的讀者可以從此節開始,並且––必要的話––回到先前的章節回顧基礎技術的知識。
第七節介紹了一些能夠幫助程式設計師做得更好的工具。即使完全理解了這些技術,距離明確複雜軟體專案的問題所在仍十分遙遠。某些工具是必要的。
最後在第八節,我們將展望可以在未來幾年期待、或是希望擁有的技術。
回報問題
作者想要更新這份文件一段時間。這包含了不僅得隨著技術推進而更新,也要修正錯誤。樂於回報問題的讀者可以來信給作者。但請在回報中包含精確的版本資訊。版本資訊可以在文件的最後一頁找到。
致謝
我要感謝 Johnray Fuller 以及 LWN 的夥伴們(尤其是 Jonathan Corbet 承擔著將作者式的英文改成更加傳統形式的艱鉅任務)。Markus Armbruster 針對本文的問題與疏忽提供了諸多有價值的建議。
關於本文
本文標題致敬於 David Goldberg 的經典論文《What Every Computer Scientist Should Know About Floating-Point Arithmetic》。這篇論文仍鮮少人知,雖然這應該是任何勇於嚴謹地撰寫程式而敲下鍵盤者的先決條件。
1. 然而,為了保證使用儲存裝置快取時的資料完整性(data integrity),改變是必要的。 ↩