成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux NUMA調優實戰:多線程程序加速方法

系統 Linux
今天,我們將深入 Linux NUMA 調優實戰領域,聚焦多線程程序加速方法。從底層原理剖析,到實用工具運用,再到具體優化策略實施,帶你逐步掌握在 NUMA 架構下釋放多線程程序性能的精髓,為開發高效能應用筑牢根基 。

在當今數據爆炸的時代,多線程程序已成為挖掘硬件潛力、加速應用運行的關鍵手段。對于運行在 Linux 系統中的多線程程序而言,非統一內存訪問(NUMA)架構既帶來了機遇,也提出了挑戰。NUMA 架構通過將內存劃分至不同節點,每個節點關聯特定處理器核心,實現本地內存快速訪問。這意味著在多線程程序運行時,若線程與內存訪問能精準匹配到同一節點,便能大幅提升效率。

然而,實際情況往往復雜得多,線程跨節點訪問內存的現象時有發生,從而引發性能瓶頸。今天,我們將深入 Linux NUMA 調優實戰領域,聚焦多線程程序加速方法。從底層原理剖析,到實用工具運用,再到具體優化策略實施,帶你逐步掌握在 NUMA 架構下釋放多線程程序性能的精髓,為開發高效能應用筑牢根基 。

Part1. NUMA 是什么?

NUMA(非統一內存訪問)是一種多處理器系統的內存架構,其中內存訪問時間取決于內存相對于處理器的位置。在 NUMA 系統中,處理器可以比訪問遠程內存更快地訪問本地內存。

在傳統的統一內存訪問(UMA,Uniform Memory Access)架構中,所有處理器通過共享的內存總線訪問同一塊物理內存,就好像所有的人都要通過同一個門進入一個大倉庫取東西 。這種架構下,處理器訪問內存的延遲是一致的,好處是內存訪問邏輯簡單,易于實現和管理,在處理器數量較少時表現良好。但隨著處理器數量的不斷增加,內存總線就成了性能瓶頸,就好比這個門太小,人多了就會擁堵,導致內存訪問延遲增加,內存帶寬不足,限制了系統整體性能的提升。

1.1 傳統SMP架構的問題

在早期的對稱多處理器(SMP)系統中:

  • 所有 CPU 通過共享總線訪問統一的內存池
  • 隨著 CPU 數量增加,總線成為瓶頸
  • 內存帶寬無法滿足多個 CPU 的需求

為了解決 UMA 架構的局限性,NUMA 架構應運而生。在 NUMA 架構中,系統被劃分為多個節點(Node),每個節點包含一個或多個處理器、本地內存以及 I/O 設備 。每個處理器可以訪問本地內存和其他節點的內存,但訪問本地內存的速度要比訪問其他節點(遠程)內存的速度快很多。

這就好比每個團隊都有自己獨立的小倉庫,團隊成員優先從自己團隊的小倉庫取東西,速度自然快,如果要去別的團隊倉庫取東西,就會花費更多時間。例如,在一個雙路服務器中,每個 CPU 及其對應的內存可以組成一個 NUMA 節點,當 CPU1 訪問自己節點的內存時,延遲較低;而當 CPU1 訪問 CPU2 節點的內存時,延遲就會明顯增加。

傳統 SMP 架構:
CPU1 ─┐
CPU2 ─┼─── 共享總線 ─── 內存
CPU3 ─┤
CPU4 ─┘

1.2 NUMA的解決方案

NUMA 通過將系統劃分為多個節點來解決這個問題:

  • 每個節點包含一組 CPU 和本地內存
  • 節點之間通過高速互連網絡連接
NUMA 架構:
節點0: CPU0,CPU1 ── 本地內存0
   │
   ├─── 互連網絡 ──——─┤
   │                 │
節點1: CPU2,CPU3 ── 本地內存1

1.3 為什么要進行 NUMA 性能調優?

在 NUMA 架構下,多線程程序的性能表現與內存訪問的局部性密切相關。如果多線程程序在運行時沒有充分考慮 NUMA 架構的特性,就可能出現大量的跨節點內存訪問,導致性能急劇下降。

假設你正在運行一個多線程的大數據分析程序,這個程序需要處理海量的數據。每個線程都要頻繁地讀寫內存中的數據,如果沒有進行 NUMA 性能調優,線程可能會隨機地訪問不同節點的內存。比如,一個線程原本在 Node1 上運行,卻頻繁地去訪問 Node2 上的內存數據,這就好比你在自己團隊的倉庫找不到東西,要頻繁地跑去別的團隊倉庫找,一來一回就浪費了很多時間。這種跨節點內存訪問會增加內存訪問延遲,降低內存帶寬的利用率,使得程序的執行速度大幅下降,原本可能幾小時就能完成的數據分析任務,現在可能需要花費數倍的時間。

再以數據庫服務器為例,數據庫服務器需要處理大量的并發查詢請求,每個查詢請求可能由一個線程來處理。如果線程沒有合理地分配到本地內存資源,不同線程對內存的訪問在各個節點上雜亂無章,就會導致大量的跨節點內存訪問。這不僅會增加內存訪問的延遲,還可能導致內存帶寬成為瓶頸,影響數據庫服務器的并發處理能力,使得數據庫的響應速度變慢,無法滿足大量用戶的快速查詢需求。

對于一些高性能計算場景,如天氣預報模型計算、基因測序數據分析等,這些任務通常需要進行大規模的并行計算,對內存訪問性能要求極高。如果多線程程序在 NUMA 架構下沒有進行優化,跨節點內存訪問帶來的性能損耗會嚴重制約計算效率,使得科研人員需要等待更長的時間才能得到計算結果,影響科研進展。

由此可見,進行 NUMA 性能調優對于多線程程序來說至關重要。通過優化,可以讓線程盡可能地訪問本地內存,減少跨節點內存訪問,充分利用 NUMA 架構的優勢,提高內存訪問效率,從而提升多線程程序的整體性能,使其能夠更快速、高效地完成任務,滿足不同應用場景對高性能計算的需求。

Part2. NUMA系統架構

2.1 內存管理的 “進化之路”

⑴SMP 架構的困境

在早期的計算機系統中,隨著應用對計算性能需求的不斷攀升,多處理器技術應運而生,其中對稱多處理(SMP)架構備受矚目。在 SMP 架構下,多個處理器平等地連接到同一條共享內存總線上,共享同一物理內存空間,就像一群小伙伴共同圍繞著一個公共的玩具箱,每個人都能平等地從中拿取玩具。這種架構的設計初衷是為了充分利用多個處理器的并行計算能力,通過操作系統的調度,讓不同的處理器協同處理各種任務,從而提升系統的整體性能。

然而,隨著處理器核心數量的持續增加,SMP 架構逐漸暴露出嚴重的性能瓶頸。想象一下,當眾多小伙伴同時沖向玩具箱想要取出自己心儀的玩具時,共享內存總線就如同那狹窄的玩具箱開口,成為了激烈競爭的焦點。多個處理器頻繁地同時訪問內存,導致總線爭用異常激烈,內存訪問延遲急劇上升。在高并發場景下,為了保證數據的一致性,處理器往往需要使用原子指令來訪問內存,例如通過鎖總線的方式獨占內存訪問權。這就好比小伙伴們在爭搶玩具時,有人直接把玩具箱的開口堵住,不讓其他人拿玩具,直到自己拿到為止,使得其他處理器只能干巴巴地等待,造成大量的處理器資源閑置浪費,系統整體性能大打折扣。

以一個典型的數據庫服務器為例,在處理大量并發事務時,多個處理器核心需要頻繁讀寫內存中的數據塊。由于 SMP 架構下內存總線的爭用,處理器常常需要等待很長時間才能獲取到所需的數據,導致事務處理的響應時間大幅增加,系統吞吐量急劇下降,無法滿足業務對高性能的要求。這種內存訪問瓶頸嚴重制約了 SMP 架構在大規模計算場景下的應用,迫切需要一種新的內存架構來打破這一困境。

⑵NUMA 架構應運而生

為了突破 SMP 架構在內存訪問方面的瓶頸,非統一內存訪問(NUMA)架構應運而生。它像是給計算機系統重新規劃了一個更合理的 “居住布局”,將整個系統劃分為多個節點(Node),每個節點都配備了自己的本地內存、處理器以及 I/O 設備,節點之間則通過高速互連網絡進行通信,就如同在一個大型社區里,劃分出了多個相對獨立的小區,每個小區都有自己的配套設施,小區之間有便捷的道路相連。

在 NUMA 架構中,處理器訪問本地內存的速度遠遠快于訪問其他節點的遠程內存,這是因為本地內存與處理器之間的物理距離更近,數據傳輸延遲更低,就像小區居民在自家樓下的小超市購物,方便快捷;而訪問其他節點的內存則像是要跑到隔壁小區的超市購物,需要經過一段路程,花費更多的時間。這種內存訪問的非一致性特性,使得 NUMA 架構能夠有效地減少內存總線的爭用,提高內存訪問的并行性,進而提升系統的整體性能。

與 SMP 架構相比,NUMA 架構最大的不同在于其內存訪問的非對稱性。SMP 架構下,所有處理器對內存的訪問延遲是一致的,就像所有居民到公共玩具箱的距離都一樣遠;而 NUMA 架構中,不同節點的內存訪問延遲存在差異,處理器會優先訪問本地內存,以獲取更快的數據讀寫速度。這種差異使得 NUMA 架構在處理大規模數據密集型應用時具有顯著優勢,能夠更好地適應現代計算機系統對高性能、高擴展性的需求。例如,在大規模科學計算、云計算數據中心等場景中,NUMA 架構能夠充分發揮各個節點的計算能力,高效地處理海量數據,為用戶提供快速、穩定的服務。

2.2 Linux 內核中的 NUMA 架構 “畫像”

圖片圖片

⑴節點的組織與表示

在 Linux 內核的世界里,對于 NUMA 架構的支持可謂是精心設計、精妙絕倫。每個 NUMA 節點在內核中是由結構體 pglist_data(在老版本內核中叫 pg_data_t,本質相同)來進行描述的,它就像是每個節點的 “管家”,掌管著節點內諸多關鍵信息。這個結構體包含了一個名為 node_zones 的數組,其類型為 struct zone,這便是內存區域的 “收納盒”,每個節點內不同特性的內存區域都被收納其中。

為了兼容不同硬件設備五花八門的特性以及應對 32 位、64 位系統各自的需求,Linux 內核將內存劃分成了不同的區域類型。常見的有 ZONE_DMA、ZONE_DMA32、ZONE_NORMAL 等。ZONE_DMA 區域,通常是低 16M 的內存范圍,它可是專為那些支持直接內存訪問(DMA)的設備量身定制的。因為有些老舊的 DMA 控制器,它們只能訪問這低 16M 的內存空間,所以內核特意劃分出這片區域,以確保這些設備能夠順暢地與內存交互,實現數據的高速傳輸,就好比為特殊需求的客人預留了特定的通道。

隨著硬件的發展,64 位系統登上舞臺,一些新的 DMA 設備能夠訪問更廣泛的內存空間,但又達不到完整的 4G 范圍,于是 ZONE_DMA32 應運而生,它主要服務于這些較新的、能訪問 4G 以內內存的 DMA 設備,為它們提供了專屬的 “棲息地”。

而 ZONE_NORMAL 區域,則涵蓋了 16M 到 896M(在 32 位系統且開啟物理地址擴展 PAE 的情況下)或者更大范圍(64 位系統)的內存,這片區域的內存可以直接映射到內核的虛擬地址空間,內核能夠直接、高效地對其進行訪問,就像是家里的 “常用物品存放區”,取用物品極為便捷,是內核日常運行時頻繁使用的內存 “主力軍”。

不同的內存區域有著不同的使命,它們緊密協作,與硬件設備默契配合,為整個系統的穩定高效運行奠定了堅實基礎。這種精細的內存區域劃分,充分展現了 Linux 內核設計的前瞻性與兼容性,使得 Linux 能夠在各種硬件平臺上縱橫馳騁,大放異彩。

⑵內存分配的 “策略藍圖”

當系統需要分配內存時,Linux 內核就像一位精明的調度大師,有著一套嚴謹且周全的策略。首先,它會依據預先計算好的節點距離信息,為內存分配指引方向。每個節點與其他節點之間的距離都被精準度量,這個距離可是影響內存分配優先級的關鍵因素。

以 ZONELIST_FALLBACK 策略為例,假設系統中有多個 NUMA 節點,節點 0 在分配內存時,會優先查看自身節點的內存情況。因為訪問自身節點的內存就如同在自家院子里取東西,速度最快,延遲最低。要是自身節點內存告急,無法滿足需求,內核就會按照節點距離由近及遠的順序,依次去相鄰節點 “借” 內存,比如先看向節點 1,再是節點 2、節點 3 等。這就好比先向隔壁鄰居求助,若鄰居也沒辦法,再往稍遠一點的人家打聽。

不過,也有些特殊場景,比如使用 __GFP_THISNODE 標志進行內存分配時,就遵循 ZONELIST_NOFALLBACK 策略,意味著內存分配只能在當前 NUMA 節點內進行,哪怕內存吃緊,也絕不 “外借”,有點像堅守自家資源,自力更生的意思。

確定好節點后,接下來就要挑選具體的內存區域了。這時候,node_zonelists 數組就派上了大用場。它就像是一張詳細的 “內存地圖”,指引著內核找到合適的內存區域。在 ZONELIST_FALLBACK 策略下,對于節點 0 的 node_zonelists[ZONELIST_FALLBACK],其內部的 zoneref 元素會按照節點距離排序,同時每個節點內的內存區域又依據優先級從高到低排列,通常是 ZONE_NORMAL 優先級較高,優先被考慮,其次是 ZONE_DMA32,最后是 ZONE_DMA。這是因為 ZONE_NORMAL 區域的內存使用最為頻繁、便捷,而 ZONE_DMA 區域相對較為特殊,只用于特定的 DMA 設備,不能輕易動用。

當進程申請內存時,內核會從這張 “地圖” 的起始位置開始查找,優先鎖定距離最近節點中的最高優先級內存區域。若該區域內存不足,才會按照既定順序,逐步往低優先級區域或者更遠節點的內存區域探索,直到找到滿足需求的內存為止。如此精細復雜的內存分配策略,確保了在 NUMA 架構下,系統能夠充分利用各個節點、各個區域的內存資源,達到性能的最優平衡,讓計算機系統在多任務、高負載的復雜環境下依然能夠穩健運行,高效處理各種數據與任務。

Part3. NUMA核心技術

NUMA(Non - Uniform Memory Access Architecture)即非統一內存訪問架構,是一種用于多處理器的電腦內存設計技術。其核心內容如下:

  • 內存和 CPU 分組:將 CPU 和內存劃分為多個節點(Node),每個節點包含若干 CPU 核心和本地內存。例如,雙路服務器通常包含 2 個 NUMA 節點。
  • 訪問速度差異:CPU 訪問本地節點的內存(本地內存)速度快,延遲通常約為 100ns。而訪問其他節點的內存(遠程內存)速度慢,需通過跨節點互聯,如 AMD 的 Infinity Fabric,延遲可達到 200 - 300ns,帶寬可能減半。

NUMA 技術的出現主要是為了解決傳統 UMA(Uniform Memory Access,統一內存訪問)架構中,隨著 CPU 核心數增加,內存總線爭用導致性能下降的問題。它通過將系統劃分為多個節點,每個節點獨立管理本地內存,減少了全局總線競爭,提升了系統的擴展性。

在實際應用中,可通過進程綁定(CPU Pinning)將進程限制在特定 NUMA 節點,強制使用本地內存;也可利用中斷親和性(IRQ Affinity)將網卡中斷分配到與進程相同的 NUMA 節點,減少跨節點通信。此外,多線程應用中,確保線程訪問的數據位于同一 NUMA 節點,實現數據結構本地化,也能優化性能

3.1 UMA技術

UMA是并行計算機中的共享存儲架構,即物理存儲器被所有處理機均勻共享,對所有存儲字具有相同的存取時間。每臺處理機可以有私用高速緩存,外圍設備也以一定形式共享。UMA技術適合于普通需求和多用戶共享時間的應用,在時序要求嚴格的應用中,被用作加速單一大型程序的執行率。

3.2 NUMA技術

NUMA是用于多進程計算中的存儲設計,存儲讀取取決于當前存儲器與處理器的關聯。在NUMA技術下,處理器訪問本地存儲器比非本地存儲器(另一個處理器的本地存儲器或者處理器共享的存儲器)更快。

3.4 vNUMA

vNUMA消除了VM和操作系統之間的透明性,并將NUMA架構直通到VM的操作系統。值得一提的是,vNUMA在業內與NUMA同樣盛名。對于一個廣泛VM技術,VM運行的底層架構,VM的NUMA拓撲跨越多個NUMA節點。在啟用了vNUMA的VM的初始功能之后,呈現給操作系統的架構是永久定義的,并且不能被修改。這個限制通常是正面的,因為改變vNUMA體系結構可能會導致操作系統的不穩定,但是如果VM通過vMotion遷移到帶有不同NUMA架構的管理程序,則可能導致性能問題。值得一提的是,盡管大多數應用程序都可以利用vNUMA,但大多數VM都足夠小,可以裝入NUMA節點;最近對寬-VM支持或vNUMA的優化并不影響它們。

因此,客戶操作系統或它的應用程序如何放置進程和內存會顯著影響性能。將NUMA拓撲暴露給VM的好處是,允許用戶根據底層NUMA架構做出最優決策。通過假設用戶操作系統將在暴露的vNUMA拓撲結構中做出最佳決策,而不是在NUMA客戶機之間插入內存。

3.5 NUMA的重要性

多線程應用程序需要訪問CPU核心的本地內存,當它必須使用遠程內存時,性能將會受到延遲的影響。訪問遠程內存要比本地內存慢得多。所以使用NUMA會提高性能。現代操作系統試圖在NUMA節點(本地內存+本地CPU=NUMA節點)上調度進程,進程將使用本地NUMA節點訪問核心。ESXi還使用NUMA技術為廣泛的虛擬機,當虛擬核心大于8時,將虛擬核心分布在多個NUMA節點上。當機器啟動時,虛擬核心將被分發到不同的NUMA節點,它將提高性能,因為虛擬核心將訪問本地內存。

Part4. 探尋NUMA節點

4.1 探測的 “魔法指令”

在 Linux 系統中,想要揭開 NUMA 節點的神秘面紗,查看其詳細信息,我們有一些非常實用的 “魔法指令”。就拿 numactl 來說,它堪稱是探索 NUMA 架構的得力助手。當我們在終端輸入 “numactl --hardware”,系統就如同一位貼心的導游,為我們展示出系統的 NUMA 拓撲全景圖。從這幅圖中,我們能清晰知曉系統里究竟有多少個 NUMA 節點,它們就像是分布在計算機世界里的不同 “領地”。

每個節點配備的 CPU 核心數量也一目了然,這些 CPU 核心可是節點的 “主力軍”,肩負著處理各種任務的重任。內存總量信息則讓我們對系統的存儲資源心中有數,清楚每個節點能容納多少數據 “寶藏”,以及當前還有多少可用內存,為資源分配提供關鍵參考。另外,節點之間的距離信息也十分關鍵,它直觀地反映了不同節點間內存訪問的 “路程遠近”,幫助我們理解數據傳輸的開銷成本。

舉個例子,在一臺配置了雙路處理器、擁有兩個 NUMA 節點的服務器上執行此命令,可能會得到類似這樣的結果:節點 0 擁有 8 個 CPU 核心,內存總量為 16GB,當前空閑內存 2GB,與節點 1 的距離為 20;節點 1 同樣有 8 個 CPU 核心,內存總量 16GB,空閑內存 3GB,節點間距離相互對稱。有了這些詳細信息,我們就能精準把握系統資源布局,為后續的應用部署、性能優化提供有力依據,讓系統運行更加高效流暢。

除了 numactl,在 /sys/devices/system/node 目錄下也隱藏著諸多關于 NUMA 節點的 “情報”。這里面的每個以 “node” 開頭的子目錄,都對應著一個具體的 NUMA 節點,仿佛是一個個裝滿信息的 “寶箱”。進入這些子目錄,查看諸如 “cpulist” 文件,就能知曉該節點所關聯的 CPU 核心列表,就像拿到了節點的 “兵力部署圖”;“meminfo” 文件則詳細記錄著內存的使用情況,包括已用內存、空閑內存等,是內存資源的 “賬本”。這些文件里的數據實時更新,時刻反映著系統運行過程中 NUMA 節點的動態變化,為系統管理員、開發者提供了一手的資源動態信息,便于及時調整策略,保障系統穩定高效運行。

4.2 代碼中的 “蛛絲馬跡”

倘若我們想要深入到 Linux 內核的底層,從代碼層面去理解 NUMA 節點探測的原理,那就得走進內核源碼的 “神秘世界”。以常見的 64 位多核操作系統為例,在 Linux 內核源碼里,有一系列關鍵的結構體和函數在默默運作。

首先是 numa_node_id() 函數,它就像是一個 “導航儀”,當進程在運行過程中需要獲取當前所處的 NUMA 節點編號時,只要調用這個函數,就能快速定位。它的實現原理涉及到對硬件寄存器、內存映射等底層機制的巧妙運用。在一些基于 Intel 架構的系統中,處理器會通過特定的寄存器來記錄當前訪問內存所對應的 NUMA 節點信息,numa_node_id() 函數則會讀取這個寄存器的值,經過簡單的轉換和校驗,將準確的節點編號返回給調用者,確保進程能精準知曉自己的 “歸屬地”。

再深入探究,struct pglist_data 結構體中的諸多成員變量,為我們全方位揭示了 NUMA 節點的詳細信息。node_id 成員明確標識了節點的唯一編號,如同每個人的身份證號,在整個系統中獨一無二;node_start_pfn 記錄著節點起始物理頁幀的編號,這是內存管理的重要基石,通過它可以快速定位節點內存的起始位置,為內存分配、回收等操作劃定邊界;node_spanned_pages 則精確統計了節點所跨越的物理頁幀數量,讓我們清楚了解每個節點的內存容量大小,以便合理規劃資源。

當系統啟動初始化階段,內核會逐個遍歷識別出的 NUMA 節點,就像一位嚴謹的普查員,對每個節點的硬件信息進行仔細登記。通過讀取主板 BIOS 提供的 ACPI(高級配置與電源接口)表,獲取節點的 CPU 拓撲結構、內存布局等關鍵信息,然后將這些信息填充到相應的結構體成員中,完成對 struct pglist_data 結構體的初始化。在后續的系統運行過程中,內核就依據這些初始化后的信息,有條不紊地進行內存管理、進程調度等一系列復雜而關鍵的任務,確保整個系統在 NUMA 架構下高效協同運行,為用戶提供流暢穩定的使用體驗。

①查看 NUMA 信息

# 查看 NUMA 拓撲
lscpu | grep NUMA
numactl --hardware
lstopo  # 需要安裝 hwloc

# 查看進程的 NUMA 使用情況
numastat
numastat -p <pid>

# 查看內存使用情況
cat /proc/meminfo
cat /proc/buddyinfo

②監控 NUMA 性能

# 查看 NUMA 命中率
numastat -c

# 使用 perf 監控 NUMA 事件
perf stat -e node-loads,node-load-misses ./program

③調試 NUMA 問題

# 查看進程的內存映射
cat /proc/<pid>/numa_maps

# 查看 NUMA 平衡統計
cat /proc/vmstat | grep numa

④性能調優

# 禁用自動 NUMA 平衡(可能提高性能)
echo 0 > /proc/sys/kernel/numa_balancing

# 調整 zone_reclaim_mode
echo 1 > /proc/sys/vm/zone_reclaim_mode

Part5. 實戰前的準備:工具與環境

在開始 NUMA 性能調優實戰之前,需要先準備好相關的工具,并確保運行環境支持 NUMA。下面介紹一些常用的工具及其安裝和基本使用方法。

5.1 numactl

numactl 是一個非常實用的命令行工具,用于在 NUMA 架構下控制進程和線程的內存分配與調度 。它可以幫助我們將進程綁定到特定的 NUMA 節點,指定內存分配策略等。

在 Debian/Ubuntu 系統上,可以使用以下命令安裝 numactl:

sudo apt - get install numactl

在 CentOS/RHEL 系統上,安裝命令如下:

sudo yum install numactl

安裝完成后,我們可以使用以下命令查看系統的 NUMA 架構信息:

sudo numactl --hardware

執行上述命令后,會輸出系統中每個 NUMA 節點的編號、CPU 列表、內存信息以及內存的距離等。例如:

available: 2 nodes (0 - 1)
node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
node 0 size: 131037 MB
node 0 free: 3019 MB
node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31
node 1 size: 131071 MB
node 1 free: 9799 MB
node distances:
node   0   1
  0:  10  20
  1:  20  10

如果我們希望將某個進程綁定到第 0 個 NUMA 節點上,可以使用如下命令:

sudo numactl --cpunodebind = 0 --membind = 0 your_command

其中,--cpunodebind = 0表示將進程分配到第 0 個 NUMA 節點上的 CPU 列表中,--membind = 0表示將進程分配到第 0 個 NUMA 節點上的內存,your_command是需要啟動的進程,比如一個可執行文件或一個命令行。

5.2 numastat

numastat用于監控和顯示系統的內存使用情況,特別是各個NUMA節點的內存分配和使用情況,它能幫助我們了解內存的使用分布,以便更好地進行性能優化 。

安裝 numastat 同樣可以使用包管理器,在 Debian/Ubuntu 系統上:

sudo apt - get install numactl

在 CentOS/RHEL 系統上:

sudo yum install numactl

安裝好后,直接運行numastat命令,就可以查看系統的內存使用信息:

numastat

輸出結果類似如下:

node0  node1
numa_hit   1775216830  6808979012
numa_miss  4091495     494235148
numa_foreign 494235148  4091495
interleave_hit 52909    53004
local_node   1775205816  6808927908
other_node   4102509    494286252

在這些輸出數據中,numa_hit表示命中的,即成功分配本地內存訪問的內存大小;numa_miss表示把內存訪問分配到另一個 node 節點的內存大小;numa_foreign表示另一個 Node 訪問本節點內存的大小;local_node表示本節點的進程成功在本節點上分配內存訪問的大小;other_node表示本節點的進程在其它節點上分配的內存訪問大小。通常,numa_miss和numa_foreign值越高,就越需要考慮進行 NUMA 綁定優化 。

5.3 perf

perf 是 Linux 內核自帶的性能分析工具,它基于事件采樣原理,能夠對處理器相關性能指標與操作系統相關性能指標進行剖析,可用于查找性能瓶頸和定位熱點代碼 。由于 perf 是內核自帶工具,大多數 Linux 系統無需額外安裝。

使用 perf 可以分析程序運行期間發生的硬件事件(如cpu - cycles、instructions 、cache - misses等)和軟件事件(如page - faults、context - switches等)。例如,要分析某個進程的 CPU 周期使用情況,可以使用以下命令:

sudo perf stat -p <pid> -e cpu - cycles

其中,-p <pid>指定要分析的進程 ID,-e cpu - cycles表示要統計的事件為 CPU 周期。執行后會輸出該進程在運行期間的 CPU 周期相關統計信息。

如果想要查看某個進程的熱點函數,使用perf top命令,它會實時顯示系統中占用 CPU 周期最多的函數:

sudo perf top -p <pid>

在輸出結果中,第一列是符號引發的性能事件的比例,指占用的 CPU 周期比例;第二列是符號所在的 DSO(Dynamic Shared Object),可以是應用程序、內核、動態鏈接庫、模塊;第三列是 DSO 的類型,[.]表示此符號屬于用戶態的 ELF 文件,[k]表示此符號屬于內核或模塊;第四列是符號名。

在進行 NUMA 性能調優實戰前,確保系統安裝并熟悉使用這些工具,將為后續的性能分析和優化工作提供有力支持。

Part6. 實戰開始:NUMA性能調優步驟

6.1 查看系統 NUMA 配置

在開始調優之前,首先要了解系統的 NUMA 配置情況。可以使用lscpu命令查看系統的CPU和NUMA節點信息 。執行lscpu命令后,會輸出一系列關于 CPU 和系統架構的詳細信息,其中與 NUMA 相關的部分如下:

NUMA node(s):         2
NUMA node0 CPU(s):    0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30
NUMA node1 CPU(s):    1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31

從這些輸出中,我們能得知系統中有 2 個 NUMA 節點,以及每個節點包含的 CPU 編號。

也可以使用numactl -H命令查看更詳細的 NUMA 架構信息,包括每個節點的 CPU 列表、內存大小、空閑內存以及節點之間的距離 :

available: 2 nodes (0 - 1)
node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23
node 0 size: 131037 MB
node 0 free: 3019 MB
node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31
node 1 size: 131071 MB
node 1 free: 9799 MB
node distances:
node   0   1
  0:  10  20
  1:  20  10

node distances表示節點之間的距離,距離值越大,說明節點間的訪問延遲越高。這里節點 0 訪問節點 1 的距離為 20,節點 1 訪問節點 0 的距離同樣為 20,而節點訪問自身的距離為 10,表明訪問本地節點的延遲更低。這些信息對于后續的性能調優至關重要,它讓我們清楚地了解系統的硬件布局,為合理分配資源提供了依據。

6.2 進程綁定到 NUMA 節點

將進程綁定到特定的 NUMA 節點是優化多線程程序性能的重要一步。這樣可以確保線程訪問的內存是本地內存,減少跨節點內存訪問。可以使用taskset和numactl命令來實現進程綁定 。

taskset命令用于設置或查看進程的 CPU 親和性,也可以用來將進程綁定到特定的 NUMA 節點 。例如,要將進程號為1234的進程綁定到 NUMA 節點 0 上,可以使用以下命令:

taskset -m 0 -p 1234

其中,-m選項表示指定 NUMA 節點,0表示 NUMA 節點 0,-p選項后面跟著要綁定的進程號。

numactl命令功能更強大,不僅可以綁定 CPU,還能指定內存綁定 。例如,要啟動一個新的進程并將其 CPU 和內存都綁定到 NUMA 節點 1,可以使用如下命令:

numactl --cpunodebind = 1 --membind = 1 your_command

--cpunodebind = 1表示將進程綁定到節點 1 的 CPU 上,--membind = 1表示將進程的內存分配綁定到節點 1 的內存上,your_command是要執行的命令或程序。比如我們要啟動一個test程序,并將其綁定到節點 1,命令如下:

numactl --cpunodebind = 1 --membind = 1 ./test

通過這樣的綁定操作,進程在運行時就會優先使用指定 NUMA 節點的 CPU 和內存資源,從而減少跨節點訪問帶來的性能損耗,提高程序的執行效率。

6.3 優化內存分配策略

內存分配策略對多線程程序在 NUMA 架構下的性能有著重要影響。合理調整內存分配策略,可以減少跨節點內存訪問,提高內存使用效率 。

Linux 系統提供了多種內存分配策略,其中常用的有首選本地節點(preferred)和交錯(interleaving)模式 。首選本地節點策略是指進程優先從本地 NUMA 節點分配內存,這樣可以充分利用本地內存訪問速度快的優勢 。可以通過修改/sys/kernel/mm/transparent_hugepage/enabled文件來設置內存分配策略為首選本地節點。打開該文件,將其內容修改為:

echo 'preferred' > /sys/kernel/mm/transparent_hugepage/enabled

交錯模式則是指進程在多個 NUMA 節點間交錯地分配內存,這種策略適用于內存訪問負載較為均衡,且需要充分利用多個節點內存資源的場景 。設置交錯模式的命令如下:

echo 'interleave' > /sys/kernel/mm/transparent_hugepage/enabled

也可以使用numactl命令在啟動進程時臨時設置內存分配策略 。例如,要以交錯模式啟動一個test程序,可以使用以下命令:

numactl --interleave=all ./test

interleave=all表示在所有 NUMA 節點間交錯分配內存。通過根據程序的內存訪問特點選擇合適的內存分配策略,可以有效提升程序在 NUMA 架構下的性能。

6.4 使用大頁(Huge Pages)

大頁是一種內存管理機制,它使用比普通內存頁更大的頁面來管理內存 。在 NUMA 系統中,使用大頁可以減少頁表項的數量,降低內存管理開銷,從而提高內存訪問效率,尤其對于內存訪問密集型的多線程程序,效果更為顯著 。

查看當前系統的大頁配置情況,可以使用如下命令:

cat /proc/meminfo | grep HugePages

執行該命令后,會輸出類似如下信息:

AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

從輸出中可以看到當前系統的大頁總數(HugePages_Total)、空閑大頁數(HugePages_Free)、已保留大頁數(HugePages_Rsvd)、超額大頁數(HugePages_Surp)以及大頁的大小(Hugepagesize)。

要分配大頁,可以通過修改/sys/kernel/mm/hugepages/hugepages-<size>/nr_hugepages文件來實現,其中<size>是大頁的大小,如2048kB 。例如,要分配 1024 個 2MB 的大頁,可以使用以下命令:

echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

使用大頁啟動應用程序時,可以結合numactl命令 。比如,要啟動一個test程序,并讓其使用大頁且將內存綁定到 NUMA 節點 0,可以使用如下命令:

numactl --membind=0 --huge ./test

--membind=0表示將內存綁定到節點 0,--huge表示使用大頁。通過合理配置和使用大頁,能夠有效提升多線程程序在 NUMA 架構下的內存訪問性能,進而提高程序的整體運行效率。

6.5 性能監控與效果評估

在完成 NUMA 性能調優后,需要對調優效果進行監控和評估,以確定是否達到了預期的性能提升。這就好比一場考試后,要通過檢查成績來判斷學習方法是否有效。

(1)監控工具的使用

①top 命令:top 命令是 Linux 系統中常用的實時性能監控工具,通過在終端輸入 “top” 即可啟動 。它能實時展示系統的關鍵性能指標,如 CPU 使用率、內存占用、負載平均值等,以及每個進程的詳細信息 。在多線程程序運行時,我們可以通過 top 命令查看進程的 CPU 使用率和內存占用情況。如果某個多線程進程的 CPU 使用率在調優后明顯降低,且內存占用也更加合理,這可能意味著調優起到了作用。比如,在調優前,一個多線程的數據處理程序的 CPU 使用率一直維持在 80% 以上,內存占用不斷攀升;調優后,CPU 使用率穩定在 50% 左右,內存占用也趨于穩定,這就是一個積極的信號。

②perf 工具:perf 是一個功能強大的性能分析工具,基于事件采樣原理,能對處理器和操作系統相關性能指標進行剖析,查找性能瓶頸和定位熱點代碼 。例如,使用 “perf stat -p -e cpu - cycles” 命令,可以分析指定進程的 CPU 周期使用情況 。在 NUMA 性能調優前后,對多線程程序執行此命令,對比調優前后的 CPU 周期數。如果調優后 CPU 周期數明顯減少,說明程序的執行效率得到了提高,可能是因為減少了跨節點內存訪問,降低了 CPU 等待內存數據的時間。使用 “perf top -p ” 命令可以實時顯示系統中占用 CPU 周期最多的函數,幫助我們找出性能熱點,以便針對性地進行優化。

③numastat 工具:numastat 用于監控和顯示系統的內存使用情況,特別是各個 NUMA 節點的內存分配和使用情況 。運行 “numastat” 命令,它會輸出各個 NUMA 節點的內存命中(numa_hit)、內存缺失(numa_miss)、跨節點訪問(numa_foreign)等信息 。在調優前,如果 numa_miss 和 numa_foreign 的值較高,說明存在大量的跨節點內存訪問。而在調優后,若這些值顯著降低,numa_hit 的值升高,就表明內存訪問的局部性得到了改善,多線程程序更多地訪問了本地內存,從而提高了性能。

(2)性能指標對比

①運行時間:在調優前后,多次運行多線程程序,記錄其運行時間 。可以使用 “time” 命令來測量程序的執行時間,例如 “time your_command” 。假設一個多線程的圖像渲染程序,調優前完成一次渲染需要 10 分鐘,調優后縮短到了 6 分鐘,這直觀地顯示了調優對程序運行效率的提升。

②吞吐量:對于一些數據處理或網絡服務類的多線程程序,吞吐量是一個重要的性能指標 。比如,一個多線程的網絡服務器,調優前每秒能處理 1000 個請求,調優后每秒能處理 1500 個請求,吞吐量的提升表明調優使得程序能夠更高效地處理任務,滿足更多的業務需求。

③CPU 使用率:通過 top 命令或其他性能監控工具獲取調優前后多線程程序的 CPU 使用率 。如果調優后 CPU 使用率降低,說明程序對 CPU 資源的利用更加高效,可能是因為減少了不必要的計算或等待時間,這在服務器環境中尤為重要,可以為其他任務釋放更多的 CPU 資源。

④內存訪問延遲:雖然沒有直接的工具可以精確測量內存訪問延遲,但可以通過 perf 工具結合其他指標來間接評估 。例如,觀察 cache - misses(緩存未命中)的情況,緩存未命中次數的減少通常意味著內存訪問延遲的降低。因為當內存訪問更傾向于本地內存時,數據更容易被緩存命中,從而減少了從內存中讀取數據的時間,提高了程序的整體性能。

通過上述性能監控工具和指標對比,我們可以全面、準確地評估 NUMA 性能調優對多線程程序的效果,驗證調優策略的有效性,為進一步的優化提供數據支持。

責任編輯:武曉燕 來源: 深度Linux
相關推薦

2012-01-10 14:35:08

JavaJVM

2009-11-05 10:03:25

Oracle調優NUMA架構

2025-05-27 08:20:00

Linux內核參數調優系統

2020-10-16 16:40:26

Linux高并發命令

2010-04-07 13:32:39

Oracle調優

2024-12-04 15:49:29

2015-07-06 10:14:25

Java垃圾回收實戰

2013-02-28 13:37:59

系統性能調優技術實戰

2013-03-18 15:35:30

2011-03-21 17:07:37

2025-06-26 02:15:00

2009-06-17 11:23:00

Java多線程

2023-11-23 09:26:50

Java調優

2010-09-26 13:48:51

JVM調優

2017-07-21 08:55:13

TomcatJVM容器

2009-07-29 16:42:35

Java多線程編程

2010-01-21 11:27:30

linux多線程機制線程同步

2022-02-28 10:11:22

查詢數據SQL

2011-03-31 13:40:34

2013-03-20 17:30:18

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91性高潮久久久久久久久 | 69久久久 | 91禁在线观看 | 日本丰满少妇裸体自慰 | 亚洲毛片av | 黄网站在线播放 | 国产欧美日韩在线观看 | 六月婷婷在线 | 成人在线观看网站 | 日本特黄特色aaa大片免费 | 91av免费在线观看 | 日日夜夜精品免费 | 免费黄网站 | 黄色成人免费网站 | 日韩激情一区二区 | 欧美日本在线 | 国产香蕉视频 | 可以免费看的av | 黄色成人在线观看 | 国产白丝精品91爽爽久久 | 五月激情综合网 | 久久精品视频网 | 日韩午夜片 | 日日操夜夜干 | 中文字幕国产在线 | 免费黄色一级视频 | 日韩免费看 | 日日干夜夜操 | 青草网 | 国产一区二区视频在线播放 | 久久最新网址 | 国产综合视频在线观看 | 欧美啪啪网 | 日本视频在线播放 | 国 产 黄 色 大 片 | 国产精品一区三区 | 国产精品自拍小视频 | 麻豆视频国产 | 日韩在线观看中文字幕 | 成年人在线观看 | 精品久久一区二区三区 |