何 森,遲萬(wàn)慶
(國(guó)防科技大學(xué)計(jì)算機(jī)學(xué)院,湖南 長(zhǎng)沙 410073)
在高性能處理器芯片的研發(fā)和仿真驗(yàn)證過程中,為了滿足處理器對(duì)訪存高帶寬、低延遲的要求,通常采用一種基于數(shù)據(jù)親和性的多核處理器體系結(jié)構(gòu)。吳俊杰[1]對(duì)所謂“數(shù)據(jù)親和性”進(jìn)行了相關(guān)定義,可以認(rèn)為若CPU對(duì)某個(gè)數(shù)據(jù)單元更具有“親和性”,則CPU訪問這個(gè)數(shù)據(jù)單元所需要的時(shí)間周期更短。在這種體系結(jié)構(gòu)下,需要對(duì)CPU進(jìn)行專門設(shè)計(jì)。本文所驗(yàn)證的CPU就是將其中的多個(gè)核劃分為若干分組(panel),每個(gè)panel又分為若干簇(cluster)。根據(jù)每個(gè)panel與整個(gè)存儲(chǔ)空間中各個(gè)物理存儲(chǔ)設(shè)備的親和性(如物理鏈路距離)不同,將存儲(chǔ)空間分成若干大空間,每個(gè)大空間對(duì)應(yīng)一個(gè)panel,組成這個(gè)大空間的這些存儲(chǔ)設(shè)備與對(duì)應(yīng)的panel中的CPU具有最高親和性。進(jìn)一步地,又根據(jù)一個(gè)panel中各個(gè)cluster對(duì)這個(gè)大空間內(nèi)各個(gè)存儲(chǔ)設(shè)備的親和性不同,將這個(gè)大空間劃分為若干子空間,每個(gè)子空間對(duì)應(yīng)一個(gè)cluster。根據(jù)CPU對(duì)存儲(chǔ)單元“數(shù)據(jù)親和性”的不同而將存儲(chǔ)設(shè)備和CPU進(jìn)行分組,就形成了一種NUMA結(jié)構(gòu)[2,3]。當(dāng)多核處理器中的CPU訪問所在cluster或者panel對(duì)應(yīng)的具有“親和性”的存儲(chǔ)設(shè)備空間時(shí),將具有高帶寬、低延遲的特點(diǎn)。
操作系統(tǒng)作為硬件資源的管理者,必須為用戶提供高效的支持方式以充分利用NUMA特性。一般而言,操作系統(tǒng)內(nèi)核與系統(tǒng)固件通過約定方式,如ACPI、設(shè)備樹等方式獲取CPU的NUMA信息。本文開展的工作是通過讀取Boot-Loader傳入的設(shè)備樹文件,從中獲取每個(gè)NUMA結(jié)點(diǎn)包含的CPU和物理內(nèi)存等資源信息。其中,物理內(nèi)存信息是通過連續(xù)物理內(nèi)存地址區(qū)域和物理內(nèi)存大小來描述的。設(shè)備樹文件中一個(gè)典型的內(nèi)存區(qū)域信息描述如下所示:
memory00{
device_type="memory";
reg=〈0x0 0x0 0x2 0x0〉;
numa-node-id=〈0x0〉
};
memory01{
device_type="memory";
reg=〈0x80 0x0 0x2 0x0〉;
numa-node-id=〈0x0〉
};
memory02{
device_type="memory";
reg=〈0x100 0x0 0x2 0x0〉;
numa-node-id=〈0x0〉
};
memory03{
device_type="memory";
reg=〈0x180 0x0 0x2 0x0〉;
numa-node-id=〈0x0〉
};
此代碼段指定了一個(gè)NUMA結(jié)點(diǎn)中的4個(gè)內(nèi)存區(qū)域的起始地址、連續(xù)長(zhǎng)度和所屬的NUMA結(jié)點(diǎn)。內(nèi)核在讀取設(shè)備樹信息的同時(shí),會(huì)根據(jù)連續(xù)內(nèi)存區(qū)域的起始地址、大小以及相互之間的相交性進(jìn)行一定的調(diào)整和規(guī)劃,確保每個(gè)NUMA結(jié)點(diǎn)中的連續(xù)內(nèi)存區(qū)域按照起始地址從小到大的順序排列,確保彼此之間不存在相交的區(qū)域。
內(nèi)核對(duì)內(nèi)存的初始化過程是依據(jù)設(shè)備樹文件中對(duì)NUMA結(jié)點(diǎn)的劃分進(jìn)行的。而一個(gè)結(jié)點(diǎn)的內(nèi)存空間范圍,就是從所含的第一個(gè)內(nèi)存區(qū)域的起始地址開始,到最后一個(gè)內(nèi)存區(qū)域的結(jié)束地址結(jié)束(包括內(nèi)存區(qū)域之間存在的空洞)。同時(shí),如李慧娟等[4]所指出的,內(nèi)核對(duì)整個(gè)內(nèi)存空間按照功能又進(jìn)行了一次分區(qū),如圖1所示,內(nèi)核將8 192 GB內(nèi)存地址空間劃分為DMA區(qū)和NORMAL區(qū)。
Figure 1 Functional zones of memory space 圖1 內(nèi)存空間功能分區(qū)
此時(shí),以設(shè)備樹文件規(guī)劃的內(nèi)存布局為例的一個(gè)NUMA結(jié)點(diǎn)內(nèi)存空間布局的示意圖如圖2所示。
Figure 2 Layout of system memory space 圖2 系統(tǒng)內(nèi)存空間分布示意圖
內(nèi)核對(duì)NUMA結(jié)點(diǎn)內(nèi)存的初始化過程可以概括為:順序處理每個(gè)結(jié)點(diǎn),并為每個(gè)NUMA結(jié)點(diǎn)內(nèi)的物理內(nèi)存頁(yè)面建立內(nèi)核數(shù)據(jù)結(jié)構(gòu),完成內(nèi)存的初始化工作。
本文第2節(jié)揭示了操作系統(tǒng)內(nèi)核在初始化NUMA結(jié)點(diǎn)內(nèi)存,尤其是在虛擬仿真平臺(tái)上進(jìn)行驗(yàn)證時(shí)存在的問題,并提出可行的解決方案。第3節(jié)將給出該解決方案的算法描述,并輔以流程圖加以說明。 第4節(jié)則通過實(shí)驗(yàn)對(duì)所提出的解決方案進(jìn)行了驗(yàn)證。
高性能計(jì)算機(jī)系統(tǒng)通常需要大量物理內(nèi)存空間來支持高性能計(jì)算。為了滿足這種需求,并且兼顧未來繼續(xù)擴(kuò)充物理內(nèi)存的可能性,在采用上述“基于數(shù)據(jù)親和性”的NUMA架構(gòu)的處理器中,通常為每個(gè)CPU核或panel劃分巨大的“親和性”地址空間。
如本文所研究的CPU硬件設(shè)計(jì)[5],將整個(gè)CPU 64位地址空間劃分到多個(gè)本地目錄控制部件DCU(Directory Control Unit)上,每個(gè)DCU管理一段連續(xù)的CPU地址空間,并且將每4個(gè)CPU和2個(gè)DCU組成一個(gè)panel,通過一個(gè)訪存控制器MCU(Memory Control Unit)訪問存儲(chǔ)設(shè)備。而一個(gè)panel中所有DCU管理的地址空間就是這個(gè)panel的“親和性”地址空間,即構(gòu)成了panel中各個(gè)CPU所屬的NUMA結(jié)點(diǎn)內(nèi)存地址空間。這樣,在實(shí)際訪存時(shí)根據(jù)目標(biāo)地址的相關(guān)位域?qū)⒃L存的最終目的分配到各個(gè)DCU管理空間中。具體如何劃分CPU地址空間給各個(gè)DCU,則取決于不同的策略。如Diener等[6]提出的一種根據(jù)目標(biāo)地址劃分的常規(guī)策略,即依據(jù)訪存目標(biāo)虛擬地址的一些關(guān)鍵位域(如64位地址中的[42:39]位),將CPU地址空間劃分為相同大小的連續(xù)地址塊(512 GB),每個(gè)DCU管理一塊,然后將相鄰的幾個(gè)DCU組成一個(gè)panel,即構(gòu)成一個(gè)NUMA結(jié)點(diǎn)的內(nèi)存地址空間。
由于目前分配到NUMA結(jié)點(diǎn)的實(shí)際物理內(nèi)存容量不足以填滿整個(gè)NUMA結(jié)點(diǎn)中多個(gè)DCU管理的CPU地址空間,這種CPU空間劃分方式導(dǎo)致了在位于相同NUMA結(jié)點(diǎn)中、不同DCU管理空間的物理內(nèi)存設(shè)備在CPU地址空間中的范圍彼此之間不連續(xù)并且存在巨大空洞。例如,按上述DCU劃分以及panel組織方式,假設(shè)第1個(gè)16 GB的物理存儲(chǔ)設(shè)備位于NUMA結(jié)點(diǎn)0的第1個(gè)DCU管理內(nèi)存空間分區(qū)(512 GB)中,則在設(shè)備樹中配置其地址空間為[0x0,0x400000000),第2個(gè)16 GB存儲(chǔ)設(shè)備位于NUMA結(jié)點(diǎn)0的第2個(gè)DCU管理內(nèi)存空間分區(qū)(512 GB)中,則配置其地址空間為:[0x8000000000,0x8400000000)。這2個(gè)存儲(chǔ)設(shè)備的地址空間之間就出現(xiàn)了多達(dá)496 GB的地址空洞,即NUMA結(jié)點(diǎn)0中出現(xiàn)了496 GB的地址空洞。此外,文獻(xiàn)[7]也指出,由于物理實(shí)現(xiàn)上的原因,使用NUMA結(jié)構(gòu)的CPU體系在NUMA結(jié)點(diǎn)中通常存在內(nèi)存空洞。
上述NUMA結(jié)點(diǎn)中出現(xiàn)的巨型空洞,會(huì)導(dǎo)致現(xiàn)行Linux內(nèi)核在NUMA結(jié)點(diǎn)內(nèi)存初始化過程中花費(fèi)大量的時(shí)間,造成系統(tǒng)啟動(dòng)緩慢。這種現(xiàn)象在虛擬仿真平臺(tái)(如Vinay 等[8]使用的Synopsis公司的ZEBU仿真平臺(tái))上進(jìn)行芯片驗(yàn)證時(shí)帶來的負(fù)面影響更為嚴(yán)重。這是由于虛擬處理器芯片工作頻率(如1 MHz)比實(shí)際芯片的頻率(如1 GHz)低,因NUMA結(jié)點(diǎn)內(nèi)存空洞引起的啟動(dòng)時(shí)間過長(zhǎng)問題更加突出,給CPU的研發(fā)帶來巨大的時(shí)間損耗。
現(xiàn)行Linux內(nèi)核針對(duì)內(nèi)存連續(xù)性情況采取了3種不同的內(nèi)存管理模型,分別是平坦內(nèi)存模型(FLAT Memory Mode)、非連續(xù)內(nèi)存模型(Discontiguous Memory Mode)和稀疏內(nèi)存模型(SPARSE Memory Mode)。其中,平坦內(nèi)存模型通常用于UMA架構(gòu)的處理器,所有CPU共享一段連續(xù)的公共物理內(nèi)存空間。非連續(xù)內(nèi)存模型針對(duì)整個(gè)內(nèi)存地址空間中存在空洞,導(dǎo)致物理內(nèi)存呈現(xiàn)多個(gè)大段連續(xù)區(qū)域、區(qū)域之間不連續(xù)的情形,常見于一般性NUMA架構(gòu)的處理器內(nèi)存模型。稀疏性內(nèi)存模型則是針對(duì)熱插拔內(nèi)存(hotplug memory)或者內(nèi)存地址空間中有效物理內(nèi)存區(qū)域過于稀疏、大面積存在空洞的情況。
針對(duì)CPU研發(fā)驗(yàn)證過程中出現(xiàn)的NUMA結(jié)點(diǎn)內(nèi)存巨大空洞所造成的Linux內(nèi)核啟動(dòng)緩慢問題,本文首先采用了SPARSE內(nèi)存模型來試圖解決該問題。但是,經(jīng)過實(shí)驗(yàn)發(fā)現(xiàn),通過Linux內(nèi)核配置開啟SPARSE模型功能模塊,對(duì)于含有巨大內(nèi)存空洞的NUMA結(jié)點(diǎn)初始化并沒有優(yōu)化加速效果,在虛擬仿真平臺(tái)上Linux內(nèi)核啟動(dòng)仍然極為緩慢。
通過研究現(xiàn)行Linux內(nèi)核發(fā)現(xiàn),開啟SPARSE模型功能模塊后,在內(nèi)核初始化過程中僅會(huì)為實(shí)際物理內(nèi)存空間按1 GB大小建立映射表,便于后續(xù)初始化后內(nèi)核管理物理頁(yè)幀。而對(duì)于實(shí)際物理頁(yè)面的初始化仍然按照非連續(xù)內(nèi)存模型的情況進(jìn)行處理,即按照NUMA結(jié)點(diǎn)的順序,對(duì)每個(gè)NUMA結(jié)點(diǎn)內(nèi)的所有物理頁(yè)面(第一個(gè)有效物理內(nèi)存區(qū)域的起始地址,到最后一個(gè)有效物理內(nèi)存區(qū)域的結(jié)束地址之間)進(jìn)行遍歷式初始化。這個(gè)過程對(duì)有效物理頁(yè)面進(jìn)行初始化,建立相關(guān)的內(nèi)核數(shù)據(jù)結(jié)構(gòu),對(duì)于無效的內(nèi)存空洞則進(jìn)行識(shí)別并跳過。
內(nèi)核的非連續(xù)或稀疏型內(nèi)存模型在初始化過程中采取了“窮舉”遍歷式方法初始化每個(gè)NUMA結(jié)點(diǎn)的內(nèi)存,當(dāng)遇到含有巨大內(nèi)存空洞的NUMA結(jié)點(diǎn)時(shí),內(nèi)核在海量的空洞頁(yè)面上進(jìn)行了無意義的處理。即使這些“處理”只是識(shí)別后跳過,但因空洞頁(yè)面數(shù)量巨大,以上述496 GB大小的空洞為例,會(huì)有130 023 424個(gè)4 KB大小的物理頁(yè)面需要遍歷處理,帶來了巨大的時(shí)間損耗。
根據(jù)前述的研究可知,目前Linux內(nèi)核中非連續(xù)內(nèi)存模型以及稀疏內(nèi)存模型都無法解決NUMA結(jié)點(diǎn)內(nèi)存巨型空洞導(dǎo)致的NUMA結(jié)點(diǎn)內(nèi)存初始化緩慢問題,因此要解決該問題只能從Linux內(nèi)核的內(nèi)存初始化算法入手。Linux內(nèi)核是一個(gè)完整且復(fù)雜的源碼體系,一般的內(nèi)核開發(fā)是基于內(nèi)核提供的接口進(jìn)行驅(qū)動(dòng)開發(fā)、模塊開發(fā)等二次開發(fā),要實(shí)現(xiàn)NUMA結(jié)點(diǎn)初始化算法的優(yōu)化,就必須直接對(duì)內(nèi)核本身進(jìn)行修改,并且避免影響內(nèi)核的接口以及相關(guān)數(shù)據(jù)結(jié)構(gòu)。
本文提出了一種針對(duì)Linux內(nèi)核NUMA結(jié)點(diǎn)內(nèi)存初始化的改進(jìn)優(yōu)化算法。該算法基于常規(guī)的NUMA結(jié)點(diǎn)內(nèi)存初始化算法,在保證原有的初始化行為正常實(shí)施的情況下,分析識(shí)別并跳過內(nèi)存空洞,僅針對(duì)性地處理有效的內(nèi)存區(qū)域,從而避免了對(duì)空洞進(jìn)行無意義的識(shí)別和處理,最終節(jié)省了大量的初始化時(shí)間,加快了內(nèi)核的啟動(dòng)過程。
為了確保優(yōu)化算法對(duì)Linux內(nèi)核的影響最小,本文選擇直接在內(nèi)核源代碼的相關(guān)初始化函數(shù)中進(jìn)行函數(shù)邏輯和功能上的調(diào)整,來實(shí)現(xiàn)所需要的“空洞跳過”功能。
在現(xiàn)有Linux內(nèi)核中,NUMA結(jié)點(diǎn)內(nèi)存初始化過程發(fā)生在內(nèi)存區(qū)域記錄完畢之后。內(nèi)核遍歷所有NUMA結(jié)點(diǎn)、并按照內(nèi)核對(duì)內(nèi)存實(shí)地址空間的功能分區(qū)順序初始化每個(gè)結(jié)點(diǎn)。在處理每個(gè)結(jié)點(diǎn)內(nèi)存的過程中,將該結(jié)點(diǎn)內(nèi)存空間中與每個(gè)內(nèi)存功能分區(qū)相交的空間區(qū)域進(jìn)行遍歷初始化,即逐一初始化每個(gè)有效/空洞物理內(nèi)存頁(yè)。通過這個(gè)過程分析可以看到,現(xiàn)有內(nèi)核對(duì)結(jié)點(diǎn)內(nèi)存的初始化,實(shí)際上是對(duì)結(jié)點(diǎn)中所有有效物理內(nèi)存頁(yè)以及空洞所在內(nèi)存頁(yè)進(jìn)行逐一遍歷并進(jìn)行相關(guān)初始化工作。
本文對(duì)上述流程進(jìn)行優(yōu)化,避免內(nèi)核對(duì)NUMA結(jié)點(diǎn)內(nèi)存中的空洞做出無意義的識(shí)別和處理。優(yōu)化的原則是在不修改Linux內(nèi)核實(shí)質(zhì)性操作的基礎(chǔ)上,對(duì)結(jié)點(diǎn)內(nèi)存初始化過程加以優(yōu)化和提速。優(yōu)化算法的基本原理和依據(jù)如下所示:
(1)設(shè)備樹中規(guī)劃的每個(gè)內(nèi)存區(qū)域都是連續(xù)的,并且是一個(gè)左閉右開區(qū)間,描述的是一段有效物理內(nèi)存區(qū)域,并且注明了所屬的NUMA結(jié)點(diǎn)ID號(hào);
(2)經(jīng)過內(nèi)核讀取、處理后,不論是在整體上或是在所屬的NUMA結(jié)點(diǎn)中,保存在內(nèi)核中的各個(gè)內(nèi)存區(qū)域之間具有邏輯順序,即第i號(hào)內(nèi)存區(qū)域的起始地址必然小于第i+1號(hào)內(nèi)存區(qū)域起始地址,且第i號(hào)內(nèi)存區(qū)域的空間范圍必然與第i+1號(hào)內(nèi)存區(qū)域空間范圍不相交;
(3)依照上述內(nèi)存區(qū)域的排列順序,對(duì)每個(gè)結(jié)點(diǎn)內(nèi)的所有內(nèi)存區(qū)域進(jìn)行針對(duì)性處理,即可處理完結(jié)點(diǎn)中的所有有效物理內(nèi)存頁(yè)面。
根據(jù)上述原理和依據(jù),優(yōu)化算法流程圖如圖3所示。
Figure 3 Flow chart of improved algorithm 圖3 優(yōu)化算法流程圖
算法步驟如下所示:
(1)內(nèi)核讀取設(shè)備樹信息,并建立相關(guān)數(shù)據(jù)結(jié)構(gòu),包括NUMA結(jié)點(diǎn)、連續(xù)內(nèi)存區(qū)域等對(duì)象。
(2)內(nèi)核針對(duì)每個(gè)內(nèi)存結(jié)點(diǎn),對(duì)比其內(nèi)存空間范圍與內(nèi)存實(shí)地址空間內(nèi)所有功能分區(qū)的相交性,記錄所有產(chǎn)生的相交區(qū)域Zone,保存在內(nèi)核結(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)中。
(3)針對(duì)步驟(2)中記錄的、屬于該結(jié)點(diǎn)的每個(gè)相交區(qū)域(Zone)的內(nèi)存進(jìn)行有效化處理:
① 順序遍歷設(shè)備樹中記錄的、屬于該NUMA結(jié)點(diǎn)所有連續(xù)內(nèi)存區(qū)域;
② 對(duì)每個(gè)連續(xù)內(nèi)存區(qū)域求取與當(dāng)前處理的Zone的交集A;
③ 若A存在且不為空,則集合A所記錄的內(nèi)存空間都是有效物理內(nèi)存,直接進(jìn)行初始化處理。
(4)繼續(xù)處理后續(xù)結(jié)點(diǎn)。
這里以圖1和圖2所示的內(nèi)存空間為例說明上述算法流程。圖2中第0個(gè)NUMA結(jié)點(diǎn)與圖1所示的系統(tǒng)內(nèi)存空間功能分區(qū)相交,得到Zone DMA32和Zone Normal 2個(gè)相交區(qū)域。當(dāng)按上述算法步驟(2)初始化結(jié)點(diǎn)0時(shí),會(huì)先后處理這2個(gè)相交區(qū)域。當(dāng)按上述算法的步驟(3)處理相交區(qū)域Zone DMA32時(shí),只會(huì)找到連續(xù)內(nèi)存區(qū)域Memory00,并且只初始化Memory00的[0,0x1000 0000)范圍。然后按算法步驟(3)處理相交區(qū)域Zone Normal時(shí),則會(huì)先后找到連續(xù)內(nèi)存區(qū)域Memory00~Memory03,并逐個(gè)初始化它們位于相交區(qū)域Zone Normal中的物理頁(yè)面。
按照算法原理和流程圖,本文在Linux內(nèi)核NUMA結(jié)點(diǎn)內(nèi)存初始化等部分中實(shí)現(xiàn)了所提算法,其中算法核心部分如下所示:
void_meminit memmap_init_zone(unsigned longsize,intnid, unsigned longzone, unsigned longstart_pfn, enum memmap_contextcontext, struct vmem_altmap*altmap)
{
unsigned longend_pfn=start_pfn+size;
unsigned longregion_start,region_end;
unsigned longreal_start,real_end;
inti;
pg_data_t*pgdat=NODE_DATA(nid);
unsigned longpfn;
unsigned longnr_initialised=0;
struct page*page;
#ifdefCONFIG_HAVE_MEMBLOCK_NODE_MAP struct memblock_region*r=NULL,*tmp;
#endif
real_start=start_pfn,real_end=end_pfn;
if(highest_memmap_pfn highest_memmap_pfn=end_pfn-1; if(altmap&&start_pfn==altmap→base_pfn) start_pfn+=altmap→reserve; #ifdefCONFIG_SKIP_NUMA_HOLES for_each_mem_pfn_range(i,nid,®ion_start,®ion_end,NULL) { if(real_start==end_pfn) break; if(region_end<=real_start) continue; real_start=max(real_start,region_start); real_end=min(end_pfn,region_end); #else real_start=start_pfn; real_end=end_pfn; #endif for(pfn=real_start,pfn { ? } #ifdefCONFIG_SKIP_NUMA_HOLES real_start=real_end; } #endif } 為驗(yàn)證本文所提出的優(yōu)化算法,在如下環(huán)境中進(jìn)行實(shí)驗(yàn):將按上述解決方案修改好的內(nèi)核源代碼進(jìn)行編譯后,在ZEBU虛擬仿真平臺(tái)上搭建的16核CPU、主頻1 446 KHz的虛擬機(jī)器上運(yùn)行該內(nèi)核。通過修改設(shè)備樹文件,測(cè)試在不同內(nèi)存空間布局下對(duì)NUMA結(jié)點(diǎn)初始化的速度。通常情況下,操作系統(tǒng)是要初始化多個(gè)NUMA結(jié)點(diǎn)(以本實(shí)驗(yàn)為例,結(jié)點(diǎn)數(shù)目為1~8個(gè))的內(nèi)存,但實(shí)際上根據(jù)本文第2節(jié)描述的目標(biāo)CPU的特性,本實(shí)驗(yàn)每個(gè)NUMA結(jié)點(diǎn)的內(nèi)存大小、布局特性相同,結(jié)點(diǎn)內(nèi)部空洞也類似,因此,在實(shí)際的驗(yàn)證工作中針對(duì)一個(gè)NUMA結(jié)點(diǎn)內(nèi)存的初始化過程進(jìn)行測(cè)試對(duì)比,即可驗(yàn)證本文優(yōu)化算法對(duì)所有NUMA結(jié)點(diǎn)初始化效率的增益影響。 實(shí)驗(yàn)設(shè)置如下幾組內(nèi)存布局: (1)1個(gè)NUMA結(jié)點(diǎn),1個(gè)8 GB的連續(xù)內(nèi)存區(qū)域,無空洞; (2)1個(gè)NUMA結(jié)點(diǎn),2個(gè)8 GB連續(xù)內(nèi)存區(qū)域,如圖2中由Memory00+Memory01組成的內(nèi)存布局,存在504 GB大小的空洞; (3)1個(gè)NUMA結(jié)點(diǎn),3個(gè)8 GB連續(xù)內(nèi)存區(qū)域,如圖2中由Memory00+Memory01+Memory02組成的內(nèi)存布局,存在1 008 GB大小的空洞; (4)1個(gè)NUMA結(jié)點(diǎn),4個(gè)8 GB連續(xù)內(nèi)存區(qū)域,如圖2中由Memory00+Memory01+Memory02+Memory03組成的內(nèi)存布局,存在1 512 GB大小的空洞; (5)1個(gè)NUMA結(jié)點(diǎn),2個(gè)8 GB連續(xù)內(nèi)存區(qū)域,如圖2中由Memory00+Memory02組成的內(nèi)存布局,存在1 016 GB大小的空洞; (6)1個(gè)NUMA結(jié)點(diǎn),2個(gè)8 GB連續(xù)內(nèi)存區(qū)域,如圖2中由Memory00+Memory03組成的內(nèi)存布局,存在1 528 GB大小的空洞。 在上述實(shí)驗(yàn)組中,組(2)、組(5)和組(6)用于測(cè)試在相同有效內(nèi)存情況下,隨著空洞大小的增加,優(yōu)化算法和現(xiàn)有Linux內(nèi)核初始化算法的效率差異情況。組(3)和組(5)、組(4)和組(6)測(cè)試在內(nèi)存空洞基本相同的情況下,有效內(nèi)存的增加對(duì)優(yōu)化算法和現(xiàn)有Linux內(nèi)核初始化算法的耗時(shí)影響情況。實(shí)驗(yàn)結(jié)果如表1所示。 Table 1 Analysis of time of NUMA node initialization 表1 NUMA結(jié)點(diǎn)初始化用時(shí)分析 實(shí)驗(yàn)結(jié)果分析如下: (1)在相同有效內(nèi)存的情況下,隨著空洞的不斷增大,現(xiàn)有Linux內(nèi)核的初始化算法耗時(shí)顯著增加,而本文優(yōu)化算法對(duì)結(jié)點(diǎn)初始化的耗時(shí)則不受內(nèi)存空洞大小的影響; (2)在空洞大小基本相等的情況下,有效內(nèi)存的增加對(duì)現(xiàn)有Linux內(nèi)核初始化和本文優(yōu)化算法初始化的耗時(shí)影響基本相同,即本文優(yōu)化算法對(duì)于有效內(nèi)存的初始化效率與現(xiàn)有Linux內(nèi)核保持一致,不會(huì)對(duì)原有的初始化算法帶來負(fù)面影響。 本文討論了Linux內(nèi)核由于可能存在的物理內(nèi)存巨大空洞而導(dǎo)致的內(nèi)核啟動(dòng)緩慢問題。這種內(nèi)存空洞可能是由于硬件設(shè)計(jì)如CPU的“數(shù)據(jù)親和性”模型帶來的,也可能是由其他因素引起的。本文針對(duì)該問題提出了一種解決方案,該方案對(duì)現(xiàn)有Linux內(nèi)核中NUMA結(jié)點(diǎn)初始化算法進(jìn)行優(yōu)化,在不影響對(duì)有效物理內(nèi)存正確初始化的前提下,能夠有效識(shí)別并跳過內(nèi)存空間中的空洞,避免了對(duì)空洞內(nèi)物理頁(yè)面的無意義遍歷,實(shí)現(xiàn)了快速高效的結(jié)點(diǎn)初始化,加快了內(nèi)核啟動(dòng)過程,尤其是在此類CPU的仿真驗(yàn)證階段,可以帶來明顯的效率提升。 需要指出的是,文中所研究的系統(tǒng)物理內(nèi)存空洞是由于CPU基于數(shù)據(jù)親和性模型建立的NUMA體系結(jié)構(gòu)引起的,實(shí)際情況中可能存在因其他原因?qū)е碌奈锢韮?nèi)存空洞現(xiàn)象。但是,本文所提算法并不區(qū)分引起內(nèi)存空洞的原因,而是直接針對(duì)初始化過程中的內(nèi)存空洞這一現(xiàn)象進(jìn)行優(yōu)化。4 實(shí)驗(yàn)結(jié)果
5 結(jié)束語(yǔ)