linux under the different threads and bind to different core cpu

Under linux single process multi-threaded program, each thread to achieve equal distribution to multi-core cpu, there are two main methods

1: use linux system's own thread-switching mechanism, linux has a service called the irqbalance, this service is a linux system comes with default will start a service when it is put above average assigned to each core CPU multithreading, as long as this service does not stop, you can assign your own multi-threaded implementation. Note, however, if there is a cycle of internal thread function, without any circulation within the system call, it may cause the thread CPU time and can not be switched out. CPU phenomenon that is filled, then add a system call, such as sleep, threads share CPU time you can switch out.

2: pthread library using the built-in thread affinity setting function to set the thread running on one CPU core, the need to achieve within the program. And taking care not to be confused with the process affinity settings

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);

The thread is bound to a different processor:

Here there are two join cpu, cpu a five nuclear

 

  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. }  

 

  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. }  

 

 

Reprinted: http: //blog.csdn.net/xluren/article/details/43202201

 

 

coolshell latest article, "Performance Tuning Guide" in the "multi-core CPU tuning" section, references to "we can not let the operating system load balancing, because we know more about their own programs, so that we can manually assign CPU nuclear, and will not take up too much CPU0, or let a bunch of key processes and other processes huddled together. ". Referred to a tool under Linux in the article, taskset, you can set CPU running a single process.

At the same time, because the program in recent relevant information see the redis, redis as a single process model, in order to take full advantage of multi-core CPU, often start multiple instances on a single server. In order to reduce the overhead of switching, it is necessary to specify a CPU operation for each instance.

 

Hereinafter, we will introduce taskset command, and sched_setaffinity system calls, both of which can be specified CPU running process instance.

1.taskset

LINUX is a command taskset provided (Ubuntu system may need to install their own, schedutils package). He allows a program running on one (or) some CPU.

The following Examples are redis-server.

1) shows the CPU processes running

Command taskset -p 21184

Show results:

pid 21184's current affinity mask: ffffff

Note: 21184 is the pid redis-server running

      ffffff display the results actually are binary 24 low bitmask 1, each corresponding to a CPU 1, it indicates that the processes running on the CPU 24

2) specify the processes to run on a particular CPU

Command taskset -pc 3 21184

Show results:

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

NOTE: 3 denotes a CPU will only run on the CPU fourth (counting from 0).

3) specify the CPU when the process starts

Command taskset -c 1 ./redis-server ../redis.conf

 

The combination of these upper three examples, taskset look at the manual, it is more clear.

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 system calls

As part of the article translated from: http://www.thinkingparallel.com/2006/08/18/more-information-on-pthread_setaffinity_np-and-sched_setaffinity/

Problem Description

sched_setaffinity a process can be bound to a particular CPU. You know more about your program than the operating system, in order to avoid the scheduler stupid scheduling your program, or in order to avoid the overhead of cache in a multi-threaded programs caused by the failure, you might want to do this. The following are examples sched_setaffinity, which can refer to the function manuals ( http://www.linuxmanpages.com/man2/sched_getaffinity.2.php ):

Copy the code

Copy the code

 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 }

Copy the code

Copy the code

Depending on your CPU's speed, adjustment of parameters waste_time. Then use the top command, you can see the process of switching between different CPU. (After starting the top command press "1", you can see various CPU).

 

It will inherit the settings of the affinity between parent and child processes. Therefore, the bold speculation, taskset actually first performed sched_setaffinity system call, then fork + exec user-specified process.

Published 29 original articles · won praise 14 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_43778179/article/details/104510357