CPU 計算平臺體系架構分爲 SMP 體系架構和 NUMA 體系架構等,下圖爲 SMP 體系架構:node
SMP(Sysmmetric Multi-Processor System,對稱多處理器系統),它由多個具備對稱關係的處理器組成。所謂對稱,即處理器之間是水平的鏡像關係,沒有主從之分。SMP 架構使得一臺計算機再也不由單個 CPU 組成。數據庫
SMP 的結構特徵是多處理器共享一個集中式存儲器,每一個處理器訪問存儲器的時間片一致,使工做負載可以均勻的分配到全部可用處理器上,極大地提升了整個系統的數據處理能力。可是,若是多個處理器同時請求訪問共享資源時,就會引起資源競爭,須要軟硬件實現加鎖機制來解決這個問題。因此,SMP 又稱爲 UMA(Uniform Memory Access,一致性存儲器訪問),其中,一致性指的是在任意時刻,多個處理器只能爲內存的每一個數據保存或共享一個惟一的數值。api
所以,這樣的架構設計沒法擁有良好的處理器數量擴展性,由於共享內存的資源競態老是存在的,處理器利用率最好的狀況只能停留在 2 到 4 顆。緩存
計算機系統中,處理器的處理速度要遠快於內存的讀寫速度,因此限制計算機計算性能的瓶頸在存儲器帶寬上。SMP 架構由於限制了處理器訪問存儲器的頻次,因此處理器可能會時刻對數據訪問感到飢餓。架構
NUMA(Non-Uniform Memory Access,非一致性存儲器訪問)架構優化了 SMP 架構擴展性差以及存儲器帶寬窄的問題。socket
從上圖能夠看出,NUMA 和 SMP 架構是相似的,一樣只會保存一份操做系統和數據庫的副本,表示 NUMA 架構中的處理器依舊可以訪問到整個存儲器。兩種主要的區別在於 NUMA 架構採用了分佈式存儲器,將處理器和存儲器劃分爲不一樣的節點(NUMA Node),每一個節點都包含了若干的處理器與內存資源。多節點的設計有效提升了存儲器的帶寬和處理器的擴展性。假設系統含有 4 個 NUMA 節點,那麼在理想狀況下系統的存儲器帶寬將會是 SMP 架構的 4 倍。分佈式
另外一方面,NUMA 節點的處理器能夠訪問到總體存儲器。按照節點內外,內存被分爲節點內部的本地內存以及節點外部的遠程內存。當處理器訪問本地內存時,走的是內部總線,當處理器訪問遠程內存時,走的是主板上的 QPI 互聯模塊。訪問前者的速度要遠快於後者,NUMA(非一致性存儲器訪問)所以而得名。
性能
Thread: 使用超線程技術虛擬出來的邏輯 Core,須要 CPU 支持。爲了便於區分,邏輯 Core 通常被寫做 Processor。在具備 Intel 超線程技術的處理器上,每一個內核能夠具備兩個邏輯處理器,這兩個邏輯處理器共享大多數內核資源(如內存緩存和功能單元)。此類邏輯處理器一般稱爲 Thread 。優化
上圖的 NUMA Topology 有 2 個 NUMA node,每一個 node 有 1 個 socket,即 pCPU, 每一個 pCPU 有 6 個 core,1 個 core 有 2 個 Processor,則共有邏輯 cpu processor 24 個。ui
在 LIUNX 命令行中執行 lscpu 便可看到機器的 NUMA 拓撲結構:
如上圖所示,機器有 2 個 node 分配到 2 個 socket 上,每一個 socket 有 14 個 core,每一個 core 有 2 個 processor, 則共有 56 個 cpu processor。同時,從上圖也可看出 NUMA node 0 上的 cpu 分佈爲 0-13,28-41,而 node 1 上的分佈爲 14-27, 42-55。
由上節分析知,NUMA node 處理器訪問本地內存的速度要快於訪問遠端內存的速度。訪問速度與 node 的距離有關係,node 間的距離稱爲 node distance,使用 numactl --hardware 能夠 show 出該距離:
node0 的本地內存大小爲 32209MB,Node1 的本地內存大小爲 32316MB。Node0 到本地內存的 distance 爲 10,到 node1 的內存 distance 距離爲 20。node1 到本地內存的 distance 爲10,到 node0 的內存distance距離爲20。
進一步對上面的 NUMA Topology 圖進行介紹。
Liunx 上使用 cat /proc/cpuinfo 命令 show 出 cpu 信息:
其中 physical id 表示 socket 號。當前的 cpu core 是第 14 個 ,siblings 爲 28 表示此 cpu14 在 core14 裏面的兄弟邏輯 cpu 爲 cpu28。CPU 14 和 CPU 28 共享 L1 Data cache、L1 instruction 和 L2 Cache 。
[***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index0/type Data [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index1/type Instruction [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index2/type Unified [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index0/size 32K [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index1/size 32K [***@controller-0 ~]$ cat /sys/devices/system/cpu/cpu14/cache/index2/size 256K
cpu 綁核策略
對 Libvirt 驅動而言,虛擬機的 vCPU 能夠綁定到主機的物理 CPU 上(pCPU)。這些配置能夠改善虛擬機實例的精確度與性能。
openstack flavor set FLAVOR-NAME \ --property hw:cpu_policy=CPU-POLICY \ --property hw:cpu_thread_policy=CPU-THREAD-POLICY
有效的CPU-POLICY值爲:
有效的 CPU-THREAD-POLICY 值爲:
NUMA拓撲
Libvirt 驅動程序能夠爲虛擬機 vCPU 定義放置的 NUMA 節點,或者定義虛擬機從哪一個 NUMA 節點分配 vCPU 與內存。
$ openstack flavor set FLAVOR-NAME \ --property hw:numa_nodes=FLAVOR-NODES \ --property hw:numa_cpus.N=FLAVOR-CORES \ --property hw:numa_mem.N=FLAVOR-MEMORY
舉例以下:
$ openstack flavor set aze-FLAVOR \ --property hw:numa_nodes=2 \ --property hw:numa_cpus.0=0,1 \ --property hw:numa_cpus.1=2,3 \ --property hw:numa_mem.0=2048 \ --property hw:numa_mem.1=2048 \
大頁內存分配
$ openstack flavor set FLAVOR-NAME \
--property hw:mem_page_size=PAGE_SIZE
有效的 PAGE_SIZE 值爲:
注意:大頁內存能夠分配給虛擬機內存,而不考慮 Guest OS 是否使用。若是 Guest OS 不使用大頁內存,則它值會識別小頁。反過來,若是 Guest OS 計劃使用大頁內存,則必定要給虛擬機分配大頁內存。不然虛擬機的性能將不及預期。
Nova 實現 NUMA 流程以下所示:
1. nova-api 對 flavor metadata 或 image property 中的 NUMA 配置信息進行解析,生成 Guest NUMA topology,保存爲 instance[‘numa_topology’]。
2. nova-scheduler 經過 NUMATopologyFilter 判斷 Host NUMA topology 是否可以知足 Guest NUMA topology,進行 ComputeNode 調度。
3. nova-compute 再次經過 instance_claim 檢查 Host NUMA 資源是否知足創建 Guest NUMA。
4. nova-compute 創建 Guest NUMA node 和 Host NUMA node 的映射關係,並根據映射關係調用 libvirt driver 生成 XML 文件。
5. Resource Tracker 會刷新 Host NUMA 資源的使用狀況。