===============================================================

linux下的单进程多线程的程序,要实现每个线程平均分配到多核cpu,主要有2个方法

1:利用linux系统自己的线程切换机制,linux有一个服务叫做irqbalance,这个服务是linux系统自带的,默认会启动,这个服务的作用就是把多线程平均分配到CPU的每个核上面,只要这个服务不停止,多线程分配就可以自己实现。但是要注意,如果线程函数内部的有某个循环,且该循环内没有任何系统调用的话,可能会导致这个线程的CPU时间无法被切换出去。也就是占满CPU现象,此时加个系统调用,例如sleep,线程所占的CPU时间就可以切换出去了。

2:利用pthread库自带的线程亲和性设置函数,来设置线程在某个CPU核心上跑,这个需要在程序内部实现。同时注意不要和进程亲和性设置搞混淆了

1
2
3
4
5
6
7
8
9
10
11
12
13
int pthread_setaffinity_np(pthread_t threadsize_t cpusetsize,
const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t threadsize_t cpusetsize, 
cpu_set_t *cpuset);
从函数名以及参数名都很明了,唯一需要点解释下的可能就是cpu_set_t这个结构体了。这个结构体的理解类似于select中的fd_set,可以理解为cpu集,也是通过约定好的宏来进行清除、设置以及判断:
//初始化,设为空
void CPU_ZERO (cpu_set_t *set); 
//将某个cpu加入cpu集中 
void CPU_SET (int cpu, cpu_set_t *set); 
//将某个cpu从cpu集中移出 
void CPU_CLR (int cpu, cpu_set_t *set); 
//判断某个cpu是否已在cpu集中设置了 
int CPU_ISSET (int cpu, const cpu_set_t *set);

=================================================================

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

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

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

  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. inline int set_cpu(int i)
  8. {
  9. cpu_set_t mask;
  10. CPU_ZERO(&mask);
  11. CPU_SET(i,&mask);
  12. printf("thread %u, i = %d\n", pthread_self(), i);
  13. if(-1 == pthread_setaffinity_np(pthread_self() ,sizeof(mask),&mask))
  14. {
  15. fprintf(stderr, "pthread_setaffinity_np erro\n");
  16. return -1;
  17. }
  18. return 0;
  19. }
  20. void *thread_ip_bitmap_set(void *p)
  21. {
  22. uint32_t i, ip;
  23. struct id_ipmap *entry;
  24. thread_info_t *info = (thread_info_t *)p;
  25. if(set_cpu(info->id))
  26. {
  27. return NULL;
  28. }
  29. printf("info->id = %d; info->start = %d;  info->end = %d, sub = %d\n", info->id, info->start, info->end, info->start - info->end);
  30. for (i = info->start; i < info->end; ++i) {
  31. entry = &ipmap_queue[i];
  32. for (ip = entry->ip_start; ip < entry->ip_end; ip++) {
  33. ip_bitmap_set(adns_htobe32(ip), entry->id);
  34. }
  35. }
  36. printf("info->id = %d finished\n", info->id);
  37. return NULL;
  38. }
  39. int main()
  40. {
  41. for(thread_index=0; thread_index < 10; thread_index++)
  42. pthread_create(&thread_id[thread_index],NULL, thread_ip_bitmap_set, &thread_info[thread_index]);
  43. }
  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. inline int set_cpu(int i)
  10. {
  11. cpu_set_t mask;
  12. CPU_ZERO(&mask);
  13. CPU_SET(i,&mask);
  14. printf("thread %u, i = %d\n", pthread_self(), i);
  15. if(-1 == pthread_setaffinity_np(pthread_self() ,sizeof(mask),&mask))
  16. {
  17. return -1;
  18. }
  19. return 0;
  20. }
  21. void *fun(void *i)
  22. {
  23. if(set_cpu(*(int *)i))
  24. {
  25. printf("set cpu erro\n");
  26. }
  27. long long a = 0;
  28. while(1)
  29. {
  30. a += rand();
  31. }
  32. return NULL;
  33. }
  34. int main (int argc, const char * argv[]) {
  35. int i;
  36. int cpu_nums = sysconf(_SC_NPROCESSORS_CONF);
  37. printf("cpu_numbs = %d\n", cpu_nums);
  38. pthread_t Thread[10];
  39. int tmp[10];
  40. for(i = 0; i < 10; ++i)
  41. {
  42. tmp[i] = i;
  43. pthread_create(&Thread[i],NULL,fun, &tmp[i]);
  44. }
  45. for(i = 0; i < 10; ++i)
  46. {
  47. pthread_join(Thread[i],NULL);
  48. }
  49. return 0;
  50. }

转载: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 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用户指定的进程。

linux下将不同线程绑定到不同core和cpu上——pthread_setaffinity_np的更多相关文章

  1. Windows和Linux下通用的线程接口

    对于多线程开发,Linux下有pthread线程库,使用起来比较方便,而Windows没有,对于涉及到多线程的跨平台代码开发,会带来不便.这里参考网络上的一些文章,整理了在Windows和Linux下 ...

  2. [转] linux 下 进程和线程的区别

    1.进程与线程 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是C ...

  3. [进程管理]linux 下 进程和线程的区别(baidu 面试)

    进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是CPU调度和分派的 ...

  4. linux 将进程或者线程绑定到指定的cpu上

    基本概念 cpu亲和性(affinity) CPU的亲和性, 就是进程要在指定的 CPU 上尽量长时间地运行而不被迁移到其他处理器,也称为CPU关联性:再简单的点的描述就将指定的进程或线程绑定到相应的 ...

  5. linux 下 进程和线程的区别

    1.进程与线程 进程是程序执行时的一个实例,即它是程序已经执行到课中程度的数据结构的汇集.从内核的观点看,进程的目的就是担当分配系统资源(CPU时间.内存等)的基本单位. 线程是进程的一个执行流,是C ...

  6. 在Linux下写一个线程池以及线程池的一些用法和注意点

    -->线程池介绍(大部分来自网络)  在这个部分,详细的介绍一下线程池的作用以及它的技术背景以及他提供的一些服务等.大部分内容来自我日常生活中在网络中学习到的一些概念性的东西. -->代码 ...

  7. Linux下C的线程同步机制

    C里提供了保证线程安全性的三种方法: (添加头文件#include<pthread.h>,pthread 库不是 Linux 系统默认的库,连接时需要使用静态库 libpthread.a, ...

  8. Linux下进程与线程的区别及查询方法

    在平时工作中,经常会听到应用程序的进程和线程的概念,那么它们两个之间究竟有什么关系或不同呢?一.深入理解进程和线程的区别 1)两者概念 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进 ...

  9. linux下怎样将sheduler绑定到制定的cpu核上

    作者:张昌昌   1.顺序绑定 erl +sbt db 是按从前到后的顺序来绑定调度器的,如: erl +sbt db +S 3含义是启动erlang虚拟机,开启3个调度器,按顺序绑定在0,1.2号核 ...

随机推荐

  1. BZOJ 3230: 相似子串

    3230: 相似子串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1485  Solved: 361[Submit][Status][Discuss ...

  2. Angular指令渗透式理解

    通过一段时间对angular指令的使用,理解了angular指令的意义,下面逐一介绍一下. ng-app:定义一个angualr模块,表示angular作用的范围,如下代码: ng-app在html标 ...

  3. 【BZOJ-2730】矿场搭建 Tarjan 双连通分量

    2730: [HNOI2012]矿场搭建 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1602  Solved: 751[Submit][Statu ...

  4. elasticsearch agg

    OK curl -XGET http://21.3.5.121:9200/ipv4geo/service/_count -d '{"query":{"match" ...

  5. Java的生日

    你知道巴西的税务系统,亚马逊的Kindle阅读器以及韩国的第一大镁板制造厂有什么共同点吗?乍一看上去,这简直就是风马牛不相及,但是这些系统同世界上其它100亿个设备共享一个元素,那就是Java. 19 ...

  6. [Unity] Shader(着色器)之固定管线

    在Unity中,固定管线Shader的性能是最好的. 什么是固定管线呢? 固定渲染管线 —— 这是标准的几何&光照(T&L)管线,功能是固定的,它控制着世界.视.投影变换及固定光照控制 ...

  7. fzoj1314 You are my brother

    题目描述 Little A gets to know a new friend, Little B, recently. One day, they realize that they are fam ...

  8. C和指针 第十三章 高级指针话题

    高级声明: int (*f)(); 这里声明有两个括号,第二个括号是函数调用,第一个括号是聚组作用.(*f)是一个函数,所以f是指向返回整型的函数的指针.程序中的每个函数都位于,内存中某个位置,所以存 ...

  9. sublime 编译运行C程序

    { "cmd": ["gcc", "${file}", "-o","${file_path}/${file_b ...

  10. position:fixed失效

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...