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

Dan*_*ong 5 linux process scheduling

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

以前类似的堆栈溢出问题已经有很多年了,可能已经过时了。

我相信 2018 年的默认值是完全公平调度程序( CFS ),而不是 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 倍。

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

副题

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

谢谢!

MC6*_*020 1

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

\n
\n

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

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

因此,任何多线程应用程序都可以比在同一内核上同时运行的任何单线程应用程序获得更多的 CPU 功率,正如多次证明的那样(从 \xc2\xa73 读取)1

\n
\n

Linux 内核控制组支持:

\n

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

\n

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

\n

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

\n

无论哪种多线程应用程序都将在全局范围内获得比属于同一任务组的任何单线程应用程序更多的 CPU 功率,但不会超过分配给任何其他共存任务组的 CPU 功率。3

\n
\n

自动分组

\n

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

\n
\n

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

\n
\n

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

\n

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

\n

3 : verbi gratia : 如果您特别注意确保您的 chromium 构建和您的视频播放器不属于同一任务组,那么您可能会喜欢与 make -j64 并行运行的视频,即使是在核心 2 上。如果您然后不要\xe2\x80\xa6 转到 1 :-P

\n

4:verbi gratia:如果您只是小心地在两个不同的会话中启动您的 chromium 版本和您的播放器,那么就尽情享受吧。如果您将它们启动到同一会话中,则 \xe2\x80\xa6 转到 1 :-P

\n