为什么使用taskset在一组隔离内核上运行multithreadingLinux程序会导致所有线程在一个内核上运行?

期望的行为:在已使用isolcpus隔离的一组内核上运行multithreadingLinux程序。

下面是一个我们可以用作multithreading程序的小程序:

 #include <stdio.h> #include <pthread.h> #include <err.h> #include <unistd.h> #include <stdlib.h> #define NTHR 16 #define TIME 60 * 5 void * do_stuff(void *arg) { int i = 0; (void) arg; while (1) { i += i; usleep(10000); /* dont dominate CPU */ } } int main(void) { pthread_t threads[NTHR]; int rv, i; for (i = 0; i < NTHR; i++) { rv = pthread_create(&threads[i], NULL, do_stuff, NULL); if (rv) { perror("pthread_create"); return (EXIT_FAILURE); } } sleep(TIME); exit(EXIT_SUCCESS); } 

如果我在没有隔离CPU的内核上编译和运行这个线程,那么这些线程就分布在我的4个CPU上。 好!

现在,如果我添加isolcpus=2,3到内核​​命令行并重新启动:

  • 在没有taskset的情况下运行程序,可以在线程0和线程1上分配线程。由于默认关联掩码现在排除了线程2和3,因此可以这样做。
  • 使用taskset -c 0,1运行具有相同的效果。 好。
  • 使用taskset -c 2,3运行会导致所有线程进入相同的核心(核心2或3)。 这是不希望的。 线程应该分布在核心2和3上。

这篇文章描述了一个类似的问题(虽然给出的例子离pthreads API更远)。 OP很高兴通过使用不同的调度器来解决这个问题。 但我不确定这是否适合我的使用情况。

有没有办法让线程分布在使用默认调度程序隔离的核心?

这是我应该报告的内核错误吗?

编辑

如果使用像fifo调度程序这样的实时调度程序,确实会发生这种情况。 有关详情,请参阅man schedman chrt

从Linux内核参数Doc:

此选项可用于指定一个或多个CPU与一般SMP平衡和调度算法隔离。

所以这个选项可以有效地防止调度程序从一个核心向另一个较小的竞争核心(SMP平衡)进行线程迁移。 由于典型的isolcpus与pthread亲和力控制一起使用,通过CPU布局知识来固定线程以获得可预测的性能。

https://www.kernel.org/doc/Documentation/kernel-parameters.txt

– 编辑 –

好吧,我明白你为什么困惑。 是的,我个人认为这个选项会有一致的行为。 问题出在两个函数select_task_rq_fair和select_task_rq_rt,它们负责选择新的run_queue(实质上是选择运行哪个next_cpu)。 我做了两个函数的快速跟踪(Systemtap),对于CFS,它会始终返回面具中相同的第一个核心; 对于RT,它会返回其他核心。 我没有机会查看每个选择算法中的逻辑,但是您可以发送电子邮件给Linux devel邮件列表中的维护人员以进行修复。