NUMA體系結構詳解


1. NUMA的幾個概念(Node,socket,core,thread)

   對於socket,core和thread會有不少文章介紹,這里簡單說一下,具體參見下圖:

    一句話總結:socket就是主板上的CPU插槽; Core就是socket里獨立的一組程序執行的硬件單元,比如寄存器,計算單元等; Thread:就是超線程hyperthread的概念,邏輯的執行單元,獨立的執行上下文,但是共享core內的寄存器和計算單元。

   NUMA體系結構中多了Node的概念,這個概念其實是用來解決core的分組的問題,具體參見下圖來理解(圖中的OS CPU可以理解thread,那么core就沒有在圖中畫出),從圖中可以看出每個Socket里有兩個node,共有4個socket,每個 socket 2個node,每個node中有8個thread,總共4(Socket)× 2(Node)× 8 (4core × 2 Thread) = 64個thread。

   另外每個node有自己的內部CPU,總線和內存,同時還可以訪問其他node內的內存,NUMA的最大的優勢就是可以方便的增加CPU的數量,因為 Node內有自己內部總線,所以增加CPU數量可以通過增加Node的數目來實現,如果單純的增加CPU的數量,會對總線造成很大的壓力,所以UMA結構 不可能支持很多的核。

                                  《此圖出自:NUMA Best Practices for Dell PowerEdge 12th Generation Servers》

    根據上面提到的,由於每個node內部有自己的CPU總線和內存,所以如果一個虛擬機的vCPU跨不同的Node的話,就會導致一個node中的CPU去 訪問另外一個node中的內存的情況,這就導致內存訪問延遲的增加。在有些特殊場景下,比如NFV環境中,對性能有比較高的要求,就非常需要同一個虛擬機 的vCPU盡量被分配到同一個Node中的pCPU上,所以在OpenStack的Kilo版本中增加了基於NUMA感知的虛擬機調度的特性。

2. 如何查看機器的NUMA拓撲結構

   比較常用的命令就是lscpu,具體輸出如下:

  1. dylan@hp3000:~$ lscpu 
  2. Architecture: x86_64
  3. CPU op-mode(s): 32-bit, 64-bit
  4. Byte Order: Little Endian
  5. CPU(s): 48 //共有48個邏輯CPU(threads)
  6. On-line CPU(s) list: 0-47
  7. Thread(s) per core: 2 //每個core有2個threads
  8. Core(s) per socket: 6 //每個socket有6個cores
  9. Socket(s): 4 //共有4個sockets
  10. NUMA node(s): 4 //共有4個NUMA nodes
  11. Vendor ID: GenuineIntel
  12. CPU family: 6
  13. Model: 45
  14. Stepping: 7
  15. CPU MHz: 1200.000
  16. BogoMIPS: 4790.83
  17. Virtualization: VT-x
  18. L1d cache: 32K //L1 data cache 32k
  19. L1i cache: 32K //L1 instruction cache 32k (牛x機器表現,馮諾依曼+哈弗體系結構)
  20. L2 cache: 256K
  21. L3 cache: 15360K
  22. NUMA node0 CPU(s): 0-5,24-29
  23. NUMA node1 CPU(s): 6-11,30-35
  24. NUMA node2 CPU(s): 12-17,36-41
  25. NUMA node3 CPU(s): 18-23,42-47

 

從上圖輸出,可以看出當前機器有4個sockets,每個 sockets包含1個numa node,每個numa node中有6個cores,每個cores包含2個thread,所以總的threads數 量=4(sockets)×1(node)×6(cores)×2(threads)=48.

另外,也可以通過下面的腳本來打印出當前機器的socket,core和thread的數量。

  1. #!/bin/bash
  2. # Simple print cpu topology
  3. # Author: kodango
  4. function get_nr_processor()
  5. {
  6.     grep '^processor' /proc/cpuinfo | wc -l
  7. }
  8. function get_nr_socket()
  9. {
  10.     grep 'physical id' /proc/cpuinfo | awk -F: '{
  11.             print $2 | "sort -un"}' | wc -l
  12. }
  13. function get_nr_siblings()
  14. {
  15.     grep 'siblings' /proc/cpuinfo | awk -F: '{
  16.             print $2 | "sort -un"}'
  17. }
  18. function get_nr_cores_of_socket()
  19. {
  20.     grep 'cpu cores' /proc/cpuinfo | awk -F: '{
  21.             print $2 | "sort -un"}'
  22. }
  23. echo '===== CPU Topology Table ====='
  24. echo
  25. echo '+--------------+---------+-----------+'
  26. echo '| Processor ID | Core ID | Socket ID |'
  27. echo '+--------------+---------+-----------+'
  28. while read line; do
  29.     if [ -z "$line" ]; then
  30.         printf '| %-12s | %-7s | %-9s |\n' $p_id $c_id $s_id
  31.         echo '+--------------+---------+-----------+'
  32.         continue
  33.     fi
  34.     if echo "$line" | grep -q "^processor"; then
  35.         p_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '` 
  36.     fi
  37.     if echo "$line" | grep -q "^core id"; then
  38.         c_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '` 
  39.     fi
  40.     if echo "$line" | grep -q "^physical id"; then
  41.         s_id=`echo "$line" | awk -F: '{print $2}' | tr -d ' '` 
  42.     fi
  43. done < /proc/cpuinfo
  44. echo
  45. awk -F: '{ 
  46.     if ($1 ~ /processor/) {
  47.         gsub(/ /,"",$2);
  48.         p_id=$2;
  49.     } else if ($1 ~ /physical id/){
  50.         gsub(/ /,"",$2);
  51.         s_id=$2;
  52.         arr[s_id]=arr[s_id] " " p_id
  53.     }
  54. END{
  55.     for (i in arr) 
  56.         printf "Socket %s:%s\n", i, arr[i];
  57. }' /proc/cpuinfo
  58. echo
  59. echo '===== CPU Info Summary ====='
  60. echo
  61. nr_processor=`get_nr_processor`
  62. echo "Logical processors: $nr_processor"
  63. nr_socket=`get_nr_socket`
  64. echo "Physical socket: $nr_socket"
  65. nr_siblings=`get_nr_siblings`
  66. echo "Siblings in one socket: $nr_siblings"
  67. nr_cores=`get_nr_cores_of_socket`
  68. echo "Cores in one socket: $nr_cores"
  69. let nr_cores*=nr_socket
  70. echo "Cores in total: $nr_cores"
  71. if [ "$nr_cores" = "$nr_processor" ]; then
  72.     echo "Hyper-Threading: off"
  73. else
  74.     echo "Hyper-Threading: on"
  75. fi
  76. echo
  77. echo '===== END ====='

———————————————————— 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM