CPU的親和性,進(jìn)程要在某個(gè)給定的 CPU 上盡量長(zhǎng)時(shí)間地運(yùn)行而不被遷移到其他處理器的傾向性,進(jìn)程遷移的頻率小就意味著產(chǎn)生的負(fù)載小。親和性一詞是從affinity翻譯來(lái)的,實(shí)際可以稱(chēng)為CPU綁定。
在多核運(yùn)行的機(jī)器上,每個(gè)CPU本身自己會(huì)有緩存,在緩存中存著進(jìn)程使用的數(shù)據(jù),而沒(méi)有綁定CPU的話(huà),進(jìn)程可能會(huì)被操作系統(tǒng)調(diào)度到其他CPU上,如此CPU cache(高速緩沖存儲(chǔ)器)命中率就低了,也就是說(shuō)調(diào)到的CPU緩存區(qū)沒(méi)有這類(lèi)數(shù)據(jù),要先把內(nèi)存或硬盤(pán)的數(shù)據(jù)載入緩存。而當(dāng)緩存區(qū)綁定CPU后,程序就會(huì)一直在指定的CPU執(zhí)行,不會(huì)被操作系統(tǒng)調(diào)度到其他CPU,性能上會(huì)有一定的提高。
另外一種使用CPU綁定考慮的是將關(guān)鍵的進(jìn)程隔離開(kāi),對(duì)于部分實(shí)時(shí)進(jìn)程調(diào)度優(yōu)先級(jí)提高,可以將其綁定到一個(gè)指定CPU核上,可以保證實(shí)時(shí)進(jìn)程的調(diào)度,也可以避免其他CPU上進(jìn)程被該實(shí)時(shí)進(jìn)程干擾。
我們可以手動(dòng)地為其分配CPU核,而不會(huì)過(guò)多的占用同一個(gè)CPU,所以設(shè)置CPU親和性可以使某些程序提高性能。
Linux操作系統(tǒng)的CPU親和性特征
—————————————
操作系統(tǒng)部分Linux的調(diào)度程序同時(shí)提供”軟CPU親和性”和”硬CPU親和性”。
● 軟親和性
進(jìn)程要在指定的 CPU 上盡量長(zhǎng)時(shí)間地運(yùn)行而不被遷移到其他CPU。Linux 內(nèi)核進(jìn)程調(diào)度器天生就具有被稱(chēng)為軟CPU親和性(Affinity)的特性,因此Linux通過(guò)這種軟的親和性試圖使某進(jìn)程盡可能在同一個(gè)CPU上運(yùn)行。
● 硬親和性
進(jìn)程或者線程綁定到某一個(gè)指定的cpu核運(yùn)行,雖然Linux盡力通過(guò)一種軟的親和性試圖使進(jìn)程盡量在同一個(gè)處理器上運(yùn)行,但它也允許用戶(hù)強(qiáng)制指定進(jìn)程無(wú)論如何都必須在指定的處理器上運(yùn)行。
硬性親和性使用場(chǎng)景
硬親和性場(chǎng)景一般發(fā)生在需要保持高CPU緩存命中率時(shí)和需要測(cè)試復(fù)雜的應(yīng)用程序時(shí)。
● 保持高CPU緩存命中率
如果一個(gè)給定的進(jìn)程遷移到其他地方去了,那么它就失去了利用 CPU 緩存的優(yōu)勢(shì)。實(shí)際上,如果正在使用的 CPU 需要為自己緩存一些特殊的數(shù)據(jù),那么所有其他 CPU 都會(huì)使這些數(shù)據(jù)在自己的緩存中失效。因此,如果有多個(gè)線程都需要相同的數(shù)據(jù),那么將這些線程綁定到一個(gè)特定的 CPU 上是非常有意義的,這樣就確保它們可以訪問(wèn)相同的緩存數(shù)據(jù)(或者至少可以提高緩存的命中率)。否則,這些線程可能會(huì)在不同的 CPU 上執(zhí)行,這樣會(huì)頻繁地使其他緩存項(xiàng)失效。
● 測(cè)試復(fù)雜的應(yīng)用程序
考慮一個(gè)需要進(jìn)行線性可伸縮性測(cè)試的應(yīng)用程序。有些產(chǎn)品聲明可以在使用更多硬件時(shí)執(zhí)行得更好。我們不用購(gòu)買(mǎi)多臺(tái)機(jī)器(為每種處理器配置都購(gòu)買(mǎi)一臺(tái)機(jī)器),而是可以采取以下方式:
1.購(gòu)買(mǎi)一臺(tái)多處理器的機(jī)器;
2.不斷增加分配的處理器;
3.測(cè)量每秒的事務(wù)數(shù);
4.評(píng)估結(jié)果的可伸縮性。
在Linux操作系統(tǒng)中修改CPU親和性的手段
—————————————————
在Linux內(nèi)核中,所有的進(jìn)程都有一個(gè)相關(guān)的數(shù)據(jù)結(jié)構(gòu),稱(chēng)為task_struct。這個(gè)結(jié)構(gòu)非常重要,其中與親和性(affinity)相關(guān)度最高的是cpus_allowed 位掩碼。這個(gè)位掩碼由n位組成,與系統(tǒng)中的n個(gè)邏輯處理器對(duì)應(yīng)。具有4個(gè)物理CPU的系統(tǒng)可以有4 位。如果這些CPU都啟用了超線程,那么這個(gè)系統(tǒng)就有8個(gè)位掩碼。 如果為給定的進(jìn)程設(shè)置了給定的位,那么這個(gè)進(jìn)程就可以在相關(guān)的 CPU 上運(yùn)行。因此,如果一個(gè)進(jìn)程可以在任何 CPU 上運(yùn)行,并且能夠根據(jù)需要在處理器之間進(jìn)行遷移,那么位掩碼就全是1。這是 Linux 中進(jìn)程的預(yù)設(shè)狀態(tài)。
Linux 內(nèi)核 API 提供了一些方法,讓用戶(hù)可以修改位掩碼或查看當(dāng)前的位掩碼,控制和綁定進(jìn)程在特定的CPU:
sched_set_affinity()(用來(lái)修改位掩碼)
sched_get_affinity()(用來(lái)查看當(dāng)前的位掩碼)
cpus_allowed(用于控制進(jìn)程可以在哪里處理器上運(yùn)行)
sched_setaffinity(用于某個(gè)進(jìn)程綁定到一個(gè)特定的CPU)
小知識(shí)
——
● 物理CPU
機(jī)器上實(shí)際安裝的CPU個(gè)數(shù),比如說(shuō)你的主板上安裝了一塊8核CPU,那么物理CPU個(gè)數(shù)就是1個(gè),所以物理CPU個(gè)數(shù)就是主板上安裝的CPU個(gè)數(shù)。
● 邏輯CPU
一般情況,我們認(rèn)為一顆CPU可以有多個(gè)核,加上Intel的超線程技術(shù)(HT), 可以在邏輯上再分一倍數(shù)量的CPU core出來(lái)。
● 超線程技術(shù)(Hyper-Threading)
就是利用特殊的硬件指令,把單個(gè)物理CPU模擬成兩個(gè)CPU(邏輯CPU),實(shí)現(xiàn)多線程。我們常聽(tīng)到的雙核四線程/四核八線程指的就是支持超線程技術(shù)的CPU。