關於CPU親和性的測試


今天看到運維的同事在配置nginx的CPU親和性時候,運維同事說他在所有的機器上都是按照8核的方式來配置worker進程的CPU親和性的。

但我覺得就是有點不太對勁,就查了一下nginx的處理worker_cpu_affinity的源代碼,發現nginx並不會在發現配置錯誤的時候拒絕啟動worker進程,而是僅僅打印一條錯誤日志“sched_setaffinity() failed”。

如果設置親和性失敗則按照SMP負載策略進行處理,linux的SMP負載均衡是基於進程數的,每個cpu都有一個可執行進程隊列,只有當其中一個cpu的可執行隊列里進程數比其他cpu隊列進程數多25%時,才會將進程移動到另外空閑cpu上,也就是說cpu0上的進程數應該是比其他cpu上多,但是會在25%以內,呈現的是一種梯形分布。

如果都使用8核的方式,那么配置在4核的機器上,就會有約一半進程是按照SMP方式分配CPU的;配置在16核機器上,就會有約一半的CPU核心空閑。

我是喜歡打破砂鍋問到底的,那么就順道寫了一些測試程序來研究一下Linux下的CPU親和性在不同設置的情況下是什么狀況。

測試前提:

系統是8個CPU邏輯核心(cpu0-cpu7)。

可以通過cat /proc/cpuinfo查看. 也可以使用 int num_procs = sysconf(_SC_NPROCESSORS_CONF); 獲取CPU邏輯核心的數量

#define _GNU_SOURCE #include <sched.h> #include <unistd.h> /* sysconf */ #include <stdlib.h> /* exit */ #include <stdio.h> //cat /proc/cpuinfo //gcc cpu_affinity_test.c -o cpu_affinity_test //ps -eo pid,args,psr | grep cpu_affinity_test int main(void) { cpu_set_t mask; CPU_ZERO(&mask); CPU_SET(7, &mask); pid_t cur_pid = getpid(); /* Set the CPU affinity for a pid */ if (sched_setaffinity(cur_pid, sizeof(cpu_set_t), &mask) == -1) { perror("sched_setaffinity"); //exit(EXIT_FAILURE); } while(1){ printf("hi\n"); usleep(1000); } return 0; } 

運行之后,

ps -eo pid,args,psr | grep cpu_affinity_test 查看該進程所占用的cpu,

可以看到這個程序一定是運行在cpu7上。

如果把 CPU_SET(7, &mask);

修改為 CPU_SET(8, &mask);

再編譯運行,則CPU親和性設置會失敗,系統會隨機給該進程分配一個cpu,但也會固定下來。

如果修改為 CPU_SET(6, &mask); CPU_SET(7, &mask);

再編譯運行,理論上會綁定兩個CPU,由於這個進程再每次打印之前會休息1秒,所以基本都是在占用cpu6, 如果再修改一下程序,把休息時間修改為1毫秒,則會發現該進程會交替使用cpu6和cpu7。

如果修改為 CPU_SET(6, &mask); CPU_SET(8, &mask);

再編譯運行,則cpu6被綁定成功,而cpu8是不存在的,所以該進程就只會在cpu6上運行。

備注: linux的SMP負載均衡是基於進程數的,每個cpu都有一個可執行進程隊列,只有當其中一個cpu的可執行隊列里進程數比其他cpu隊列進程數多25%時,才會將進程移動到另外空閑cpu上,也就是說cpu0上的進程數應該是比其他cpu上多,但是會在25%以內。它也自帶負載均衡策略,可以在運行時將某些進程從某一個cpu核心的進程隊列移到另外一個cpu核心的進程隊列。

https://my.oschina.net/xuhh/blog/755825


免責聲明!

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



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