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 |
|
The thread is bound to a different processor:
Here there are two join cpu, cpu a five nuclear
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <sched.h>
- inline int set_cpu(int i)
- {
- cpu_set_t mask;
- CPU_ZERO(&mask);
- CPU_SET(i,&mask);
- printf("thread %u, i = %d\n", pthread_self(), i);
- if(-1 == pthread_setaffinity_np(pthread_self() ,sizeof(mask),&mask))
- {
- fprintf(stderr, "pthread_setaffinity_np erro\n");
- return -1;
- }
- return 0;
- }
- void *thread_ip_bitmap_set(void *p)
- {
- uint32_t i, ip;
- struct id_ipmap *entry;
- thread_info_t *info = (thread_info_t *)p;
- if(set_cpu(info->id))
- {
- return NULL;
- }
- printf("info->id = %d; info->start = %d; info->end = %d, sub = %d\n", info->id, info->start, info->end, info->start - info->end);
- for (i = info->start; i < info->end; ++i) {
- entry = &ipmap_queue[i];
- for (ip = entry->ip_start; ip < entry->ip_end; ip++) {
- ip_bitmap_set(adns_htobe32(ip), entry->id);
- }
- }
- printf("info->id = %d finished\n", info->id);
- return NULL;
- }
- int main ()
- {
- for(thread_index=0; thread_index < 10; thread_index++)
- pthread_create(&thread_id[thread_index],NULL, thread_ip_bitmap_set, &thread_info[thread_index]);
- }
- #define _GNU_SOURCE
- #include <sched.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include<string.h>
- #include <stdio.h>
- #include <errno.h>
- #include <pthread.h>
- inline int set_cpu(int i)
- {
- cpu_set_t mask;
- CPU_ZERO(&mask);
- CPU_SET(i,&mask);
- printf("thread %u, i = %d\n", pthread_self(), i);
- if(-1 == pthread_setaffinity_np(pthread_self() ,sizeof(mask),&mask))
- {
- return -1;
- }
- return 0;
- }
- void *fun(void *i)
- {
- if(set_cpu(*(int *)i))
- {
- printf("set cpu erro\n");
- }
- long long a = 0;
- while(1)
- {
- a += rand();
- }
- return NULL;
- }
- int main (int argc, const char * argv[]) {
- int i;
- int cpu_nums = sysconf(_SC_NPROCESSORS_CONF);
- printf("cpu_numbs = %d\n", cpu_nums);
- pthread_t Thread[10];
- int tmp[10];
- for(i = 0; i < 10; ++i)
- {
- tmp[i] = i;
- pthread_create(&Thread[i],NULL,fun, &tmp[i]);
- }
- for(i = 0; i < 10; ++i)
- {
- pthread_join(Thread[i],NULL);
- }
- return 0;
- }
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 ):
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 }
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.