設定 IO IRQ(Interrupt) 與 CPU
每個 I/O 會有各自的 IRQ (中斷) 透過設定我們可以將個別的 IRQ 指定給特定的 CPU 來處理 ,先檢查對應的 IRQ 檔案 /proc/interrupts (每個 IRQ 對應到每個 I/O 裝置)
# cat /proc/interrupts |grep -i eth 16: 35502 13732 IO-APIC-fasteoi vmwgfx, snd_ens1371, eth1 19: 20253 51673 IO-APIC-fasteoi eth0
第一個數字所代表的是 IRQ ,後面代表的是該 IRQ 使用 CPU0 與 CPU1 的累計次數.
可以看到 eth0 的 irq 是 19 所以我們可以指定他使用哪一個 CPU 核心來處理.接下來就是要如何指定,我們可以透過設定 /proc/irq/IRQ_NUMBER/smp_affinity ,檔案裡的參數可以用來指定 IRQ 中斷 與 CPU 的關聯 (一個或是多個 CPU 核心).
目前我的系統是 64 位元 雙核心,而 eth0 的 irq 是 19
# cat echo 1 > /proc/irq/19/smp_affinity 00000000,00000002
00000000,00000002 <- 這是??
這是 64 位元處理器的表示方式,00000000,00000002 是 16 位元進制 2(16 位元進制) -> 0010(2 位元進制) -> 2(10 位元進制)
0000 (2 位元進制)-> 0(16 位元進制)
0001 (2 位元進制)-> 1(16 位元進制)
0010 (2 位元進制)-> 2(16 位元進制)
0011 (2 位元進制)-> 3(16 位元進制)
0100 (2 位元進制)-> 4(16 位元進制)
0101 (2 位元進制)-> 5(16 位元進制)
0110 (2 位元進制)-> 6(16 位元進制)
0111 (2 位元進制)-> 7(16 位元進制)
1000 (2 位元進制)-> 8(16 位元進制)
1001 (2 位元進制)-> 9(16 位元進制)
1010 (2 位元進制)-> A(16 位元進制)
1011 (2 位元進制)-> B(16 位元進制)
1100 (2 位元進制)-> C(16 位元進制)
1101 (2 位元進制)-> D(16 位元進制)
1110 (2 位元進制)-> E(16 位元進制)
1111 (2 位元進制)-> F(16 位元進制)
00000000,00000002 <- 這是由第二顆核心來處理,00000000,00000001 <- 這是由第一顆核心來處理,如果要同是由兩個核心來處理可以下 00000000,00000003 …以此類推.
# echo 00000000,00000003 > /proc/irq/19/smp_affinity
也有些系統不是顯示這麼一長串的數字
# cat /proc/irq/32/smp_affinity f
smp_affinity f 表示 IRQ 可以接受所有系統上的 CPU 的服務,設定 為 1 則表示只有 CPU 0 可以服務此中斷 ,2 -> CPU 1 , 3 CPU 0 + CPU 1 .
# echo 1 > /proc/irq/32/smp_affinity # cat /proc/irq/32/smp_affinity 1
設定 process ID (PID) 與 CPU
前面的 smp_affinity 是透過 irq 來指定 CPU ,我們也是可以透過 taskset 工具指定 process ID (PID) 與 CPUs 的關係.
假如某一程式 my_embedded_process 要指定給 CPU 3 來處理 (需要用 16 位元進制來表示,CPU 0 -> 1 , CPU 1 -> 2 , CPU 2->4 , CPU 3->8 ).
# taskset 8 /usr/local/bin/my_embedded_process
如果是已經在執行的程式也是可以再指定的 ,只要使用參數 -p (–pid) 即可,假設 PID 是 7013 (可透過 #ps 查詢 PID)要將他指定給 CPU 0.
# taskset -p 1 7013
如果你的系統有 Non-Uniform Memory Access (NUMA) 功能也可以使用 #numactl 來指定 process ID (PID) 與 CPU ,關於 NUMA 請參考 https://benjr.tw/96788