linux下将不同线程绑定到不同core和cpu上 pthread_setaffinity_np——005最全面

来源:互联网 发布:手机端回到顶部 js 编辑:程序博客网 时间:2024/05/16 07:00

http://blog.csdn.net/zdy0_2004/article/details/54730611

http://blog.csdn.net/sprintfwater/article/details/39203049

将线程绑定到不同的processor上:

这里加入有两个cpu,一个cpu五个核

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. #define _GNU_SOURCE                                                                                                                                              
  2. #include <stdio.h>  
  3. #include <string.h>  
  4. #include <stdlib.h>  
  5. #include <stdint.h>  
  6. #include <sched.h>  
  7.   
  8. inline int set_cpu(int i)  
  9. {  
  10.     cpu_set_t mask;  
  11.     CPU_ZERO(&mask);  
  12.   
  13.     CPU_SET(i,&mask);  
  14.   
  15.     printf("thread %u, i = %d\n", pthread_self(), i);  
  16.     if(-1 == pthread_setaffinity_np(pthread_self() ,sizeof(mask),&mask))  
  17.     {  
  18.         fprintf(stderr, "pthread_setaffinity_np erro\n");  
  19.         return -1;  
  20.     }  
  21.     return 0;  
  22. }  
  23. void *thread_ip_bitmap_set(void *p)  
  24. {  
  25.     uint32_t i, ip;  
  26.     struct id_ipmap *entry;  
  27.     thread_info_t *info = (thread_info_t *)p;  
  28.   
  29.     if(set_cpu(info->id))  
  30.     {  
  31.         return NULL;  
  32.     }  
  33.    
  34.     printf("info->id = %d; info->start = %d;  info->end = %d, sub = %d\n", info->id, info->start, info->end, info->start - info->end);  
  35.     for (i = info->start; i < info->end; ++i) {  
  36.         entry = &ipmap_queue[i];  
  37.         for (ip = entry->ip_start; ip < entry->ip_end; ip++) {  
  38.             ip_bitmap_set(adns_htobe32(ip), entry->id);  
  39.         }  
  40.     }  
  41.     printf("info->id = %d finished\n", info->id);  
  42.     return NULL;  
  43. }  
  44.   
  45.   
  46.   
  47. int main()  
  48. {  
  49. for(thread_index=0; thread_index < 10; thread_index++)  
  50.         pthread_create(&thread_id[thread_index],NULL, thread_ip_bitmap_set, &thread_info[thread_index]);  
  51. }  




[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. #define _GNU_SOURCE  
  2. #include <sched.h>  
  3. #include <unistd.h>  
  4. #include <sys/types.h>  
  5. #include<string.h>  
  6. #include <stdio.h>  
  7. #include <errno.h>  
  8. #include <pthread.h>  
  9.   
  10.   
  11. inline int set_cpu(int i)  
  12. {  
  13.     cpu_set_t mask;  
  14.     CPU_ZERO(&mask);  
  15.   
  16.     CPU_SET(i,&mask);  
  17.   
  18.     printf("thread %u, i = %d\n", pthread_self(), i);  
  19.     if(-1 == pthread_setaffinity_np(pthread_self() ,sizeof(mask),&mask))  
  20.     {  
  21.         return -1;  
  22.     }  
  23.     return 0;  
  24. }  
  25. void *fun(void *i)  
  26. {  
  27.     if(set_cpu(*(int *)i))  
  28.     {  
  29.         printf("set cpu erro\n");  
  30.     }  
  31.     long long a = 0;  
  32.     while(1)  
  33.     {  
  34.         a += rand();  
  35.     }  
  36.     return NULL;  
  37. }  
  38.   
  39. int main (int argc, const char * argv[]) {  
  40.     int i;  
  41.     int cpu_nums = sysconf(_SC_NPROCESSORS_CONF);  
  42.   
  43.     printf("cpu_numbs = %d\n", cpu_nums);  
  44.     pthread_t Thread[10];  
  45.     int tmp[10];  
  46.   
  47.     for(i = 0; i < 10; ++i)  
  48.     {  
  49.         tmp[i] = i;  
  50.         pthread_create(&Thread[i],NULL,fun, &tmp[i]);  
  51.     }  
  52.   
  53.   
  54.     for(i = 0; i < 10; ++i)  
  55.     {  
  56.         pthread_join(Thread[i],NULL);  
  57.     }  
  58.   
  59.     return 0;  
  60. }  


转载:http://blog.csdn.NET/xluren/article/details/43202201

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 a10 * 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用户指定的进程。


原创粉丝点击