這絕對是你的知識盲點,NUMA的為什麼存在

Silkage發表於2021-04-29

  NUMA的產生背景

  在NUMA架構出現前,CPU歡快的朝著頻率越來越高的方向發展(縱向發展)。受到物理極限的挑戰,又轉為核數越來越多的方向發展(橫向發展)。在一開始,記憶體控制器還在北橋中,所有CPU對記憶體的訪問都要透過北橋來完成。此時所有CPU訪問記憶體都是“一致的”,如下圖所示:

  這樣的架構稱為UMA(Uniform Memory Access),直譯為“統一記憶體訪問”,這樣的架構對軟體層面來說非常容易,匯流排模型保證所有的記憶體訪問是一致的,即每個處理器核心共享相同的記憶體地址空間。但隨著CPU核心數的增加,這樣的架構難免遇到問題,比如對匯流排的頻寬帶來挑戰、訪問同一塊記憶體的衝突問題。為了解決這些問題,有人搞出了NUMA。

  注意:北橋晶片(North Bridge)是主機板晶片組中起主導作用的最重要的組成部分,也稱為主橋(Host Bridge)。 一般來說, 晶片組的名稱就是以北橋晶片的名稱來命名的,例如:英特爾845E晶片組的北橋晶片是82845E,875P晶片組的北橋晶片是82875P等等。

  NUMA構架細節

  透過“NUMA的產生背景”,讓我們瞭解到了之前記憶體訪問架構原則,與此相對的就是NUMA,NUMA 全稱 Non-Uniform Memory Access,譯為“非一致性記憶體訪問”。這種構架下,不同的記憶體器件和CPU核心從屬不同的Node,每個 Node 都有自己的整合記憶體控制器(IMC,Integrated Memory Controller)。

  在 Node 內部,架構類似SMP,使用IMC Bus進行不同核心間的通訊;不同的 Node間透過QPI(Quick Path Interconnect)進行通訊,如下圖所示:

  一般來說,一個記憶體插槽對應一個Node。需要注意的一個特點是,QPI的延遲要高於IMC Bus,也就是說CPU訪問記憶體有了遠近(remote/local)之別,而且實驗分析來看,這個差別非常明顯。

  在Linux中,對於NUMA有以下幾個需要注意的地方:

  預設情況下,核心不會將記憶體頁面從一個 NUMA Node 遷移到另外一個 NUMA Node;

  但是有現成的工具可以實現將冷頁面遷移到遠端(Remote)的節點:NUMA Balancing;

  關於不同 NUMA Node 上記憶體頁面遷移的規則,社群中有依然有不少爭論。

  NUMA詳細分析

  非一致性記憶體架構(Non-uniform Memory Architecture)是為了解決傳統的對稱多處理(Symmetric Multi-processor)系統中的可擴充套件性問題而誕生的。在對稱多處理系統中,處理器共享北橋中的記憶體控制器來達到共同訪問外部記憶體和IO的目的,也就是說所有的處理器對記憶體和I/O的訪問方式和開銷都是相同的。在這種系統中,隨著更多的處理器被新增到SMP系統中,匯流排的競爭將會越來越大,系統的效能也必將隨之大打折扣。SMP系統的示意圖如下:

  本地節點: 對於某個節點中的所有CPU,此節點稱為本地節點;(速度最快)

  鄰居節點: 與本地節點相鄰的節點稱為鄰居節點;(速度次之)

  遠端節點: 非本地節點或鄰居節點的節點,稱為遠端節點。(速度最差)

  超立方體可以作為一種有效的拓撲來描述NUMA系統,它將系統中的節點數限制在2^C內,C是每個節點擁有的鄰居節點數,如下圖所示

  開銷總結

  以C=3為例,則對於節點1而言,2,3,5則為鄰居節點,4,6,7,8為遠端節點,顯然訪問開銷的關係為 本地節點<鄰居節點<遠端節點。

  NUMA案例分析

  AMD Hyper-Transport

  早期的SMP(對稱多處理器系統) 只擁有一個位於北橋中的記憶體控制器,而如今更先進的做法是將記憶體控制器整合到CPU中去,這樣每個CPU都擁有自己的記憶體控制器,不會相互之間產生競爭。

  最先採用這種做法的一批處理器就是AMD在2003年推出的AMD Opteron系列處理器,其結構如下圖所示:

  每個CPU中都整合了一個記憶體控制器(IMC),並且CPU之間採用了一種Hyper-Transport的技術建立連線,這種連線可以使得CPU透過其他CPU來訪問外部記憶體,當然訪問開銷要比訪問本地記憶體更大。

  作業系統的支援

  為了支援NUMA架構,OS的設計必須將記憶體分佈的特點考慮進去。

  舉一個簡單的例子,假如一個程式執行在一個給定的處理器中,那麼為這個程式所分配的實體記憶體就應該是該處理器的本地記憶體,而不是外部記憶體。

  OS還要注意避免將一個程式從一個節點給遷移到另一個節點。在一個普通的多處理系統中,OS就應該已經嘗試不去在處理器之間遷移程式,因為這意味著一個處理器的cache中的相關內容都將被丟失。如果在某種情況下必須進行遷移,那麼OS可以隨意選擇一個空閒的處理器。

  但是在NUMA系統中,可選擇的新處理器將要受到一些限制,最重要的一點就是新處理器訪問記憶體的開銷不能比先前的處理器大,也就是說應該儘可能選擇本地節點中的處理器。

  當找不到符合條件的處理器,OS才能選擇其他型別的處理器。

  在這種較糟的情況下有兩種選擇:

  如果程式只是暫時性的被遷移出去,可以再將其遷移回更加合適的處理器;

  如果不是暫時性的,那麼可以將該程式的記憶體複製到新處理器的記憶體中,這樣就可以透過訪問複製的記憶體來消除訪問外部記憶體的開銷,顯然這是一種空間換時間的做法。

  NUMA Node 操作

  NUMA Node 分配

  有兩個NUMA Node,每個節點管理16GB記憶體。

  NUMA Node 繫結

  Node 和 Node 之間進行通訊的代價是不等的,同樣是 Remote 節點,其代價可能不一樣,這個資訊在 node distances 中以一個矩陣的方式展現。

  我們可以將一個程式繫結在某個 CPU 或 NUMA Node 的記憶體上執行。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69999013/viewspace-2770468/,如需轉載,請註明出處,否則將追究法律責任。

相關文章