是否可以增加 Linux CPU 调度程序允许进程运行的时间片长度?我怎么能这样做?
背景知识
这个问题询问如何减少内核强制在同一 CPU 上运行的不同进程之间切换的频率。这是被描述为“抢先式多任务”的内核特性。此功能通常很好,因为它可以阻止单个进程占用 CPU 并使系统完全无响应。然而,进程之间的切换是有成本的,因此需要权衡。
如果您有一个进程使用它可以获得的所有 CPU 时间,而另一个进程与用户交互,那么更频繁地切换可以减少延迟响应。
如果您有两个进程使用了它们可以获得的所有 CPU 时间,那么减少切换频率可以让它们同时完成更多的工作。
动机
我根据我对 如何更改 Linux 上下文切换频率的问题的最初反应发布此消息?
我个人不想更改时间片。但是,我隐约记得这是一件事,带有CONFIG_HZ
构建时选项。所以我想知道现在的情况如何。CPU 调度程序时间片是否仍基于CONFIG_HZ
?
此外,在实践中,构建时调整非常有限。对于 Linux 发行版,如果每个 CPU 架构可以有一个内核,并允许在运行时或至少在启动时进行配置,则更为实用。如果调整时间片仍然相关,是否有一种新方法不会在构建时将其锁定?
对于大多数 RHEL7 服务器,RedHat 建议增加到
sched_min_granularity_ns
10ms 和sched_wakeup_granularity_ns
15ms。(来源。从技术上讲,此链接说 10 μs,这将小 1000 倍。这是一个错误)。我们可以尝试更详细地理解这个建议。
增加 sched_min_granularity_ns
在当前的 Linux 内核上,CPU 时间片由完全公平调度程序 CFS 分配给任务。CFS 可以使用一些
sysctl
设置进行调整。kernel.sched_min_granularity_ns
kernel.sched_latency_ns
kernel.sched_wakeup_granularity_ns
您可以在下次重新启动之前临时设置 sysctl,或者在每次启动时应用的配置文件中永久设置。要了解如何应用此类设置,请查找“sysctl”或阅读此处的简短介绍。
sched_min_granularity_ns
是最突出的设置。在最初的sched-design-CFS.txt中,这被描述为唯一的“可调”设置,“将调度程序从‘桌面’(低延迟)调整到‘服务器’(良好的批处理)工作负载。”换句话说,我们可以更改此设置以减少上下文切换的开销,从而以响应性(“延迟”)为代价提高吞吐量。
我认为这个 CFS 设置模仿了之前的构建时设置CONFIG_HZ。在 CFS 代码的第一个版本中,默认值为 1 ms,相当于“桌面”使用的 1000 Hz。其他支持的 CONFIG_HZ 值为 250 Hz(默认值),“服务器”端为 100 Hz。在非常慢的 CPU 上运行 Linux 时,100 Hz 也很有用,这是首次在 X86 上添加 CONFIG_HZ 作为构建设置时给出的原因之一。
尝试将此值更改为 10 毫秒(即 100 赫兹)并测量结果听起来很合理。请记住 sysctls 以ns为单位。1 毫秒 = 1,000,000 纳秒。
我们可以看到这种老式的“服务器”调优在 2011 年对于一些高负载基准测试的吞吐量仍然非常重要:https ://events.static.linuxfound.org/slides/2011/linuxcon/lcna2011_rajan.pdf
也许还有其他一些设置
上面三个设置的默认值看起来比较接近。这让我想保持简单,并将它们全部乘以相同的因子:-)。但我试图研究这一点,似乎一些更具体的调整也可能是相关的,因为您正在调整吞吐量。
sched_wakeup_granularity_ns
涉及“唤醒抢占”。即,它控制由事件唤醒的任务何时能够立即抢占当前正在运行的进程。2011 年的幻灯片也显示了此设置的性能差异。另请参阅IBM 2010 年参考资料中的“禁用 WAKEUP_PREEMPT” ,这表明“对于某些工作负载”,此默认启用功能“可能会花费百分之几的 CPU 利用率”。
SUSE Linux 有一个文档建议将其设置为大于一半
sched_latency_ns
将有效地禁用唤醒抢占,然后“短占空比任务将无法有效地与 CPU hogs 竞争”。SUSE 文档还建议对其他设置进行一些更详细的描述。不过,您绝对应该检查您自己系统上的当前默认值。例如,我系统上的默认值似乎与 SUSE 文档所说的略有不同。
https://www.suse.com/documentation/opensuse121/book_tuning/data/sec_tuning_taskscheduler_cfs.html
如果您尝试使用这些调度变量中的任何一个,我认为您还应该知道所有三个都按 CPU 数量的 1+log_2 进行缩放(乘以)。可以使用 禁用此缩放
kernel.sched_tunable_scaling
。我可能会遗漏一些东西,但这似乎令人惊讶,例如,如果您正在考虑提供交互式应用程序并以/接近满负荷运行的服务器的响应能力,以及该响应能力将如何随每台服务器的 CPU 数量而变化。建议您的工作负载是否有大量线程/进程
我还遇到了一个 2013 年的建议,对于其他一些设置,如果您的工作负载具有大量线程,这可能会获得显着的吞吐量。(或者更准确地说,它重新获得了他们在 CFS 之前的内核上获得的吞吐量)。
忽视
CONFIG_HZ
我认为您不必担心
CONFIG_HZ
设置的内容。我的理解是它与当前内核无关,假设您有合理的计时器硬件。另请参阅提交 8f4d37ec073c,“sched: high-res preemption tick”,通过此评论在有关更改的线程中找到:https ://lwn.net/Articles/549754/ 。(如果您查看提交,我不会担心这
SCHED_HRTICK
取决于X86
。该要求似乎已在最近的一些提交中被删除)。看起来您需要批处理调度程序:用于
schedtool
在不同的调度程序下运行进程。例如schedtool -B «Command to be run in batch mode»
(这应该是一个评论,但它有点长)
仅当内核抢占任务并将它们放回运行队列时。
通常,当这种情况发生时,它应该既不频繁又短暂。通常任务会显式地让步,等待某事发生。唯一一次你会看到任何好处是负载始终高于 CPU 的数量。但您也将面临失去响应能力的风险。