最近内核中bad thread wake up performance problem的解决方案与从acpi_idle
切换到intel_idle
cpuidle驱动程序有关,后者是旧内核中使用的驱动程序.遗憾的是,intel_idle
驱动程序忽略了用户对C状态和dances to its own tune状态的BIOS配置.换句话说,即使您完全禁用PC(或服务器)BIOS中的所有C状态,该驱动程序仍会在短暂的不活动期间强制它们打开,除非运行一个全核心消耗的合成基准测试(例如压力测试),否则这种情况几乎总是会发生.在大多数兼容的硬件上,您可以使用精彩的Google i7z tool监控C状态转换,以及与处理器频率相关的其他有用信息.
要查看哪个cpuidle驱动程序当前在您的设置中处于活动状态,只需在/sys/devices/system/cpu
的cpuidle
部分中键入current_driver
文件,如下所示:
cat /sys/devices/system/cpu/cpuidle/current_driver
如果希望现代Linux操作系统具有尽可能低的上下文切换延迟,请添加以下内核 bootstrap 参数以禁用所有这些节能功能:
在Ubuntu12.04上,你可以将它们添加到/etc/default/grub
中的GRUB_CMDLINE_LINUX_DEFAULT
条目中,然后运行update-grub
.要添加的启动参数包括:
intel_idle.max_cstate=0 processor.max_cstate=0 idle=poll
以下是关于三个启动选项的详细信息:
将intel_idle.max_cstate
设置为零将使cpuidle驱动程序恢复为acpi_idle
(至少根据选项的文档),或者完全禁用它.在我的盒子上,它被完全禁用(即,在/sys/devices/system/cpu/cpuidle
中显示current_driver
文件会产生none
的输出).在这种情况下,第二个 bootstrap 选项processor.max_cstate=0
是不必要的.然而,文档中指出,将intel_idle
驱动程序的max_cstate设置为零应该会将操作系统恢复为acpi_idle
驱动程序.因此,为了以防万一,我加入了第二个启动选项.
processor.max_cstate
选项将acpi_idle
驱动程序的最大C状态设置为零,希望也能将其禁用.我没有一个可以在上面测试的系统,因为intel_idle.max_cstate=0
在我可用的所有硬件上完全击败了cpuidle驱动程序.但是,如果您的安装只使用第一个启动选项就将您从intel_idle
恢复到acpi_idle
,请告诉我第二个选项processor.max_cstate
是否执行了注释中记录的操作,以便我更新此答案.
最后,这三个参数中的最后一个,idle=poll
是一个真正的能量猪.它将禁用C1/C1E,这将删除最后剩余的延迟位,但会消耗更多的电量,因此只有在真正必要时才使用该选项.对于大多数人来说,这将是过度的,因为C1*延迟并没有那么大.使用我在原始问题中描述的硬件上运行的测试应用程序,延迟从9us增加到3us.对于对延迟高度敏感的应用程序(如金融交易、高精度遥测/跟踪、高频数据采集等),这无疑是一个显著的减少,但对于绝大多数桌面应用程序来说,这可能不值得遭受电力冲击.唯一可以确定的方法是,对比硬件功耗/热量的实际增加,分析应用程序在性能上的改进,并权衡权衡.
Update:
在使用各种idle=*
个参数进行额外测试后,我发现如果硬件支持,将idle
设置为mwait
是一个更好的主意.似乎MWAIT/MONITOR
指令的使用允许CPU进入C1E,而不会给线程唤醒时间增加任何明显的延迟.使用idle=mwait
,CPU温度会更低(与idle=poll
相比),功耗更低,并且仍然保持轮询空闲循环的出色低延迟.因此,基于这些发现,我更新了针对低CPU线程唤醒延迟的建议 bootstrap 参数集:
intel_idle.max_cstate=0 processor.max_cstate=0 idle=mwait
使用idle=mwait
而不是idle=poll
也可能有助于启动涡轮增压(通过帮助CPU保持低于其TDP[热设计功率])和超线程(对于超线程,MWAIT是不消耗整个物理内核的理想机制,同时避免更高的C状态).然而,这尚未在测试中得到证实,我将继续这样做.
Update 2:
mwait
空闲选项为removed from newer 3.x kernels(感谢用户ck_u的更新).这给我们留下了两个 Select :
idle=halt
-应该和mwait
一样工作,但是测试以确保你的硬件是这样的.HLT
指令几乎相当于状态提示为0的MWAIT
指令.问题在于,中断需要脱离HLT状态,而内存写入(或中断)可以用于脱离MWAIT状态.根据Linux内核在空闲循环中使用的内容,这可能会使MWAIT更加高效.所以,正如我所说,测试/配置文件,看看它是否满足您的延迟需求...
和
idle=poll
- The highest performance option, at the expense of power 和 heat.