【问题标题】:Pinning a large number of threads to a single CPU causes utilization spike on all cores将大量线程固定到单个 CPU 会导致所有内核的利用率飙升
【发布时间】:2018-08-17 10:16:42
【问题描述】:

我编写了一个小测试程序,它生成大量线程(在我的情况下,在具有 4 个内核的计算机上为 32 个线程)并使用 pthread_setaffinity_np 系统调用将它们全部固定到一个内核。

这些线程在循环中运行,它们通过标准输出报告sched_getcpu 调用的结果,然后休眠一小段时间。我想看到的是,操作系统如何严格遵守用户的线程固定设置(即使它们在我的情况下没有意义)。 所有线程报告都在我将它们固定到的核心上运行,这是我所期望的。

但是,我注意到,当程序运行时,所有 4 个内核的 cpu 利用率都在 100% 左右(通常在 0% 到 25% 之间)。有人能告诉我为什么会这样吗? 我本来希望固定核心上的利用率最大,而其他核心上的利用率可能会更高一些以进行补偿。

如有必要,我可以附加我的代码,但我认为它非常简单,因此并不是真正必要的。我在一台装有 Ubuntu 18.04 的相当旧的 PC 上进行了测试。

更新

#define _GNU_SOURCE

#include <assert.h>
#include <pthread.h>
#include <sched.h>
#include <stdio.h>
#include <unistd.h>

#define THREADS 32
#define PINNED 3
#define MINUTE 60
#define MILLISEC 1000

void thread_main(int id);

int main(int argc, char** argv) {
    int i;
    pthread_t pthreads[THREADS];

    printf("%d threads will be pinned to cpu %d\n", THREADS, PINNED);

    for (i = 0; i < THREADS; ++i) {
        pthread_create(&pthreads[i], NULL, &thread_main, i);
    }

    sleep(MINUTE);

    return 0;
}

void thread_main(int id) {
    printf("thread %d: inititally running on cpu %d\n", id, sched_getcpu());

    pthread_t pthread = pthread_self();
    cpu_set_t cpu_set;

    CPU_ZERO(&cpu_set);
    CPU_SET(PINNED, &cpu_set);

    assert(0 == pthread_setaffinity_np(pthread, sizeof(cpu_set_t), &cpu_set));

    while (1) {
        printf("thread %d: running on cpu %d\n", id, sched_getcpu());
        //usleep(MILLISEC);
    }
}

当我关闭所有后台活动时,利用率并不是 100%,但肯定会在很大程度上影响所有 4 个核心。

【问题讨论】:

  • 我们需要查看代码,根据您的描述,这不应该发生,所以代码可能有错误。
  • 看起来线程 printf 永远以 100% CPU 输出到标准输出?你让他们在哪里睡觉?如果您不这样做,还有什么可期待的?
  • 我只注释掉了usleep进行测试,抱歉。我的问题是所有 CPU 都会出现峰值,尽管所有线程似乎只在一个 cpu 上运行。
  • 你绝对应该assert(/* here */)中放入any副作用的东西,因为当NDEBUG被定义时,你的assertions将被剥夺……逻辑也将被剥夺。我建议像int fubar = pthread_setaffinity_np(...); assert(!fubar);...
  • 如果您在伪终端中运行这些,那么另一个进程正在接收所有 printf 输出并对其进行处理,这也需要 CPU 时间。该过程(您的终端,也可能是 Xorg)将大量出现在配置文件中。考虑到以图形方式呈现文本输出将比生成它的printf() 占用更多 CPU。尝试运行您的测试过程,并将输出重定向到/dev/null

标签: c linux multithreading pthreads affinity


【解决方案1】:

@caf

如果您在伪终端中运行这些,那么另一个进程正在接收所有的 printf 输出并对其进行处理,这也需要 CPU 时间。那个过程 (您的终端,也可能是 Xorg)将大量出现在配置文件中。考虑 > 以图形方式呈现文本输出将比生成它的 printf() 占用更多 CPU。尝试运行您的测试过程,并将输出重定向到 /dev/null。

这是正确答案,谢谢。

将输出定向到/dev/null 时,CPU 使用率峰值仅限于将所有线程固定到它的 CPU。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    • 2012-10-30
    • 2014-10-02
    • 1970-01-01
    • 2020-05-01
    • 1970-01-01
    • 2012-03-19
    相关资源
    最近更新 更多