Linux CFS 如何在 2018 4.9 内核中公平地调度进程与线程?

Linux CFS 如何在 2018 4.9 内核中公平地调度进程与线程?

Linux 调度程序不断发展:当今内核如何调度进程与线程?我需要自动分组吗?

之前类似的堆栈溢出问题已经很多年了并且可能已经过时了。

我相信2018年的默认值是完全公平的调度器慢性疲劳综合症) 而不是 O(1) 或其他调度程序。

对于 Linux,一些文档提到了操作系统的杂耍任务漠不关心地代表着一个过程或一个线进程的区别,或者没有明确区分,尽管它对于调度至关重要。

为了清楚起见,进程运行一个程序,并且当它是多线程时可能会产生 1 个或多个线程。对我来说,区别在于进程的所有线程都使用相同的虚拟地址空间。然而对于 CPU 上的调度来说,这种区别是无关紧要的。

如果我运行 P 个进程,每个进程具有不同的 Tp 线程数:

  • 流程公平:如何保证具有多个线程的进程不会耗尽所有资源并压倒仅具有 1 个线程的进程?形式化的公平调度意味着:进程 P 应该获得 1/Pth 的 CPU 资源,并将该 1/Pth 平均分配给 P 的每个线程 1/(Pth*Tp)。这是 CFS 默认保证的吗?
  • 我需要自动分组吗?自动分组允许流程将任务组安排在一起。默认情况下有一组,但如果您旋转第二个线程,它将获得 1/2 的 CPU,旋转 10 个,每组线程将获得 1/10。简单(参见帮派调度)。
  • 多核:我不太关心多核负载平衡和核之间的进程迁移的考虑,从而使答案变得混乱。

实验结果:CFS 似乎在进程之间是公平的。

我尝试在 4.9.27 上监视小进程的运行时间与具有多个线程的长时间运行进程的运行时间。看来我的内核上的调度程序是按进程调度的,而不是按线程调度的。所以小进程受到了公平对待,得到了50%的CPU。当我使用 2 个长时间运行的进程时,我得到了 33%。减速分别为 2.2 倍和 3.4 倍。

这个内核似乎没有编译自动组; setid() 有效,但似乎什么也没做,并且 /proc/*/autogroup 不存在,因此尝试在 CFS 时使用 autogroup似乎做正确的事是一项昂贵的事业。然而,其他一些数据点似乎表明有时该行为对进程不公平。

附带问题

有没有一种技巧可以保证一个进程比所有其他进程运行得更频繁?我认为由于 LD_LIBRARY_PATH 的使用,我无法将其提升为实时。即便如此,我怀疑因为它读取 /proc 来监视系统,当系统严重超出容量时,它有时仍然会严重延迟。

谢谢!

答案1

回答有关在 SCHED_OTHER 调度策略下在同一核心上同时运行的 cpu 绑定任务(因为公平性考虑比 io 绑定任务更容易观察)(因为它是唯一真正的分时调度策略)


进程(按照从 UNIX 系统继承的术语的含义)不是调度实体。只有线程是,并且 CFS 会调度它们,而不管任何父级考虑因素。引用 man sched :

   The thread to run is chosen from the static priority 0 list based
   on a dynamic priority that is determined only inside this list.
   The dynamic priority is based on the nice value (see below) and
   is increased for each time quantum the thread is ready to run,
   but denied to run by the scheduler.  This ensures fair progress
   among all SCHED_OTHER threads.

因此,无论什么多线程应用程序与在同一内核上同时运行的任何单线程应用程序相比,全局获得更多的 CPU 功率,正如多次证明的那样(从§3开始阅读)时期。1


Linux 内核控制组支持:

如果配置充分(CONFIG_CROUPS=y),内核提供将任务分组到...的功能,只需猜测:任务组! :-P 顺便让其他程序(填充数据结构)(例如内存控制器,当然还有 CFS)了解这些分组。

然后,如果配置充分(CONFIG_CGROUP_SCHED=y),CFS 将控制 CPU 带宽分配,以确保所有现有任务组之间的公平性。2

在这种情况下(CONFIG_CROUPS=y && CONFIG_CGROUP_SCHED=y),我们可以重新表述上面的语句:

无论什么多线程应用程序将要与任何单线程应用程序相比,全局获得更多的 CPU 功率属于同一任务组但不超过分配给任何其他共存任务组的 CPU 功率。3


自动分组

因为对任务进行分组需要用户明确操作(如果不是早期特定的系统配置),并且大多数常见桌面用户不想为此操心,但仍希望他们的桌面保持响应,无论用户在其自己的会话中执行什么操作,内核都提供了在每个会话基础上自动创建和填充任务组的功能。
如果设置了 CONFIG_SCHED_AUTOGROUP,则每个会话都会创建一个任务组,并且在此会话中启动的所有任务都将属于该任务组。4


你的附带问题(“是否有一种技巧可以保证一个进程比所有其他进程运行得更频繁?”)似乎几乎不合理,因为用于调度 SCHED_NORMAL 线程的算法是确定性的,并且将确保尽可能最好的规律性。在这种情况下,你不能指望达到“更有规律性”,甚至更少规律性对于某些线程,除非希望……中断规律性
不过,您可能希望或多或少地调度线程。在这种情况下,只需调整它们的好值即可。


1:恩惠之言:如果没有任何额外的照顾,不要指望享受在构建 chromium -j64 时启动的视频:-P

2:不!与配置标签所建议的相反,CFS 不会开始调度任务组。它仍然会调度线程,但在选择时会考虑分配给属于同一任务组的每个其他线程的 cpu 时间总和;确保它不超过分配给属于其他现有任务组的线程的总时间。

3:恩惠之言:如果您特别注意确保您的 chromium 版本和视频播放器不属于同一任务组,那么即使在核心 2 上,您也可能会喜欢与 make -j64 并行运行的视频。如果您不这样做,那么您可能会喜欢与 make -j64 并行运行的视频。 …转到 1 :-P

4:恩惠之言:如果您只是小心地在两个不同的会话中启动您的 chromium 版本和您的播放器,那么就尽情享受吧。如果您将它们启动到同一个会话中,那么...转到 1 :-P

相关内容