天天看點

作業系統底層技術——CPU親和性

頭圖是加拿大lake simcoe自然風光,非常漂亮,基本沒有中國遊客,适合深度遊。

這是作業系統底層技術第二篇,前一篇是《Codegen技術學習》

CPU親和性

簡單地說,CPU親和性(affinity)就是程序要在某個給定的CPU上盡量長時間地運作而不被遷移到其他處理器的傾向性。

Linux核心程序排程器天生就具有被稱為軟CPU親和性(affinity)的特性,這意味着程序通常不會在處理器之間頻繁遷移。這種狀态正是我們希望的,因為程序遷移的頻率小就意味着産生的負載小。2.6版本的Linux核心還包含了一種機制,它讓開發人員可以程式設計實作硬CPU親和性(affinity)。這意味着應用程式可以顯式地指定程序在哪個(或哪些)處理器上運作。

原理

什麼是Linux核心硬親和性(affinity)?在Linux核心中,所有的程序都有一個相關的資料結構,稱為task_struct。這個結構非常重要,原因有很多;其中與親和性(affinity)相關度最高的是cpus_allowed位掩碼。這個位掩碼由n位組成,與系統中的n個邏輯處理器一一對應。具有4個實體CPU的系統可以有4位。如果這些CPU都啟用了超線程,那麼這個系統就有一個8位的位掩碼。如果為給定的程序設定了給定的位,那麼這個程序就可以在相關的CPU上運作。是以,如果一個程序可以在任何CPU上運作,并且能夠根據需要在處理器之間進行遷移,那麼位掩碼就全是1。實際上,這就是Linux中程序的預設狀态。

Linux核心API提供了一些方法,讓使用者可以修改位掩碼或檢視目前的位掩碼:

sched_set_affinity()(用來修改位掩碼)

sched_get_affinity()(用來檢視目前的位掩碼)

為什麼應該使用硬親和性(affinity)?通常Linux核心都可以很好地對程序進行排程,在應該運作的地方運作程序(這就是說,在可用的處理器上運作并獲得很好的整體性能)。核心包含了一些用來檢測CPU之間任務負載遷移的算法,可以啟用程序遷移來降低繁忙的處理器的壓力。

一般情況下,在應用程式中隻需使用預設的排程器行為。然而,您可能會希望修改這些預設行為以實作性能的優化。讓我們來看一下使用硬親和性(affinity)的2個原因。

原因1.充分利用cpu cache

如果一個給定的程序遷移到其他地方去了,那麼它就失去了利用CPU緩存的優勢。實際上,如果正在使用的CPU需要為自己緩存一些特殊的資料,那麼所有其他CPU都會使這些資料在自己的緩存中失效。

是以,如果有多個線程都需要相同的資料,那麼将這些線程綁定到一個特定的CPU上是非常有意義的,這樣就確定它們可以通路相同的緩存資料(或者至少可以提高緩存的命中率)。否則,這些線程可能會在不同的CPU上執行,這樣會頻繁地使其他緩存項失效。

原因2保障時間敏感的、決定性的程序的cpu利用

我們對CPU親和性(affinity)感興趣的最後一個原因是實時(對時間敏感的)程序。例如,您可能會希望使用硬親和性(affinity)來指定一個8路主機上的某個處理器,而同時允許其他7個處理器處理所有普通的系統排程。這種做法確定長時間運作、對時間敏感的應用程式可以得到運作,同時可以允許其他應用程式獨占其餘的計算資源。

應用場景

使用cpu親和技術會顯著提高cpu使用率,但是同時帶來的副作用是喪失程式的擴充性,應用程式需要單獨設定。這項技術在一些需要高性能,軟硬結合的場景下非常有效。

雲的核心技術就是虛拟化技術,首先是虛拟化技術,Cpu親和技術在雲上是以失效。