天天看點

玩轉CPU Topology http://www.searchtb.com/2012/12/%E7%8E%A9%E8%BD%ACcpu-topology.html 先溫習幾個概念 檢視CPU Topology 使用CPU Topology Tips

http://www.searchtb.com/2012/12/%E7%8E%A9%E8%BD%ACcpu-topology.html

先溫習幾個概念

請原諒對部分術語筆者直接引用了wikipedia上的英文解釋,因為哥實在做不到比wikipedia上更準确描述。我會試着解釋部分的術語,并在本節的最後梳理一下這些術語之間的關系。注意,筆者對由于不準确的描述導緻的性能下降,程序crash等任何問題不承擔任何責任☺

NUMA:Non-Uniform Memory Access (NUMA) is a computer memory design used in multiprocessing, where the memory access time depends on the memory location relative to a processor. Under NUMA, a processor can access its own local memory faster than non-local memory, that is, memory local to another processor or memory shared between processors.NUMA architectures logically follow in scaling from symmetric multiprocessing (SMP) architectures.

提到NUMA就不能不對比SMP,

SMP:Symmetric multiprocessing (SMP) involves a multiprocessor computer hardware architecture where two or more identical processors are connected to a single shared main memory and are controlled by a single OS instance.

說了這麼多其實都是為了介紹NUMA Node:

A fairly technically correct and also fairly ugly definition of a node is: a region of memory in which every byte has the same distance from each CPU.

A more common definition is: a block of memory and the CPUs, I/O, etc. physically on the same bus as the memory.

CPU:這個不解釋,原因你懂得。

想當年CPU拼的是頻率,頻率越高越NB,但是提升頻率和制程密切相關。

玩轉CPU Topology http://www.searchtb.com/2012/12/%E7%8E%A9%E8%BD%ACcpu-topology.html 先溫習幾個概念 檢視CPU Topology 使用CPU Topology Tips

但是制程這玩意有一個實體天花闆,提升越來越難,有報道指出,現階段普遍應用的矽半導體在尺寸上有一個10nm的實體極限。為了提升性能cpu走上了多核的道路,即在一個封裝(socket或者processor)裡放多個core。這還不夠,又發明了超線程技術Hyper-threading

HT:HT Technology is used to improve parallelization of computations (doing multiple tasks at once) performed on PC microprocessors. For each processor core that is physically present, the operating system addresses two virtual or logical cores, and shares the workload between them when possible. They appear to the OS as two processors, thus the OS can schedule two processes at once. 一個core 在HT之後OS看到的就是2個Logical Processor。

下圖展示了這些術語之間的邏輯關系:

玩轉CPU Topology http://www.searchtb.com/2012/12/%E7%8E%A9%E8%BD%ACcpu-topology.html 先溫習幾個概念 檢視CPU Topology 使用CPU Topology Tips

一個NUMA node包括一個或者多個Socket,以及與之相連的local memory。一個多核的Socket有多個Core。如果CPU支援HT,OS還會把這個Core看成 2個Logical Processor。為了避免混淆,在下文中統一用socket指代Processor or Socket;為了偷懶,下文中用Processor指代Logical Processor,擊鍵能省則省不是。

檢視CPU Topology

本文以筆者能通路的某台Red Hat Enterprise Linux Server release 5.4為例介紹,其他系統請自行google。

NUMA Node

第一種方法使用numactl檢視

numactl –hardware

+ expand source

第二種方法是通過sysfs檢視,這種方式可以檢視到更多的資訊

ls /sys/devices/system/node/

1

node0  node1

//兩個目标表示本機有2個node,每個目錄内部有多個檔案和子目錄描述node内cpu,記憶體等資訊。比如說node0/meminfo描述了node0記憶體相關資訊。

Socket

可以直接通過/proc/cpuinfo檢視,cpuinfo裡的physical id描述的就是Socket的編号,

cat /proc/cpuinfo|grep “physical id”

+ expand source

由上可知本機有2個Socket,編号為0和1。

還可以簡單的使用如下指令直接檢視Socket個數

cat /proc/cpuinfo|grep “physical id”|sort -u|wc –l

1

2  

//本機有2個實體CPU封裝

Core

仍然是可以通過/proc/cpuinfo檢視,cpuinfo中跟core相關的資訊有2行。

cpu cores : 4 //一個socket有4個核,

core id : 1 //一個core在socket内的編号

通過如下指令可以直接檢視core的數量

cat /proc/cpuinfo |grep “cpu cores”|uniq|cut -d: -f2

1

//1個socket有4個core

本機有2個socket,每個有4個core,是以一共有8個core

還可以檢視core在Socket裡的編号

cat /proc/cpuinfo|grep “core id”|sort -u

1 2 3 4

core id         : 0

core id         : 1

core id         : 10

core id         : 9

一個socket裡面4個core的編号為0,1,9,10。是的,core id是不連續的。如果誰知道為啥麻煩通知我,先謝了。

Logical Processor

仍然是可以通過/proc/cpuinfo檢視在OS的眼裡有多少個Logical Processor

cat /proc/cpuinfo |grep processor|wc –l

1

Ok,8個core變成了16個Logical Processor,是以本機開啟了HT。

問題來了,cpuinfo裡面16個Processor編号為0-15,Core的id為0,1,9,10,Socket的id為0,1。這些編号是如何對應的呢?

我們檢視一個Processor完整的cpuinfo就比較清楚了,我剔除了不相關的行:

processor : 0 processor : 5

physical id : 0

siblings : 8

core id : 0

cpu cores : 4

physical id : 1

siblings : 8

core id : 1

cpu cores : 4

明白了?

Processor 0:在socket 0的core 0 裡。

Processor 5:在socket 1的core 1 裡。

Cache

仍然可以通過/proc/cpuinfo檢視,OMG, cpuinfo難道是萬能的?

1 2 3

processor       : 0

cache size      : 12288 KB

//cpu cache 大小

cache_alignment : 64 

問題又來了,我們知道CPU cache分為L1,L2,L3, L1一般還分為獨立的指令cache和資料cache。Cpuinfo裡這個cache size指的是?

好吧,cpuinfo也不是萬能的。詳細的cache資訊可以通過sysfs檢視

ls /sys/devices/system/cpu/cpu0/cache/

1

index0  index1  index2  index3

4個目錄

index0:1級資料cache

index1:1級指令cache

index2:2級cache

index3:3級cache ,對應cpuinfo裡的cache

目錄裡的檔案是cache資訊描述,以本機的cpu0/index0為例簡單解釋一下:

檔案 内容 說明
type Data 資料cache,如果檢視index1就是Instruction
Level 1 L1
Size 32K 大小為32K
coherency_line_size 64 64*4*128=32K
physical_line_partition 1
ways_of_associativity 4
number_of_sets 128
shared_cpu_map 00000101 表示這個cache被CPU0和CPU8 share

解釋一下shared_cpu_map内容的格式:

表面上看是2進制,其實是16進制表示,每個bit表示一個cpu,1個數字可以表示4個cpu

截取00000101的後4位,轉換為2進制表示

CPU id 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
0×0101的2進制表示 1 1

0101表示cpu8和cpu0,即cpu0的L1 data cache是和cpu8共享的。

驗證一下?

cat /sys/devices/system/cpu/cpu8/cache/index0/shared_cpu_map

00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000101

再看一下index3 shared_cpu_map的例子

cat /sys/devices/system/cpu/cpu0/cache/index3/shared_cpu_map

00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000f0f

CPU id 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
0x0f0f的2進制表示 1 1 1 1 1 1 1 1

cpu0,1,2,3和cpu8,9,10,11共享L3 cache

小結

綜合以上資訊可以繪制出以下的cpu topology圖:

玩轉CPU Topology http://www.searchtb.com/2012/12/%E7%8E%A9%E8%BD%ACcpu-topology.html 先溫習幾個概念 檢視CPU Topology 使用CPU Topology Tips

抱歉,圖比較大,網頁上看不清楚,下面放大單node圖,另一個node基本上可以類推。

玩轉CPU Topology http://www.searchtb.com/2012/12/%E7%8E%A9%E8%BD%ACcpu-topology.html 先溫習幾個概念 檢視CPU Topology 使用CPU Topology Tips

使用CPU Topology

好吧,現在我們知道了如何檢視CPU topology。那麼這與各位攻城獅的工作有什麼關系呢?

以淘寶搜尋常見的服務模型為例,服務端把離線處理的資料load到記憶體中,開始監聽某個服務端口,接收到用戶端請求後從線程池中配置設定一個工作線程,該線程解析請求,讀取記憶體中對應的資料,進行一些計算,然後把結果傳回給用戶端。

把這個過程簡化簡化再簡化,抽象抽象再抽象,可以得到一個簡單的測試程式,程式流程為:

1. 主線程申請2塊256M的記憶體,使用memset初始化這兩塊記憶體的每個byte

2. 啟動2個子線程,每個線程内循環16M次,在每次循環中随機讀取2塊記憶體中的各1K資料,對每個byte進行簡單加和,傳回。

3. 主線程等待子線程結束,列印每個線程的結果,結束。

使用-O2編譯出可執行檔案test,分别使用下面2個指令運作該程式。運作時間和機器配置以及目前load有關,絕對值沒有意義,這裡僅比較相對值。

指令 time ./test time numactl -m 0 –physcpubind=2,3 ./test
用時

real 0m38.678s

user 1m6.270s

sys 0m5.569s

real 0m28.410s

user 0m54.997s

sys 0m0.961s

發生了什麼?為什麼有這麼大的差異?

第一個指令直覺,那麼我們看一下第二個指令具體做了什麼:

numactl -m 0 –physcpubind=2,3 ./test

-m 0:在node 0上配置設定記憶體

–physcpubind=2,3:在cpu 2和3上運作程式,即一個線程運作在cpu2上,另一個運作在cpu3上。

參考上面的CPUtopology圖就很容易了解了,由于線程綁定cpu2和3執行,共享了L3 cache,且全部記憶體都是本node通路,運作效率自然比随機選擇cpu運作,運作中還有可能切換cpu,記憶體通路有可能跨node的第一種方式要快了。

接下來,讓我們看看完整的表格,讀者可以看看有沒有驚喜:

情況 指令 用時 解釋
完全由OS控制 time ./test

real 0m38.678s

user 1m6.270s

sys 0m5.569s

樂觀主義者,甩手掌櫃型
綁定跨node的Cpu執行 time numactl –physcpubind=2,6 ./test

real 0m38.657s

user 1m7.126s

sys 0m5.045s

Cpu 2和6不在同一個node,不能share L3 cache
綁定單node的Cpu執行 time numactl –physcpubind=2,3 ./test

real 0m28.605s

user 0m55.161s

sys 0m0.856s

Cpu 2和3在同一個node,share L3 cache。記憶體使用由OS控制,一般來說node 0和1記憶體都會使用。
跨node記憶體通路+綁定單node CPU執行 time numactl -m 1 –physcpubind=2,3 ./test

real 0m33.218s

user 1m4.494s

sys 0m0.911s

記憶體全使用node1,2個cpu在node0,記憶體通路比較吃虧
單node記憶體通路+綁定本node CPU執行 time numactl -m 0 –physcpubind=2,3 ./test

real 0m28.367s

user 0m55.062s

sys 0m0.825s

記憶體&cpu都使用node0
單node記憶體通路+綁定本node 單core執行 time numactl -m 0 –physcpubind=2,10 ./test

real 0m58.062s

user 1m55.520s

sys 0m0.270s

CPU2和10不但在同一個node,且在同一個core,本意是希望共享L1,L2cache,提升性能。但是不要忘了,CPU2和10是HT出來的logical Processor,在本例cpu密集型的線程中硬體争用嚴重,效率急劇下降。有沒有發現和上一個case的時間比率很有意思?

現在誰還能說了解點cpu topology沒用呢?☺

Tips

補充幾個小tips,友善有興趣的同學分析上面表格的各個case

1.檢視程序的記憶體numa node分布

簡單的說可以檢視程序的numa_maps檔案

cat /proc//numa_maps

檔案格式可以直接:man numa_maps

為了避免輸入數字pid,我使用如下指令檢視:

cat /proc/$(pidof test|cut –d” ” -f1)/numa_maps

2.檢視線程run在哪個processor

可以使用top指令檢視一個程序的各個線程分别run在哪個processor上

同樣,為了避免輸入數字pid,我使用如下指令啟動top:

top -p$(pidof test |sed -e ‘s/ /,/g’)

在預設配置下不顯示線程資訊,需要進入Top後按“shift+H”,打開線程顯示。

另外,如果沒有P列,還需要按“f”,按“j”,添加,這一列顯示的數字就是這個線程上次run的processor id。

關于top的使用,請讀者自行man top

3.另一種綁定cpu執行的方法

如果讀者的程式不涉及大量記憶體的通路,可以通過taskset綁定cpu執行。别怪我沒提醒你,仔細判斷是否應該綁定到同一個core的processor上哦。

關于指令的使用,請讀者自行Man taskset

繼續閱讀