Open wutiejun opened 7 years ago
本文档介绍了Kconfig选项和引导参数 减少调度时钟中断的数量,从而提高能量 效率和降低操作系统抖动。 降低操作系统抖动是非常重要的 某些类型的计算密集型高性能计算(HPC) 应用程序和实时应用程序。
管理调度时钟中断有三种主要方式 (也称为“调度时钟滴答”或简称“ticks”):
1.不要忽略调度时钟滴答(CONFIG_HZ_PERIODIC = y或 对于旧的内核,CONFIG_NO_HZ = n)。 你通常会 - 不 - 想选择这个选项。
2.忽略空闲CPU上的调度时钟滴答(CONFIG_NO_HZ_IDLE = y或 CONFIG_NO_HZ = y用于较老的内核)。 这是最常见的 方法,应该是默认的。
3.省略CPU或空闲的调度时钟 只有一个可运行的任务(CONFIG_NO_HZ_FULL = y)。 除非你 正在运行实时应用程序或某些类型的HPC 工作负载通常不需要此选项。
这三种情况在以下三节中进行了说明 第四节是关于区域协调单位具体考虑的第三部分 讨论测试,以及列出已知问题的第五部分和最后一节。
十九世纪九十年代初至二十世纪初的Linux的旧版本 无法省略计划时钟滴答。 事实证明 有些情况下,这种老式的办法仍然是 正确的方法,例如,在繁重的工作负载很多任务 使用短脉冲的CPU,其中非常频繁的空闲 时间段,但是这些空闲时间也很短(几十或 几百微秒)。 对于这些类型的工作负载,调度 时钟中断通常会以任何方式传送,因为在那里 每个CPU经常会有多个可运行的任务。 在这些情况下, 尝试关闭调度时钟中断将不起作用 而不是增加切换到空闲和从空闲的开销 在用户和内核执行之间进行转换。
这种操作模式可以使用CONFIG_HZ_PERIODIC = y(或 对于旧的内核,CONFIG_NO_HZ = n)。
但是,如果您改为长时间闲置的轻型工作负载 时间段,不能省略调度时钟中断将导致 功耗过大 这在电池供电方面特别糟糕 器件,导致极短的电池寿命。 如果你 正在运行轻量级的工作负载,因此您应该阅读以下内容 部分。
另外,如果您正在运行实时工作负载或HPC 工作负载短暂迭代,调度时钟中断可以 降低应用程序性能。 如果这描述你的工作量, 你应该阅读以下两节。
如果CPU空闲,则发送调度时钟几乎没有意义 打断。 毕竟,调度时钟中断的主要目的 是迫使一个忙碌的CPU把注意力转移到多个职责之中, 而空闲的CPU没有任何职责将其注意力转移到其中。
CONFIG_NO_HZ_IDLE = y Kconfig选项使内核避免发送 调度时钟中断到空闲CPU,这是至关重要的 无论是电池供电设备还是高度虚拟化的大型机。 运行CONFIG_HZ_PERIODIC = y内核的电池供电设备 很快耗尽电池,容易2-3倍的速度 相同的设备运行CONFIG_NO_HZ_IDLE = y内核。 大型机运行 1,500个操作系统实例可能会发现其CPU时间的一半被消耗 不必要的调度时钟中断。 在这些情况下,那里 是避免发送调度时钟中断的强烈动机 空闲CPU。 也就是说,dyntick-idle模式不是免费的:
1.它增加了在路径上执行的指令数量 到和从空闲循环。
2.在许多架构上,dyntick-idle模式也增加了 数量昂贵的时钟重编程操作。
因此,经常具有积极的实时响应约束的系统 运行CONFIG_HZ_PERIODIC = y内核(或旧的内核使用CONFIG_NO_HZ = n) 以避免从空闲转移延迟退化。
据说没有接收到调度时钟中断的空闲CPU “dyntick-idle”,“dyntick-idle mode”,“nohz mode”或“running 本文档的其余部分将使用“dyntick-idle模式”。
还有一个可以用于禁用的引导参数“nohz =” 通过指定“nohz = off”,CONFIG_NO_HZ_IDLE = y内核中的dyntick-idle模式。 默认情况下,CONFIG_NO_HZ_IDLE = y内核使用“nohz = on”启动,启用 dyntick-idle模式。
如果一个CPU只有一个可运行的任务,发送它就没什么意义了 一个调度时钟中断,因为没有其他任务切换到。 请注意,省略只有一个可运行的CPU的调度时钟滴答 任务意味着也省略了空闲的CPU。
ONFIG_NO_HZ_FULL = y Kconfig选项使内核避免 通过单个可运行的任务向CPU发送调度时钟中断, 并且这样的CPU被称为“自适应蜱CPU”。这个很重要 对于具有激进的实时响应约束的应用程序,因为 它允许他们最大限度地改善最坏情况的响应时间 调度时钟中断的持续时间。这也很重要 计算密集型短周期工作负载:如果有任何CPU 在给定的迭代期间延迟,所有其他CPU将被强制执行 延迟CPU完成时等待空闲。因此,延迟被乘以 比CPU少一个。在这些情况下,有 再次强烈的动机是避免发送调度时钟中断。
默认情况下,没有CPU将是自适应刻度CPU。 “nohz_full =” boot参数指定自适应ticks CPU。例如, “nohz_full = 1,6-8”表示CPU 1,6,7和8是自适应蜱 的CPU。请注意,您禁止将所有CPU标记为 自适应校验CPU:至少有一个非自适应校验CPU必须保留 在线处理计时任务,以确保系统 像gettimeofday()这样的调用在自适应刻度CPU上返回准确的值。 (这不是CONFIG_NO_HZ_IDLE = y的问题,因为没有运行 用户进程观察时钟频率的轻微漂移) 启动CPU被禁止进入自适应蜱模式。指定一个 包含引导CPU的“nohz_full =”掩码将导致启动时间 错误消息,引导CPU将从掩码中删除。注意 这意味着您的系统必须至少有两个CPU CONFIG_NO_HZ_FULL = y为您做任何事情。
或者,CONFIG_NO_HZ_FULL_ALL = y Kconfig参数指定 除了引导CPU之外的所有CPU都是自适应校验CPU。这个 Kconfig参数将被“nohz_full =”引导参数覆盖, 所以如果CONFIG_NO_HZ_FULL_ALL = y Kconfig参数和 指定了“nohz_full = 1”引导参数,引导参数将会启动 只有CPU 1将是一个自适应ticks CPU。
最后,自适应剔除CPU必须卸载其RCU回调。 这在下面的“RCU含义”部分中有所介绍。
通常,CPU尽可能长时间保持自适应模式。 特别是转换到内核模式不会自动更改 的模式。相反,只有在需要的情况下,CPU才会退出自适应模式, 例如,如果该CPU排队RCU回调。
就像使用dyntick-idle模式一样,自适应嘀嗒模式的好处是 不来免费:
2.由于用户/内核转换稍微更昂贵 需要通知内核子系统(如RCU) 模式的变化。
4.如果有更多的perf事件挂起比硬件可以 容纳,通常是循环收集 所有这些都随着时间的推移。自适应模式可能会阻止这种情况 轮回发生。这可能会被修正 防止CPU等待大量的perf事件 进入自适应模式。
可以计算自适应刻度CPU的调度器统计信息 略微不同于非自适应刻度的CPU。 这可能反过来会扰乱实时任务的负载平衡。
LB_BIAS调度程序功能通过自适应跳数禁用。
虽然随着时间的推移有所改进,但是自适应蜱是相当的 可用于许多类型的实时和计算密集型应用程序。 然而,上面列出的缺点意味着自适应蜱不应该 (还)默认启用。
有些情况下无法使用空闲CPU 最多输入dyntick-idle模式或自适应tick模式 通常是当该CPU具有挂起的RCU回调时。
可以使用CONFIG_RCU_FAST_NO_HZ = y Kconfig选项来引起这种CPU 无论如何,进入dyntick-idle模式或自适应tick模式。在这种情况下, 一个定时器将每四个jiffies唤醒这些CPU,以确保 RCU回调被及时处理。
另一种方法是将RCU回调处理卸载到“rcuo”kthreads 使用CONFIG_RCU_NOCB_CPU = y Kconfig选项。具体的CPU到 卸载可以通过以下几种方式进行选择:
三个互斥的Kconfig选项之一指定一个 构建时间默认为CPU卸载:
一个。 CONFIG_RCU_NOCB_CPU_NONE = y Kconfig选项生成 没有CPU被卸载。
湾CONFIG_RCU_NOCB_CPU_ZERO = y Kconfig选项导致 CPU 0被卸载。
C。 CONFIG_RCU_NOCB_CPU_ALL = y Kconfig选项导致所有 CPU被卸载。请注意,回调将是 卸载到“rcuo”kthreads,那些那些kthreads 实际上会运行在某些CPU上。但是,这种方法 对精确的CPU进行了细粒度的控制 回调运行,以及其调度优先级 (包括SCHED_OTHER的默认值),并进一步 允许这种控制在运行时动态变化。
2.“rcu_nocbs =”内核引导参数,以逗号分隔 CPU和CPU范围的列表,例如“1,3-5”选择CPU 1, 3,4和5.指定的CPU将被卸载 任何指定为由CONFIG_RCU_NOCB_CPU_ZERO = y卸载的CPU CONFIG_RCU_NOCB_CPU_ALL = Y。这意味着“rcu_nocbs =”启动 参数对于使用RCU_NOCB_CPU_ALL = y构建的内核没有影响。
卸载的CPU将不会排队RCU回调,因此RCU 从不防止卸载的CPU进入dyntick-idle模式 或自适应刻度模式。也就是说,请注意,由用户空间决定 如果需要,将“rcuo”kthreads引导到特定的CPU。否则, 调度程序将决定运行它们的位置,这可能是也可能不是 你希望他们跑的地方
因此,您可以启用本文档中描述的所有OS-jitter功能, 但是您的工作负载的行为看不到任何改变。这是因为吗 您的工作负载不受OS抖动影响,或者是因为 还有其他的事情呢?本节有助于回答这个问题 通过提供一个简单的OS-jitter测试套件,可以在分支机构上使用 掌握以下git存档:
混帐://git.kernel.org/pub/scm/linux/kernel/git/frederic/dynticks-testing.git
克隆此存档并按照README文件中的说明进行操作。 此测试程序将产生一个可以让您进行评估的痕迹 无论您是否成功从系统中删除操作系统抖动。 如果此跟踪显示您已经删除OS抖动 可能的话,你可以得出结论,你的工作量不是全部 对OS抖动敏感。
注意:此测试要求您的系统至少有两个CPU。 我们目前没有一种从单CPU消除操作系统抖动的好办法 系统。
o Dyntick-idle使转换过渡到空闲状态。 在实践中,除了最多,这还没有成为问题 积极的实时工作负载,可以选择禁用 dyntick-idle模式,它们大多数都采用的选项。然而, 一些工作量无疑将要使用自适应蜱 消除调度时钟中断延迟。这里有一些 这些工作负载的选项:
一个。使用用户空间中的PMQOS通知内核 延迟要求(首选)。
湾在x86系统上,使用“idle = mwait”引导参数。
C。在x86系统上,使用“intel_idle.max_cstate =”来限制 `最大C状态深度。
天。在x86系统上,使用“idle = poll”引导参数。 但是请注意,使用此参数可能会导致 你的CPU过热,这可能会导致热调节 降低延迟 - 而且这种退化可以 甚至比愚蠢的更糟糕。此外, 此参数有效地禁用了英特尔的Turbo模式 CPU可以显着降低最大性能。
o Adaptive-ticks会稍微减慢用户/内核转换。 这不会是计算密集型的问题 工作量很少,这些过渡很少。仔细的基准测试 将需要确定是否有其他工作负载 受此影响显着影响。
o自适应蜱不做任何事情,除非只有一个 给定CPU的可运行任务,即使有一个数字 在其他情况下,调度时钟tick不是 需要。给出一个例子,考虑一个有一个的CPU 可运行的高优先级SCHED_FIFO任务和任意数 的低优先级SCHED_OTHER任务。在这种情况下,CPU是 需要运行SCHED_FIFO任务,直到它阻塞或 一些其他较高优先级的任务唤醒(或分配给) 这个CPU,所以发送调度时钟没有意义 中断到这个CPU。但是,目前的实现 然而将调度时钟中断发送到具有a的CPU 单次运行SCHED_FIFO任务和多个可运行SCHED_OTHER 即使这些中断是不必要的。
即使在给定的CPU上有多个可运行的任务, 中断CPU直到目前为止都没有什么意义 运行任务的时间片过期,几乎总是这样 比下一个调度时钟中断的时间长。
更好地处理这些情况是未来的工作。
o需要重新启动才能重新配置自适应空闲和RCU 回调卸载可以提供运行时重新配置 然而,如果需要,由于重新配置RCU的复杂性 运行时,需要一个非常好的理由。 特别是因为你有直接的选择 只需从所有CPU卸载RCU回调并固定它们 当你想要他们被固定在哪里。
o需要额外的配置来处理其他来源 OS抖动,包括中断和系统实用工作 和流程。此配置通常涉及绑定 特定CPU的中断和任务。
o某些OS抖动来源目前只能被消除 限制工作量。例如,消除的唯一方法 由于全局TLB下降引起的操作系统抖动是为了避免重新映射 操作(如内核模块卸载操作)那样 导致这些击倒。另一个例子,页面错误 和TLB错失可以减少(在某些情况下被消除) 使用庞大的页面和限制使用的内存量 通过应用程序。预设工作组也可以 有用的,特别是当结合mlock()和mlockall() 系统调用
o除非所有CPU都处于空闲状态,否则至少有一个CPU必须保留 调度时钟中断为了支持准确 报时。
o如果可能有一些自适应蜱的CPU,那么 将至少有一个CPU保持调度时钟中断 即使所有CPU都处于空闲状态。
更好地处理这种情况正在进行中。
o某些流程处理操作仍然偶尔需要 调度时钟滴答。这些操作包括计算CPU 加载,维护平均,计算CFS实体vruntime, 计算avenrun,并执行负载平衡。他们是 目前通过调度时钟每秒钟调整 或者。正在进行的工作将消除对这些的需求 不频繁的调度 - 时钟滴答。
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/timers/NO_HZ.txt