Bind the process / thread to a specific CPU core and run under Linux

Transfer from: https://blog.csdn.net/guotianqing/article/details/80958281

Overview
Now everyone is basically using multi-core CPU, generally 4 cores. Usually applications are managed by the operating system at runtime. The operating system schedules application processes to run on different cores in turn.

For ordinary applications, the operating system's default scheduling mechanism is no problem. However, when a process needs a higher operating efficiency, it is necessary to consider running it on a separate core to reduce the overhead caused by scheduling on different cores.

After a process / thread is bound to a specific CPU core, the process will always run on this core and will not be scheduled by the operating system to other cores. But the bound core may still be scheduled to run other applications.

Operating system scheduling of multi-core CPUs
Currently, both Windows and Linux support scheduling management of multi-core CPUs.

The core of software development in a multi-core environment is multi-threaded development. This multi-threading not only represents multi-threading in software implementation, but also requires multi-threading technology in hardware.

The focus of multi-core operating systems is on the allocation and scheduling of processes. Process allocation allocates processes to reasonable physical cores, because different cores have different sharing and historical operating conditions. Some physical cores can share the secondary cache, while others are independent. If the process with data sharing is allocated to the core with shared secondary cache, the performance will be greatly improved; otherwise, it may affect performance.

Process scheduling will involve real-time, load balancing and other issues. The current research hotspots mainly focus on the following aspects:

The parallel development of the program design
time-dependent
tasks of multi-process allocation and scheduling
cache error sharing
consistency access problem
inter-process communication
multi-processor core internal resource competition
multi-process and multi-thread running on the CPU core are as follows:

When each CPU core runs a process, since the resources of each process are independent, there is no need to consider the context when switching between CPU cores. When
each CPU core runs a thread, sometimes the threads need to share resources, so these The resource must be copied from one core of the CPU to another core, which will cause additional overhead.
Bind the process to run on the cpu core.
View the cpu. There are several cores.
Use cat / proc / cpuinfo to view cpu information.

processor, indicating the number of CPU
cores of the CPU, indicating the number of cores of each processor.
You can also use the system call sysconf to obtain the number of CPU cores:

#include <unistd.h>

int sysconf (_SC_NPROCESSORS_CONF); / * returns the number of cores that can be used by the system, but its value will include the number of cores disabled in the system, so this value does not represent the number of cores available in the current system * /
int sysconf (_SC_NPROCESSORS_ONLN); / * The return value really represents the number of cores currently available in the system * /

/ * The following two functions are similar to the above * /
#include <sys / sysinfo.h>

int get_nprocs_conf (void); / * Available cores * /
int get_nprocs (void); / * Really reflects the current available cores * /

I use a virtual machine, there are 2 processors, each processor has only one The core is equivalent to one processor with two cores.

Use the taskset instruction to
get the process pid
->% ps
PID TTY TIME CMD
2683 pts / 1 00:00:00 zsh
2726 pts / 1 00:00:00 dgram_servr
2930 pts / 1 00:00:00 ps to

see where the process is currently running On the cpu
->% taskset -p 2726
pid 2726's current affinity mask: 3

shows the decimal number 3 converted to 2 hexadecimal is the lowest two is 1, each 1 corresponds to a CPU, so the process runs on 2 CPUs.

The specified process is running on cpu1
->% taskset -pc 1 2726
pid 2726's current affinity list: 0,1
pid 2726's new affinity list: 1

Note that the label of the cpu starts from 0, so cpu1 represents the second cpu (the first The label of a cpu is 0).

So far, the application is bound to run on cpu1, view as follows:

->% taskset -p 2726
pid 2726's current affinity mask: 2

Bind cpu when starting the program
# Bind to the second cpu when starting
->% taskset -c 1 ./dgram_servr&
[1] 3011


#Check to confirm the binding status ->% taskset -p 3011
pid 3011's current affinity mask: 2

Use sched_setaffinity system call
sched_setaffinity to bind a process to a specific CPU.

#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <sched.h>

/ * Set the process with the process ID of pid to run on the CPU set by the mask
* The second parameter cpusetsize is the length of the number specified by the mask
* Usually set to sizeof (cpu_set_t)

* If the value of pid is 0, it means that the specified process is the current process
* /
int sched_setaffinity (pid_t pid, size_t cpusetsize, cpu_set_t * mask);

int sched_getaffinity (pid_t pid, size_t cpusetsize, cpu_set_t * mask); / * Obtain the CPU bit mask of the process indicated by pid, and return the mask to the structure pointed to by mask * /

Instance
# include <stdlib.h >
#include <stdio.h>
#include <sys / types.h>
#include <sys / sysinfo.h>
#include <unistd.h>

#define __USE_GNU
#include<sched.h>
#include<ctype.h>
#include<string.h>
#include<pthread.h>
#define THREAD_MAX_NUM 200 //1个CPU内的最多进程数

int num = 0; // The number of cores in the CPU
void * threadFun (void * arg) // arg Pass the thread label (defined by yourself)
{
cpu_set_t mask; // The collection of CPU cores
cpu_set_t get; // Get the CPU
int in the collection * a = (int *) arg;
int i;

printf ("the thread is:% d \ n", * a); // Display the number of threads
CPU_ZERO (& mask); // Set
CPU_SET (* a, & mask); // Set affinity value
if (sched_setaffinity (0, sizeof (mask), & mask) == -1) // Set thread CPU affinity
{
printf ("warning: could not set CPU affinity, continuing ... \ n");
}

CPU_ZERO (& get);
if (sched_getaffinity (0, sizeof (get), & get) == -1) // Get thread CPU affinity
{
printf ("warning: cound not get thread affinity, continuing ... \ n");
}
for (i = 0; i <num; i ++)
{
if (CPU_ISSET (i, & get)) // determine which CPU the thread has affinity with
{
printf ("this thread% d is running processor:% d \ n", i, i);
}
}

return NULL;
}

int main(int argc, char* argv[])
{
int tid[THREAD_MAX_NUM];
int i;
pthread_t thread[THREAD_MAX_NUM];

num = sysconf(_SC_NPROCESSORS_CONF); //获取核数
if (num > THREAD_MAX_NUM) {
printf("num of cores[%d] is bigger than THREAD_MAX_NUM[%d]!\n", num, THREAD_MAX_NUM);
return -1;
}
printf("system has %i processor(s). \n", num);

for (i = 0; i <num; i ++)
{
tid [i] = i; // Each thread must have a tid [i]
pthread_create (& thread [i], NULL, threadFun, (void *) & tid [i ]);
}
for (i = 0; i <num; i ++)
{
pthread_join (thread [i], NULL); // Wait for all threads to end, the thread is an endless loop so CTRL + C ends
}
return 0;
}

Run Result
->% ./a.out
system has 2 processor (s).
The thread is: 0
the thread is: 1
this thread 0 is running processor: 0
this thread 1 is running processor: 1

binds the thread to the CPU core
Use the pthread_setaffinity_np function to run the binding thread to the CPU core. Its prototype is defined as follows:
#define _GNU_SOURCE / * See feature_test_macros (7) * /
#include <pthread.h>

int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset);

Compile and link with -pthread.

The meaning of each parameter is similar to sched_setaffinity.

Examples

#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define handle_error_en(en, msg) \
do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

int
main(int argc, char *argv[])
{
int s, j;
cpu_set_t cpuset;
pthread_t thread;

thread = pthread_self();

/* Set affinity mask to include CPUs 0 to 7 */

CPU_ZERO(&cpuset);
for (j = 0; j < 8; j++)
CPU_SET(j, &cpuset);

s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0)
handle_error_en(s, "pthread_setaffinity_np");

/* Check the actual affinity mask assigned to the thread */

s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
if (s != 0)
handle_error_en(s, "pthread_getaffinity_np");

printf("Set returned by pthread_getaffinity_np() contained:\n");
for (j = 0; j < CPU_SETSIZE; j++)
if (CPU_ISSET(j, &cpuset))
printf(" CPU %d\n", j);

exit (EXIT_SUCCESS);
}

Running result
->% ./a.out
Set returned by pthread_getaffinity_np () contained:
CPU 0
CPU 1

Summary
There are many ways to assign processes / threads to specific CPU cores for operation.

In specific use, it is necessary to decide which method to use according to the usage scenario and requirements. I personally think that the important step is to determine whether to use the method of binding threads to the core.

[Reference]
Introduction of multi-core technology operating systems supported method for multi-core processors
thread-bound CPU core -sched_setaffinity
pthread_setaffinity_np (3) Linux Programmer's ManualPTHREAD_SETAFFINITY_NP
(3) ----------------
Copyright statement: This article is an original article of CSDN blogger "guotianqing", which follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this statement when reprinting.
Original link: https://blog.csdn.net/guotianqing/java/article/details/80958281

Guess you like

Origin www.cnblogs.com/sky-heaven/p/12753284.html