SMP (Symmetrical Multi-Processing):指在一個(gè)計(jì)算機(jī)上匯集了一組處理器(多CPU)蛉幸,各CPU之間共享內(nèi)存子系統(tǒng)以及總線結(jié)構(gòu)革半。SMP意為對(duì)稱多處理系統(tǒng),內(nèi)有許多緊耦合多處理器舶斧,這種系統(tǒng)的最大特點(diǎn)就是共享所有資源欣鳖。另外與之相對(duì)立的標(biāo)準(zhǔn)是MPP (Massively Parallel Processing),意為大規(guī)模并行處理系統(tǒng)茴厉,這樣的系統(tǒng)是由許多松耦合處理單元組成的泽台,要注意的是這里指的是處理單元而不是處理器。每個(gè)單元內(nèi)的CPU都有自己私有的資源矾缓,如總線怀酷、內(nèi)存、硬盤等嗜闻。在每個(gè)單元內(nèi)都有操作系統(tǒng)和管理數(shù)據(jù)庫(kù)的實(shí)例復(fù)本蜕依。這種結(jié)構(gòu)最大的特點(diǎn)在于不共享資源 [更多...]
CPU affinity:中文喚作“CPU親和力”,是指在CMP架構(gòu)下琉雳,能夠?qū)⒁粋€(gè)或多個(gè)進(jìn)程綁定到一個(gè)或多個(gè)處理器上運(yùn)行样眠。[更多...]
一、在Linux上修改進(jìn)程的“CPU親和力”
在Linux上翠肘,可以通過(guò) taskset 命令進(jìn)行修改檐束,安裝taskset工具。
# yum install util-linux-ng
對(duì)運(yùn)行中的進(jìn)程束倍,文檔上說(shuō)可以用下面的命令被丧,把CPU#1 #2 #3分配給PID為2345的進(jìn)程:
# taskset -cp 1,2,3 2345
但我嘗試沒(méi)奏效,于是我關(guān)掉了MySQL绪妹,并用taskset將它啟動(dòng):
# taskset -c 1,2,3 /etc/init.d/mysql start
對(duì)于其他進(jìn)程甥桂,也可如此處理(nginx除外,詳見(jiàn)下文)邮旷。之后用top查看CPU的使用情況黄选,原來(lái)空閑的#1 #2 #3,已經(jīng)在辛勤工作了婶肩。
二糕簿、配置nginx綁定CPU
剛才說(shuō)nginx除外,是因?yàn)閚ginx提供了更精確的控制狡孔。
在conf/nginx.conf中懂诗,有如下一行:
worker_processes? 1;
這是用來(lái)配置nginx啟動(dòng)幾個(gè)工作進(jìn)程的,默認(rèn)為1苗膝。而nginx還支持一個(gè)名為worker_cpu_affinity的配置項(xiàng)殃恒,也就是說(shuō),nginx可以為每個(gè)工作進(jìn)程綁定CPU辱揭。我做了如下配置:
worker_processes? 3;
worker_cpu_affinity 0010 0100 1000;
這里0001离唐、0010、0100问窃、1000是掩碼亥鬓,分別代表第1、2域庇、3嵌戈、4顆cpu核心覆积。
重啟nginx后,3個(gè)工作進(jìn)程就可以各自用各自的CPU了熟呛。
三宽档、刨根問(wèn)底
如果自己寫代碼,要把進(jìn)程綁定到CPU庵朝,該怎么做吗冤?可以用sched_setaffinity函數(shù)。在Linux上九府,這會(huì)觸發(fā)一次系統(tǒng)調(diào)用椎瘟。
如果父進(jìn)程設(shè)置了affinity,之后其創(chuàng)建的子進(jìn)程是否會(huì)有同樣的屬性侄旬?我發(fā)現(xiàn)子進(jìn)程確實(shí)繼承了父進(jìn)程的affinity屬性肺蔚。
四、Windows勾怒?
在Windows上修改“CPU親和力”婆排,可以通過(guò)任務(wù)管理器搞定。
* 個(gè)人感覺(jué)笔链,Windows系統(tǒng)中翻譯的“處理器關(guān)系”比“CPU親和力”容易理解點(diǎn)兒
—————–
進(jìn)行了這樣的修改后段只,即使系統(tǒng)負(fù)載達(dá)到3以上,不帶緩存打開(kāi)blogkid.net首頁(yè)(有40多次查詢)依然順暢鉴扫;以前一旦負(fù)載超過(guò)了1.5赞枕,響應(yīng)就很慢了。效果很明顯坪创。
linux taskset命令詳解
SYNOPSIS
? ? ? taskset [options] [mask | list ] [pid | command [arg]...]
OPTIONS
? ? ? -p, --pid
? ? ? ? ? ? ? operate on an existing PID and not launch a new task
? ? ? -c, --cpu-list
? ? ? ? ? ? ? specifiy? a? numerical? list of processors instead of a bitmask.
? ? ? ? ? ? ? The list may contain multiple items,? separated? by? comma,? and
? ? ? ? ? ? ? ranges.? For example, 0,5,7,9-11.
? ? ? -h, --help
? ? ? ? ? ? ? display usage information and exit
? ? ? -V, --version
? ? ? ? ? ? ? output version information and exit
# taskset -p -c 0 16380? 或者? taskset -cp 0 16380
# ps -e -o psr,pid,cmd |grep 29165? 查驗(yàn)?
psr : 進(jìn)程當(dāng)前被分配的處理器
---------------------------------------------------------------
使CPU隔離炕婶,專門用于某個(gè)服務(wù)或進(jìn)程:
為客戶提供一個(gè)有2個(gè)邏輯CPU計(jì)算能力的一個(gè)客戶機(jī)。要求CPU資源獨(dú)立被占用莱预,不受宿主機(jī)中其他客戶機(jī)的負(fù)載水平的影響柠掂。為了滿足這個(gè)需求,可以分為如下兩個(gè)步驟來(lái)實(shí)現(xiàn)依沮。
第一步涯贞,啟動(dòng)宿主機(jī)時(shí)隔離出兩個(gè)邏輯CPU專門供一個(gè)客戶機(jī)使用。在Linux內(nèi)核啟動(dòng)的命令行加上“isolcpus=”參數(shù)危喉,可以實(shí)現(xiàn)CPU的隔離宋渔,讓系統(tǒng)啟動(dòng)后普通進(jìn)程默認(rèn)都不會(huì)調(diào)度到被隔離的CPU上執(zhí)行。例如辜限,隔離了cpu2和cpu3的grub的配置文件如下:
title Red Hat Enterprise Linux Server (3.5.0)
root (hd0,0)
kernel /boot/vmlinuz-3.5.0 ro root=UUID=1a65b4bb-cd9b-4bbf-97ff-7e1f7698d3db isolcpus=2,3
initrd /boot/initramfs-3.5.0.img
系統(tǒng)啟動(dòng)后皇拣,在宿主機(jī)中檢查是否隔離成功,命令行如下:
[root@jay-linux ~]# ps -eLo psr | grep 0 | wc -l
106
[root@jay-linux ~]# ps -eLo psr | grep 1 | wc -l
107
[root@jay-linux ~]# ps -eLo psr | grep 2 | wc -l
4
[root@jay-linux ~]# ps -eLo psr | grep 3 | wc -l
4
[root@jay-linux ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | awk ‘{if($5==2) print $0}’
root? ? ? ? 10? ? 2? ? 10? 2 [migration/2]
root? ? ? ? 11? ? 2? ? 11? 2 [kworker/2:0]
root? ? ? ? 12? ? 2? ? 12? 2 [ksoftirqd/2]
root? ? ? 245? ? 2? 245? 2 [kworker/2:1]
[root@jay-linux ~]# ps –eLo ruser,pid,ppid,lwp,psr,args | awk ‘{if($5==3) print $0}’
root? ? ? ? 13? ? 2? ? 13? 3 [migration/3]
root? ? ? ? 14? ? 2? ? 14? 3 [kworker/3:0]
root? ? ? ? 15? ? 2? ? 15? 3 [ksoftirqd/3]
root? ? ? 246? ? 2? 246? 3 [kworker/3:1]
從上面的命令行輸出信息可知薄嫡,cpu0和cpu1上分別有106和107個(gè)線程在運(yùn)行氧急,而cpu2和cpu3上都分別只有4個(gè)線程在運(yùn)行颗胡。而且,根據(jù)輸出信息中cpu2和cpu3上運(yùn)行的線程信息(也包括進(jìn)程在內(nèi))态蒂,分別有migration進(jìn)程(用于進(jìn)程在不同CPU間遷移)杭措、兩個(gè)kworker進(jìn)程(用于處理workqueues)费什、ksoftirqd進(jìn)程(用于調(diào)度CPU軟中斷的進(jìn)程)钾恢,這些進(jìn)程都是內(nèi)核對(duì)各個(gè)CPU的一些守護(hù)進(jìn)程,而沒(méi)有其他的普通進(jìn)程在cup2和cpu3上運(yùn)行鸳址,說(shuō)明對(duì)其的隔離是生效的瘩蚪。
另外,簡(jiǎn)單解釋一下上面的一些命令行工具及其參數(shù)的意義稿黍。ps命令顯示當(dāng)前系統(tǒng)的進(jìn)程信息的狀態(tài)疹瘦,它的“-e”參數(shù)用于顯示所有的進(jìn)程,“-L”參數(shù)用于將線程(LWP巡球,light-weight process)也顯示出來(lái)言沐,“-o”參數(shù)表示以用戶自定義的格式輸出(其中“psr”這列表示當(dāng)前分配給進(jìn)程運(yùn)行的處理器編號(hào),“l(fā)wp”列表示線程的ID酣栈,“ruser”表示運(yùn)行進(jìn)程的用戶险胰,“pid”表示進(jìn)程的ID,“ppid”表示父進(jìn)程的ID矿筝,“args”表示運(yùn)行的命令及其參數(shù))起便。結(jié)合ps和awk工具的使用,是為了分別將在處理器cpu2和cpu3上運(yùn)行的進(jìn)程打印出來(lái)窖维。
第二步榆综,啟動(dòng)一個(gè)擁有2個(gè)vCPU的客戶機(jī)并將其vCPU綁定到宿主機(jī)中兩個(gè)CPU上。此操作過(guò)程的命令行如下:
#(啟動(dòng)一個(gè)客戶機(jī))
[root@jay-linux kvm_demo]# qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
VNC server running on ‘::1:5900’
#(查看代表vCPU的QEMU線程)
[root@jay-linux ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | grep qemu | grep -v grep
root? ? ? 3963? ? 1? 3963? 0 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
root? ? ? 3963? ? 1? 3967? 0 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
root? ? ? 3963? ? 1? 3968? 1 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 –daemonize
#(綁定代表整個(gè)客戶機(jī)的QEMU進(jìn)程铸史,使其運(yùn)行在cpu2上)
[root@jay-linux ~]# taskset -p 0×4 3963
pid 3963′s current affinity mask: 3
pid 3963′s new affinity mask: 4
#(綁定第一個(gè)vCPU的線程鼻疮,使其運(yùn)行在cpu2上)
[root@jay-linux ~]# taskset -p 0×4 3967
pid 3967′s current affinity mask: 3
pid 3967′s new affinity mask: 4
#(綁定第二個(gè)vCPU的線程,使其運(yùn)行在cpu3上)
[root@jay-linux ~]# taskset -p 0×8 3968
pid 3968′s current affinity mask: 4
pid 3968′s new affinity mask: 8
#(查看QEMU線程的綁定是否生效琳轿,如下的第5列為處理器親和性)
[root@jay-linux ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | grep qemu | grep -v grep
root? ? ? 3963? ? 1? 3963? 2 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
root? ? ? 3963? ? 1? 3967? 2 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
root? ? ? 3963? ? 1? 3968? 3 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 –daemonize
#(執(zhí)行vCPU的綁定后判沟,查看在cpu2上運(yùn)行的線程)
[root@jay-linux ~]# ps -eLo ruser,pid,ppid,lwp,psr,args | awk ‘{if($5==2) print $0}’
root? ? ? ? 10? ? 2? ? 10? 2 [migration/2]
root? ? ? ? 11? ? 2? ? 11? 2 [kworker/2:0]
root? ? ? ? 12? ? 2? ? 12? 2 [ksoftirqd/2]
root? ? ? 245? ? 2? 245? 2 [kworker/2:1]
root? ? ? 3963? ? 1? 3963? 2 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
root? ? ? 3963? ? 1? 3967? 2 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
#(執(zhí)行vCPU的綁定后,查看在cpu3上運(yùn)行的線程)
[root@jay-linux ~]# ps –eLo ruser,pid,ppid,lwp,psr,args | awk ‘{if($5==3) print $0}’
root? ? ? ? 13? ? 2? ? 13? 3 [migration/3]
root? ? ? ? 14? ? 2? ? 14? 3 [kworker/3:0]
root? ? ? ? 15? ? 2? ? 15? 3 [ksoftirqd/3]
root? ? ? 246? ? 2? 246? 3 [kworker/3:1]
root? ? ? 3963? ? 1? 3968? 3 qemu-system-x86_64 rhel6u3.img -smp 2 -m 512 -daemonize
由上面的命令行及其輸出信息可知利赋,CPU綁定之前水评,代表這個(gè)客戶機(jī)的QEMU進(jìn)程和代表各個(gè)vCPU的QEMU線程分別被調(diào)度到cpu0和cpu1上。使用taskset命令將QEMU進(jìn)程和第一個(gè)vCPU的線程綁定到cpu2媚送,將第二個(gè)vCPU線程綁定到cpu3上中燥。綁定之后,即可查看到綁定的結(jié)果是生效的塘偎,代表兩個(gè)vCPU的QEMU線程分別運(yùn)行在cpu2和cpu3上(即使再過(guò)一段時(shí)間后疗涉,它們也不會(huì)被調(diào)度到其他CPU上去)拿霉。
對(duì)taskset命令解釋一下,此處使用的語(yǔ)法是:taskset -p [mask] pid 咱扣。其中绽淘,mask是一個(gè)代表了處理器親和性的掩碼數(shù)字,轉(zhuǎn)化為二進(jìn)制表示后闹伪,它的值從最低位到最高位分別代表了第一個(gè)邏輯CPU到最后一個(gè)邏輯CPU沪铭,進(jìn)程調(diào)度器可能將該進(jìn)程調(diào)度到所有標(biāo)為“1”的位代表的CPU上去運(yùn)行。根據(jù)上面的輸出偏瓤,taskset運(yùn)行之前杀怠,QEMU線程的處理器親和性mask值是0×3(其二進(jìn)制值為:0011),可知其可能會(huì)被調(diào)度到cpu0和cpu1上運(yùn)行厅克;而運(yùn)行“taskset -p 0×4 3967”命令后赔退,提示新的mask值被設(shè)為0×4(其二進(jìn)制值為:0100),所以該進(jìn)程就只能被調(diào)度到cpu2上去運(yùn)行证舟,即通過(guò)taskset工具實(shí)現(xiàn)了vCPU進(jìn)程綁定到特定的CPU上硕旗。
上面命令行中,根據(jù)ps命令可以看到QEMU的線程和進(jìn)程的關(guān)系女责,但如何查看vCPU與QEMU線程之間的關(guān)系呢漆枚?可以切換(“Ctrl+Alt+2”快捷鍵)到QEMU monitor中進(jìn)行查看,運(yùn)行“info cpus”命令即可(還記得3.6節(jié)中運(yùn)行過(guò)的“info kvm”命令吧)鲤竹,其輸出結(jié)果如下:
(qemu) info cpus
* CPU #0: pc=0xffffffff810375ab thread_id=3967
CPU #1: pc=0xffffffff812b2594 thread_id=3968
從上面的輸出信息可知浪读,客戶機(jī)中的cpu0對(duì)應(yīng)的線程ID為3967,cpu1對(duì)應(yīng)的線程ID為3968辛藻。另外碘橘,“CPU #0”前面有一個(gè)星號(hào)(*),是標(biāo)識(shí)cpu0是BSP(Boot Strap Processor吱肌,系統(tǒng)最初啟動(dòng)時(shí)在SMP生效前使用的CPU)拘泞。
總的來(lái)說(shuō)得封,在KVM環(huán)境中,一般并不推薦手動(dòng)地人為設(shè)置QEMU進(jìn)程的處理器親和性來(lái)綁定vCPU,但是器仗,在非常了解系統(tǒng)硬件架構(gòu)的基礎(chǔ)上逢慌,根據(jù)實(shí)際應(yīng)用的需求泳姐,是可以將其綁定到特定的CPU上去從而提高客戶機(jī)中的CPU執(zhí)行效率或者實(shí)現(xiàn)CPU資源獨(dú)享的隔離性乍赫。
CPU中斷請(qǐng)求隔離方法:
應(yīng)該將中斷綁定至那些非隔離的CPU上,從而避免那些隔離的CPU處理中斷程序:
echo CPU_MASK > /proc/irq/ <irq number>/smp_affinity
[root@lopdb1 ~]# cat? /proc/irq/2/smp_affinity
7fffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff? ?
1. 不同的設(shè)備一般都有自己的IRQ號(hào)碼(當(dāng)然一個(gè)設(shè)備還有可能有多個(gè)IRQ號(hào)碼)
通過(guò)命令:cat /proc/interrupts查看
如:cat /proc/interrupts | grep -e “CPU\|eth4″
2. 中斷的smp affinity在cat? /proc/irq/$Num/smp_affinity
可以echo “$bitmask” > /proc/irq/$num/smp_affinity來(lái)改變它的值猛铅。
注意smp_affinity這個(gè)值是一個(gè)十六進(jìn)制的bitmask字支,它和cpu No.序列的“與”運(yùn)算結(jié)果就是將affinity設(shè)置在那個(gè)(那些)CPU了。(也即smp_affinity中被設(shè)置為1的位為CPU No.)
比如:我有8個(gè)邏輯core,那么CPU#的序列為11111111 (從右到左依次為#0~#7的CPU)
如果cat? /proc/irq/84/smp_affinity的值為:20(二進(jìn)制為:00100000)堕伪,則84這個(gè)IRQ的親和性為#5號(hào)CPU揖庄。
每個(gè)IRQ的默認(rèn)的smp affinity在這里:cat /proc/irq/default_smp_affinity
另外,cat? /proc/irq/$Num/smp_affinity_list 得到的即是CPU的一個(gè)List欠雌。
3. 默認(rèn)情況下蹄梢,有一個(gè)irqbalance在對(duì)IRQ進(jìn)行負(fù)載均衡,它是/etc/init.d/irqbalance
在某些特殊場(chǎng)景下富俄,可以根據(jù)需要停止這個(gè)daemon進(jìn)程禁炒。
4. 如果要想提高性能,將IRQ綁定到某個(gè)CPU蛙酪,那么最好在系統(tǒng)啟動(dòng)時(shí)齐苛,將那個(gè)CPU隔離起來(lái)翘盖,不被scheduler通常的調(diào)度桂塞。
可以通過(guò)在Linux kernel中加入啟動(dòng)參數(shù):isolcpus=cpu-list來(lái)將一些CPU隔離起來(lái)。
參考文檔:
https://www.kernel.org/doc/Documentation/IRQ-affinity.txt