樂觀鎖與悲觀鎖總結
1433
2025-03-31
OpenMP 和 NUMA架構
OpenMP是一個基于共享內存的并發編程模型。在程序中加入了OpenMP引導語后,主線程會生成一系列的子線程,并將任務劃分給子線程進行執行。這里需要強調的是,所有的線程在同一個地址空間內運行,每個線程有獨立的棧和程序計數器,但是所有線程共享進程的堆、數據段、代碼段等內存空間。
NUMA架構全稱non-uniform memory achitecture,是一種非對稱的內存訪問架構。簡單的說,不同的處理器訪問同一塊內存的時延不一樣,或者說同一個處理器訪問不同內存的時延不一樣。鯤鵬920就基于這樣的NUMA架構。在Linux命令行中執行numactl --hardware可以看到當前機器的NUMA拓撲結構:
[user@A191240619 temp]$ numactl --hardware available: 4 nodes (0-3) node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 node 0 size: 128124 MB node 0 free: 11256 MB node 1 cpus: 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 node 1 size: 129020 MB node 1 free: 2018 MB node 2 cpus: 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 node 2 size: 129020 MB node 2 free: 23937 MB node 3 cpus: 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 node 3 size: 129019 MB node 3 free: 18981 MB node distances: node 0 1 2 3 0: 10 16 32 33 1: 16 10 25 32 2: 32 25 10 16 3: 33 32 16 10
可以看到當前機器有4個NUMA節點,每個節點有128G內存和32個CPU,node distance代表了跨NUMA節點的訪存延遲。一個CPU訪問自己所在的NUMA節點延遲最小,訪問其他節點則存在2-3倍的訪存延遲。
這就帶來一個問題,在NUMA架構運行OpenMP程序時,如何將某個線程所需的數據盡可能放在自己所在的NUMA節點,避免跨節點的內存訪問?
數據初始化
以如下代碼為例:
int main() { double *A = new double[1000]; for (int i = 0; i < 1000; i++) A[i] = 0.0; #pragma omp for for (int i = 0; i < 1000; i++) A[i] = do_work(i, A); delete[] A; return 0; }
大部分的NUMA架構都是基于First touch的策略來分配內存,也就是內存會分配在第一次訪問此內存的核所在節點上。在以上例子中,數據初始化的部分并沒有加OpenMP的引導語,會由主線程單獨執行。所以所有的A數組都會被放在一個單獨的NUMA節點,而在后續并行計算部分,所有其他NUMA節點的線程訪問此數據都會產生較高延遲。
因此,較為理想的情況是,需要將數據初始化的部分也并行化,從而將A數組較為平均地分配到不同的NUMA節點,減少跨NUMA節點訪存延遲:
#pragma omp for for (int i = 0; i < 1000; i++) A[i] = 0.0;
線程綁核
同樣基于以上思想,執行線程的CPU應該和執行線程所以依賴的數據盡可能放在一個NUMA節點。主要有兩個環境變量決定線程在什么核上執行:
OMP_PLACES = [cores, threads, sockets] 決定線程在什么地方執行
OMP_PROC_BIND = [spread, close, master] 決定線程和OMP_PLACES如何映射
例如OMP_PLACES=cores決定每個線程綁核,OMP_PROC_BIND=close決定每個線程放在盡可能近得放在每個核上,例如主線程在CPU0上,則線程1放在CPU1上,線程2放在CPU2上…
以上調優思路適用于所有NUMA架構的OpenMP應用,但具體的參數選擇需要根據具體的應用靈活特征靈活調整。
任務調度 高性能計算
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。