如何指定進程運行的CPU


coolshell最新的文章《性能調優攻略》在“多核CPU調優”章節,提到“我們不能任由操作系統負載均衡,因為我們自己更了解自己的程序,所以,我們可以手動地為其分配CPU核,而不會過多地占用CPU0,或是讓我們關鍵進程和一堆別的進程擠在一起。”。在文章中提到了Linux下的一個工具,taskset,可以設定單個進程運行的CPU。

同時,因為最近在看redis的相關資料,redis作為單進程模型的程序,為了充分利用多核CPU,常常在一台server上會啟動多個實例。而為了減少切換的開銷,有必要為每個實例指定其所運行的CPU。

 

下文,將會介紹taskset命令,以及sched_setaffinity系統調用,兩者均可以指定進程運行的CPU實例。

1.taskset

taskset是LINUX提供的一個命令(ubuntu系統可能需要自行安裝,schedutils package)。他可以讓某個程序運行在某個(或)某些CPU上。

以下均以redis-server舉例。

1)顯示進程運行的CPU

命令taskset -p 21184

顯示結果:

pid 21184's current affinity mask: ffffff

注:21184是redis-server運行的pid

      顯示結果的ffffff實際上是二進制24個低位均為1的bitmask,每一個1對應於1個CPU,表示該進程在24個CPU上運行

2)指定進程運行在某個特定的CPU上

命令taskset -pc 3 21184

顯示結果:

pid 21184's current affinity list: 0-23
pid 21184's new affinity list: 3

注:3表示CPU將只會運行在第4個CPU上(從0開始計數)。

3)進程啟動時指定CPU

命令taskset -c 1 ./redis-server ../redis.conf

 

結合這上邊三個例子,再看下taskset的manual,就比較清楚了。

OPTIONS
-p, --pid
operate on an existing PID and not launch a new task

-c, --cpu-list
specify 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.

 

2.sched_setaffinity系統調用

如下文章部分翻譯自:http://www.thinkingparallel.com/2006/08/18/more-information-on-pthread_setaffinity_np-and-sched_setaffinity/

問題描述

sched_setaffinity可以將某個進程綁定到一個特定的CPU。你比操作系統更了解自己的程序,為了避免調度器愚蠢的調度你的程序,或是為了在多線程程序中避免緩存失效造成的開銷,你可能會希望這樣做。如下是sched_setaffinity的例子,其函數手冊可以參考(http://www.linuxmanpages.com/man2/sched_getaffinity.2.php):

 1 /* Short test program to test sched_setaffinity
 2 * (which sets the affinity of processes to processors).
 3 * Compile: gcc sched_setaffinity_test.c
 4 *              -o sched_setaffinity_test -lm
 5 * Usage: ./sched_setaffinity_test
 6 *
 7 * Open a "top"-window at the same time and see all the work
 8 * being done on CPU 0 first and after a short wait on CPU 1.
 9 * Repeat with different numbers to make sure, it is not a
10 * coincidence.
11 */
12  
13 #include <stdio.h>
14 #include <math.h>
15 #include <sched.h>
16  
17 double waste_time(long n)
18 {
19     double res = 0;
20     long i = 0;
21     while(i <n * 200000) {
22         i++;
23         res += sqrt (i);
24     }
25     return res;
26 }
27  
28 int main(int argc, char **argv)
29 {
30     unsigned long mask = 1; /* processor 0 */
31  
32     /* bind process to processor 0 */
33     if (sched_setaffinity(0, sizeof(mask), &mask) <0) {
34         perror("sched_setaffinity");
35     }
36  
37     /* waste some time so the work is visible with "top" */
38     printf ("result: %f\n", waste_time (2000));
39  
40     mask = 2; /* process switches to processor 1 now */
41     if (sched_setaffinity(0, sizeof(mask), &mask) <0) {
42         perror("sched_setaffinity");
43     }
44  
45     /* waste some more time to see the processor switch */
46     printf ("result: %f\n", waste_time (2000));
47 }

根據你CPU的快慢,調整waste_time的參數。然后使用top命令,就可以看到進程在不同CPU之間的切換。(啟動top命令后按“1”,可以看到各個CPU的情況)。

 

父進程和子進程之間會繼承對affinity的設置。因此,大膽猜測,taskset實際上是首先執行了sched_setaffinity系統調用,然后fork+exec用戶指定的進程。


免責聲明!

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



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