【问题标题】:Pinning a process to any CPU respecting affinity将进程固定到任何尊重亲和性的 CPU
【发布时间】:2018-09-22 22:16:22
【问题描述】:

假设我想以编程方式将当前进程固定到单个 CPU,但我不在乎是哪个 CPU。

使用sched_setaffinity 和固定CPU 编号的一种简单方法,可能是0,因为应该总是有一个“CPU 0”1

但是,如果进程的亲和性已设置为现有 CPU 的子集(不包括您选择的 CPU)(例如,使用 taskset 启动它),则此方法会失败。

所以我想选择“任何 CPU”来固定,但只能从当前关联掩码允许的 CPU 中选择。这是一种方法:

cpu_set_t cpu_set;
if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set)) {
    err("failed while getting existing cpu affinity");
}
for (int cpu = 0; cpu < CPU_SETSIZE; cpu++) {
    if (CPU_ISSET(cpu, &cpu_set)) {
        CPU_ZERO(cpu_set);
        CPU_SET(cpu, &cpu_set);
    }
}
int result = sched_setaffinity(0, sizeof(cpu_set), &cpu_set);

基本上我们得到当前的关联掩码,然后循环遍历每个可能的 CPU 以寻找第一个允许的 CPU,然后将仅此 CPU 设置为 sched_setaffinity 的掩码传递给。

但是,如果当前的关联掩码在 getset 调用之间发生了变化,则 @​​987654328@ 调用将失败。有什么办法可以解决这种竞争条件?


1 虽然 CPU 零并不总是在线

【问题讨论】:

    标签: linux scheduler affinity


    【解决方案1】:

    您可以使用getcpu() 来发现您的进程正在其中运行的 cpu,并使用结果设置与该 cpu 的关联:

    unsigned mycpu=0;
    if( -1 == getcpu(&mycpu,NULL,NULL) ) {
       // handle error
    }
    

    大概任何现有的 CPU 关联性规则都会被调度程序遵守,因此getcpu() 调用将返回允许进程在其上运行的 CPU。

    亲和力集仍有可能发生变化,但这似乎不太可能发生,并且允许的 CPU 可能会在未来某个时间点受到影响,超出相关进程的控制范围。

    我想您可以检测到sched_setaffinity() 调用中的错误,然后重试该过程,直到 setaffinity 调用正常...

    【讨论】:

    • 使用sched_getcpu() 可能会更好,否则我同意:)
    • 啊酷。我不是内核黑客,但谷歌帮助我伪造它。 :)
    【解决方案2】:

    考虑到进程的亲和掩码随时可能发生变化,可以反复尝试将进程pin到当前CPU上,成功后停止。

    cpu_set_t cpu_set;
    
    int cpu = 0;
    int result = -1;
    
    while (result<0){
    
        cpu = sched_getcpu();
        if (cpu>0){
            CPU_ZERO(&cpu_set);
            CPU_SET(cpu, &cpu_set);
            result = sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2015-08-21
      • 1970-01-01
      • 2017-12-06
      • 1970-01-01
      • 2012-01-09
      • 1970-01-01
      • 1970-01-01
      • 2012-01-10
      • 2010-11-27
      相关资源
      最近更新 更多