是否可以增加 Linux CPU 调度程序允许进程运行的时间片长度?我怎么能这样做呢?
背景知识
这个问题询问如何减少内核强制在同一 CPU 上运行的不同进程之间切换的频率。这就是被描述为“抢占式多任务”的内核功能。此功能通常很好,因为它可以阻止单个进程占用 CPU 并使系统完全无响应。然而在进程之间切换有成本,因此需要权衡。
如果您有一个进程使用它可以获得的所有 CPU 时间,而另一个进程与用户交互,那么更频繁地切换可以减少延迟响应。
如果您有两个进程使用了它们可以获得的所有 CPU 时间,那么较低的切换频率可以让它们在同一时间内完成更多的工作。
动机
我根据我对这个问题的初步反应发布此内容 如何改变Linux上下文切换频率?
我个人不想改变时间片。然而我依稀记得这是一个带有CONFIG_HZ
构建时选项的东西。所以我想知道现在的情况是怎样的。 CPU调度程序时间片仍然基于 吗CONFIG_HZ
?
此外,在实践中,构建时调整非常有限。对于 Linux 发行版来说,如果每个 CPU 架构都有一个内核,并允许在运行时或至少在启动时对其进行配置,那就更实用了。如果调整时间片仍然相关,是否有一种新方法不会在构建时锁定它?
答案1
对于大多数 RHEL7 服务器,RedHat 建议增加到sched_min_granularity_ns
10 毫秒和sched_wakeup_granularity_ns
15 毫秒。 (来源。从技术上讲,这个链接说的是 10 μs,这会小 1000 倍。这是一个错误)。
我们可以尝试更详细地理解这个建议。
增加 sched_min_grainarity_ns
在当前的 Linux 内核上,CPU 时间片由 CFS(完全公平调度程序)分配给任务。可以使用一些sysctl
设置来调整 CFS。
kernel.sched_min_granularity_ns
kernel.sched_latency_ns
kernel.sched_wakeup_granularity_ns
您可以临时设置 sysctl,直到下次重新启动为止,或者在每次启动时应用的配置文件中永久设置。要了解如何应用此类设置,请查找“sysctl”或阅读简短介绍这里。
sched_min_granularity_ns
是最显眼的设定。在原来的计划设计-CFS.txt这被描述为唯一的“可调”设置,“将调度程序从‘桌面’(低延迟)调整到‘服务器’(良好的批处理)工作负载。”
换句话说,我们可以更改此设置以减少上下文切换的开销,从而以响应能力(“延迟”)为代价提高吞吐量。
我认为这个 CFS 设置模仿了之前的构建时设置,配置_HZ。在 CFS 代码的第一个版本中,默认值为 1 毫秒,相当于“桌面”使用的 1000 Hz。 CONFIG_HZ 其他支持的值为 250 Hz(默认值),“服务器”端为 100 Hz。当在非常慢的 CPU 上运行 Linux 时,100 Hz 也很有用,这是给出的原因之一当 CONFIG_HZ 首次作为 X86 上的构建设置添加时。
尝试将此值更改为 10 ms(即 100 Hz)并测量结果听起来很合理。请记住 sysctl 的测量单位为纳秒。 1 毫秒 = 1,000,000 纳秒。
我们可以看到这种对“服务器”的老式调整在 2011 年仍然非常重要,对于一些高负载基准测试中的吞吐量而言:https://events.static.linuxfound.org/slides/2011/linuxcon/lcna2011_rajan.pdf
也许还有其他一些设置
上面三个设置的默认值看起来比较接近。这让我想要让事情变得简单,并将它们全部乘以相同的因子:-)。但我试图研究这一点,似乎一些更具体的调整也可能相关,因为您正在调整吞吐量。
sched_wakeup_granularity_ns
涉及“唤醒抢占”。即它控制由事件唤醒的任务何时能够立即抢占当前正在运行的进程。 2011 年的幻灯片也显示了此设置的性能差异。
另请参阅此中的“禁用 WAKEUP_PREEMPT”2010 年 IBM 引用,这表明“对于某些工作负载”,这种默认启用的功能“可能会消耗几个百分点的 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 之前的内核上获得的吞吐量)。
- ”两个必要的内核调整" - PostgreSQL 邮件列表上的讨论。
- ”请增加虚拟主机配置文件中的 kernel.sched_migration_cost“ - 红帽错误 969491。
忽略CONFIG_HZ
我认为您不必担心CONFIG_HZ
设置的内容。我的理解是,假设您有合理的计时器硬件,它与当前内核无关。也可以看看commit 8f4d37ec073c,“sched:高分辨率抢占勾选”,通过有关更改的线程中的此评论找到:https://lwn.net/Articles/549754/。
(如果您查看提交,我不会担心这SCHED_HRTICK
取决于X86
。该要求似乎在最近的一些提交中已被删除)。
答案2
看来您需要批处理调度程序:用于schedtool
在不同的调度程序下运行进程。例如schedtool -B «Command to be run in batch mode»
答案3
(这应该是评论,但有点长)
不太频繁的上下文切换应该能够允许更高的吞吐量
仅当内核抢占任务并将它们放回运行队列时。
一般来说,这种情况发生时应该是罕见且短暂的。通常任务会显式地让出等待某事发生。您会看到任何好处的唯一时间是负载始终高于 CPU 数量的情况。但您也将面临失去响应能力的风险。