问题
Is there a programmatic method to set CPU affinity for a process in c/c++ for the Linux operating system.
回答1:
You need to use sched_setaffinity(2).
For example, to run on CPUs 0 and 2 only:
#define _GNU_SOURCE
#include <sched.h>
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(0, &mask);
CPU_SET(2, &mask);
result = sched_setaffinity(0, sizeof(mask), &mask);
(0
for the first parameter means the current process, supply a PID if it's some other process you want to control).
See also sched_getcpu(3).
回答2:
Use sched_setaffinity at the process level, or pthread_attr_setaffinity_np for individual threads.
回答3:
sched_setaffinity
+ sched_getaffinity
minimal C runnable example
This example was extracted from my answer at: How to use sched_getaffinity and sched_setaffinity in Linux from C? I believe the questions are not duplicates since that one is a subset of this one, as it asks about sched_getaffinity
only, and does not mention C++.
In this example, we get the affinity, modify it, and check if it has taken effect with sched_getcpu().
main.c
#define _GNU_SOURCE
#include <assert.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void print_affinity() {
cpu_set_t mask;
long nproc, i;
if (sched_getaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
perror("sched_getaffinity");
assert(false);
}
nproc = sysconf(_SC_NPROCESSORS_ONLN);
printf("sched_getaffinity = ");
for (i = 0; i < nproc; i++) {
printf("%d ", CPU_ISSET(i, &mask));
}
printf("\n");
}
int main(void) {
cpu_set_t mask;
print_affinity();
printf("sched_getcpu = %d\n", sched_getcpu());
CPU_ZERO(&mask);
CPU_SET(0, &mask);
if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) == -1) {
perror("sched_setaffinity");
assert(false);
}
print_affinity();
/* TODO is it guaranteed to have taken effect already? Always worked on my tests. */
printf("sched_getcpu = %d\n", sched_getcpu());
return EXIT_SUCCESS;
}
GitHub upstream.
Compile and run:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
Sample output:
sched_getaffinity = 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
sched_getcpu = 9
sched_getaffinity = 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sched_getcpu = 0
Which means that:
- initially, all of my 16 cores were enabled, and the process was randomly running on core 9 (the 10th one)
- after we set the affinity to only the first core, the process was moved necessarily to core 0 (the first one)
It is also fun to run this program through taskset
:
taskset -c 1,3 ./a.out
Which gives output of form:
sched_getaffinity = 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
sched_getcpu = 2
sched_getaffinity = 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
sched_getcpu = 0
and so we see that it limited the affinity from the start.
This works because the affinity is inherited by child processes, which taskset
is forking: How to prevent inheriting CPU affinity by child forked process?
Tested in Ubuntu 16.04.
回答4:
In short
unsigned long mask = 7; /* processors 0, 1, and 2 */
unsigned int len = sizeof(mask);
if (sched_setaffinity(0, len, &mask) < 0) {
perror("sched_setaffinity");
}
Look in CPU Affinity for more details
回答5:
I have done many effort to realize what is happening so I add this answer for helping people like me(I use gcc
compiler in linux mint)
#include <sched.h>
cpu_set_t mask;
inline void assignToThisCore(int core_id)
{
CPU_ZERO(&mask);
CPU_SET(core_id, &mask);
sched_setaffinity(0, sizeof(mask), &mask);
}
int main(){
//cal this:
assignToThisCore(2);//assign to core 0,1,2,...
return 0;
}
But don't forget to add this options to the compiler command : -D _GNU_SOURCE
Because operating system might assign a process to the particular core, you can add this GRUB_CMDLINE_LINUX_DEFAULT="quiet splash isolcpus=2,3"
to the grub file located in /etc/default
and the run sudo update-grub
in terminal to reserve the cores you want
来源:https://stackoverflow.com/questions/280909/how-to-set-cpu-affinity-for-a-process-from-c-or-c-in-linux