如何在C语言的Linux中使用sched_getaffinity和sched_setaffinity?

Bas*_*mah 14 c linux schedule process affinity

我在尝试着:

  • 使用处理器固定同时运行16个副本(每个核心2个副本)

  • 在处理器固定(每个核心2个副本)的同时运行8个副本,并在某个功能说功能1完成后将处理器核心翻转到最远的核心.

我面临的问题是如何选择最远的处理器.

有些朋友建议使用sched_getaffinity和sched_setaffinity,但我认为没有找到任何好的例子.

Pet*_*ham 17

要使用sched_setaffinity使当前进程在核心7上运行,请执行以下操作:

cpu_set_t my_set;        /* Define your cpu_set bit mask. */
CPU_ZERO(&my_set);       /* Initialize it all to 0, i.e. no CPUs selected. */
CPU_SET(7, &my_set);     /* set the bit that represents core 7. */
sched_setaffinity(0, sizeof(cpu_set_t), &my_set); /* Set affinity of tihs process to */
                                                  /* the defined mask, i.e. only 7. */
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅http://linux.die.net/man/2/sched_setaffinityhttp://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html.


小智 7

不要将CPU_SETSIZE用作sched_ [set | get] affinity的cpusetsize参数.这些名称具有误导性,但这是错误的.makro CPU_SETSIZE是(引用man 3 cpu_set)"比可以存储在cpu_set_t中的最大CPU数大1的值." 你必须使用

sched_setaffinity(0, sizeof(cpu_set_t), &my_set);
Run Code Online (Sandbox Code Playgroud)

代替.


Cir*_*四事件 5

最小的可运行示例

在此示例中,我们获取了亲和力,对其进行了修改,然后使用来检查它是否已生效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;
}
Run Code Online (Sandbox Code Playgroud)

GitHub上游

编译并运行:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out
Run Code Online (Sandbox Code Playgroud)

样本输出:

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
Run Code Online (Sandbox Code Playgroud)

意思就是:

  • 最初,我的所有16个内核都已启用,并且该进程随机在第9个内核(第10个)上运行
  • 在我们将亲和力设置为仅第一个核心之后,该进程必然移至核心0(第一个核心)

通过taskset以下方式运行该程序也很有趣:

taskset -c 1,3 ./a.out
Run Code Online (Sandbox Code Playgroud)

给出以下形式的输出:

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
Run Code Online (Sandbox Code Playgroud)

因此我们看到它从一开始就限制了亲和力。

之所以可行,是因为该关联性是由子进程继承的,这taskset是分叉的:如何防止子分叉进程继承CPU的关联性?

nprocsched_getaffinity默认情况下尊重,如以下所示:如何使用python找出CPU的数量

在Ubuntu 16.04中测试。