Есть ли программный метод для установки сродства процессора для процесса в c/c++ для операционной системы Linux.
Как установить привязку к процессору для процесса из C или C++ в Linux?
Ответ 1
Вам нужно использовать sched_setaffinity(2)
.
Например, для запуска только на процессорах 0 и 2:
#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
для первого параметра означает текущий процесс, укажите PID, если это какой-то другой процесс, которым вы хотите управлять).
Смотрите также sched_getcpu(3)
.
Ответ 2
Используйте параметр sched_setaffinity на уровне процесса или pthread_attr_setaffinity_np для отдельных потоков.
Ответ 3
Короче
unsigned long mask = 7; /* processors 0, 1, and 2 */
unsigned int len = sizeof(mask);
if (sched_setaffinity(0, len, &mask) < 0) {
perror("sched_setaffinity");
}
Посмотрите Приоритет процессора для более подробной информации
Ответ 4
Я много сделал для того, чтобы понять, что происходит, поэтому я добавляю этот ответ для помощи таким людям, как я (я использую gcc
компилятор в 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;
}
Но не забудьте добавить эти параметры в команду компилятора: -D _GNU_SOURCE
Поскольку операционная система может назначить процесс конкретному ядру, вы можете добавить этот GRUB_CMDLINE_LINUX_DEFAULT="quiet splash isolcpus=2,3"
в файл grub, расположенный в /etc/default
, и запустить sudo update-grub
в терминале, чтобы зарезервировать нужные вам ядра.
Ответ 5
sched_setaffinity
+ sched_getaffinity
минимальный C исполняемый пример
Этот пример был извлечен из моего ответа по адресу: Как использовать sched_getaffinity и sched_setaffinity в Linux из C? Я полагаю, что вопросы не являются дубликатами, так как этот вопрос является подмножеством этого, поскольку он спрашивает только о sched_getaffinity
и не упоминает C++.
В этом примере мы получаем сходство, модифицируем его и проверяем, вступило ли оно в силу с sched_getcpu()
.
#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);
} else {
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;
}
Скомпилируйте и запустите с:
gcc -std=c99 main.c
./a.out
Образец вывода:
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
Который означает, что:
- изначально все мои 16 ядер были включены, и процесс был запущен случайным образом на ядре 9 (10-е)
- после того, как мы установили привязку только к первому ядру, процесс обязательно был перемещен в ядро 0 (первое)
Также интересно запускать эту программу через taskset
:
taskset -c 1,3 ./a.out
Который дает вывод формы:
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
и поэтому мы видим, что это ограничивало сродство с самого начала.
Это работает, потому что сходство наследуется дочерними процессами, какой taskset
разветвляется: как предотвратить наследование taskset
процессора дочерним разветвленным процессом?
Протестировано в Ubuntu 16.04, GitHub upstream.