如何在Linux中为C或C++中的进程设置CPU关联?

jco*_*nja 34 c linux smp affinity

是否有一种编程方法可以为Linux操作系统在c/c ++中为进程设置CPU亲和性.

Aln*_*tak 48

你需要使用sched_setaffinity(2).

例如,仅在CPU 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);
Run Code Online (Sandbox Code Playgroud)

(0对于第一个参数表示当前进程,如果它是您想要控制的其他进程,则提供PID).

另见sched_getcpu(3).


pue*_*tzk 8

在进程级别使用sched_setaffinity,或在各个线程使用pthread_attr_setaffinity_np.


Mar*_*tin 7

我已经做了很多努力来意识到发生了什么,所以我添加这个答案来帮助像我这样的人(我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;
}
Run Code Online (Sandbox Code Playgroud)

但不要忘记将此选项添加到编译器命令中:-D _GNU_SOURCE 因为操作系统可能会将进程分配给特定核心,因此您可以将其添加GRUB_CMDLINE_LINUX_DEFAULT="quiet splash isolcpus=2,3"到位于的 grub 文件/etc/default和运行 sudo update-grub终端中以保留所需的核心

更新: 如果您想分配更多核心,您可以遵循这段代码:

inline void assignToThisCores(int core_id1, int core_id2)
{
    CPU_ZERO(&mask1);
    CPU_SET(core_id1, &mask1);
    CPU_SET(core_id2, &mask1);
    sched_setaffinity(0, sizeof(mask1), &mask1);
    //__asm__ __volatile__ ( "vzeroupper" : : : ); // It is hear because of that bug which dirtied the AVX registers, so, if you rely on AVX uncomment it.
}
Run Code Online (Sandbox Code Playgroud)


Cir*_*四事件 6

sched_setaffinity+sched_getaffinity最小的 C 可运行示例

这个例子摘自我的回答:How to use sched_getaffinity and sched_setaffinity in Linux from C? 我相信这些问题不是重复的,因为这个问题是这个问题的子集,因为sched_getaffinity它只询问有关 C++ 的问题,而没有提及 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);
    }
    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分叉:How to Prevent Inheriting CPUaffinity by child forked process?

蟒蛇:os.sched_getaffinityos.sched_setaffinity

请参阅:如何使用 python 找出 CPU 数量

在 Ubuntu 16.04 中测试。