为什么操作系统可能会忽略 BIOS 设置?
- 操作系统可能会根据正在使用的空闲驱动程序忽略 BIOS 设置。
- 如果使用 intel_idle(intel 机器上的默认值),操作系统可以忽略 ACPI 和 BIOS 设置,例如:驱动程序可以重新启用 C 状态。
- 如果禁用 intel_idle 并使用较旧的 acpi_idle 驱动程序,操作系统应遵循 BIOS 设置。
可以通过以下方式禁用 intel_idle 驱动程序:
passing intel_idle.max_cstate=0 to kernel boot command line or passing idle=* (where * can be e.g. poll, for example:idle=poll)
重要说明:确保处理器支持 acpi 驱动程序,否则我们不应更改驱动程序。
CPU 允许的最大 C 状态是多少?
如上表所示,我们有多个 CPU c 状态,但根据延迟值和 GRUB 中提供的其他 max_cstate 值,任何处理器允许的最大 c 状态可能会有所不同。
下面的文件应该给出你节点的值
# cat /sys/module/intel_idle/parameters/max_cstate 9
什么是 C 状态、cstate 或者 C 模式?
CPU 有多种电源模式,根据它们当前的使用情况确定,统称为“C 状态”或者“C 模式”。
486DX4 处理器首次引入了低功耗模式。
到目前为止,已经引入了更多的功耗模式,并对每种模式进行了增强,以便 CPU 在这些低功耗模式下消耗更少的功率。
- CPU 的每个状态使用不同的电量并对应用程序性能产生不同的影响。
- 每当 CPU 内核空闲时,内置的节能逻辑就会启动并尝试将内核从当前的 C 状态转换为更高的 C 状态,从而关闭各种处理器组件以节省电量
- 但是我们还需要了解,每次应用程序尝试将自身绑定到 CPU 以执行某些任务时,相应的 CPU 都必须从其“深度睡眠状态”返回到“运行状态”,这需要更多时间来唤醒CPU 并再次 100% 启动并运行。它也必须在原子上下文中完成,以便在启动时没有任何尝试使用内核。
- 因此 CPU 转换到的各种模式称为 C 状态
- 它们通常在 C0 启动,这是正常的 CPU 运行模式,即 CPU 100% 开启
- 随着 C 数的增加,CPU 睡眠模式更深,即关闭更多电路和信号,CPU 将需要更多时间返回 C0 模式,即唤醒。
- 每种模式也有不同的名称,其中有几种模式具有不同的省电级别和唤醒时间级别的子模式。
下表解释了所有 CPU C 状态及其含义
如何检查不同 C 状态的现有延迟值?
延迟值可能会根据不同的 C 状态和从更深的 C 状态到 C0 的转换时间而变化。
下面的命令将为我们提供每个 cpu 的所有 c 状态的现有延迟值
# cd /sys/devices/system/cpu/cpu0/cpuidle # for state in state{0..4} ; do echo c-$state `cat $state/name` `cat $state/latency` ; done c-state0 POLL 0 c-state1 C1-HSW 2 c-state2 C1E-HSW 10 c-state3 C3-HSW 33 c-state4 C6-HSW 133
通过更改上述突出显示区域中的 CPU 编号,可以为所有可用 CPU 搜索类似的值。
什么是 POLL 空闲状态?
如果 cpuidle 处于活动状态,则 X86 平台具有一种特殊的空闲状态。
POLL 空闲状态不是真正的空闲状态,它不节省任何电量。
相反,会在短时间内执行一个忙循环,什么都不做。
如果内核知道必须很快处理工作并且进入任何真正的硬件空闲状态可能会导致轻微的性能损失,则使用此状态。
X86架构平台上存在两种不同的cpuidle驱动:
“acpi_idle”cpuidle 驱动程序
acpi_idle cpuidle 驱动程序从 ACPI BIOS 表(从最新平台上的 _CST ACPI 函数或者旧平台上的 FADT BIOS 表)中检索可用的睡眠状态(C 状态)。
不会从 ACPI 表中检索 C1 状态。
如果进入 C1 状态,内核将调用 hlt 指令(或者 mwait 在 Intel 上)。
“intel_idle”cpuidle 驱动程序
在内核 2.6.36 中引入了 intel_idle 驱动程序。
它只服务于最新的 Intel CPU(Nehalem、Westmere、Sandybridge、Atoms 或者更新版本)。
在较旧的 Intel CPU 上,仍使用 acpi_idle 驱动程序(如果 BIOS 提供 C 状态 ACPI 表)。
intel_idle 驱动程序知道处理器的睡眠状态功能并忽略 ACPI BIOS 导出的处理器睡眠状态表。
如何阅读和解释/dev/cpu_dma_latency?
如果我们使用普通的文本编辑器工具来读取这个文件,那么输出将类似于
# cat /dev/cpu_dma_latency 5w
由于此值是“原始”(未编码为文本),因此我们可以使用 hexdump 之类的内容读取它。
# hexdump -C /dev/cpu_dma_latency 00000000 00 94 35 77 |..5w| 00000004
当我们进一步阅读本文时
# echo $(( 0x77359400 )) 2000000000
它告诉我们当前的延迟值 time 是 2000 秒,这是 CPU 从更深的 C 状态上升到 C0 需要或者花费的时间。
注意:默认情况下,在 Red Hat Enterprise Linux 7 上设置为 2000 秒。
当我们使用 force_latency=1 设置调整的配置文件时
例如在这里我将设置网络延迟的调整配置文件
# tuned-adm profile network-latency
检查现有的活动配置文件
# tuned-adm active Current active profile: network-latency
现在让我们检查延迟值
# hexdump -C /dev/cpu_dma_latency 00000000 01 00 00 00 |....| 00000004
如我们所见,延迟值已更改为 1 微秒。
如何查看当前加载的驱动程序?
- intel_idle 驱动程序是支持现代 Intel 处理器的 CPU 空闲驱动程序。
- intel_idle 驱动程序向内核提供每个受支持的英特尔处理器的目标驻留时间和退出延迟。
- CPU 空闲菜单调控器使用此数据来预测 CPU 将空闲多长时间
# cat /sys/devices/system/cpu/cpuidle/current_driver intel_idle
或者你也可以使用下面的命令
# dmesg |grep idle [ 1.766866] intel_idle: MWAIT substates: 0x2120 [ 1.766868] intel_idle: v0.4.1 model 0x3F [ 1.767023] intel_idle: lapic_timer_reliable_states 0xffffffff [ 1.835938] cpuidle: using governor menu
如何禁用处理器睡眠状态?
延迟敏感的应用程序不希望处理器转换到更深的 C 状态,因为从 C 状态返回到 C0 会引起延迟。
这些延迟的范围可以从数百微秒到毫秒。
有多种方法可以实现这一点。
方法一
通过使用内核命令行参数 processor.max_cstate=0 启动,系统将永远不会进入除零以外的 C 状态。
我们可以在 grub2 文件中添加这些变量。
追加“processor.max_cstate=0”如
# vim /etc/sysconfig/grub GRUB_CMDLINE_LINUX="novga console=ttyS0,115200 panic=1 numa=off elevator=cfq rd.md.uuid=f6015b65:f15bf68d:7abf04cc:e53fa9a2 rd.lvm.lv=os/root rd.md.uuid=a66dd4fd:9bf06835:5c2bc8df:f150487f rd.md.uuid=84bfe346:bb18024a:054d652a:d7678fa4 processor.max_cstate=0"
重建你的 initramfs
# grub2-mkconfig -o /boot/grub2/grub.cfg
重新启动节点以激活更改
方法二
- 第二种方法是使用电源管理服务质量接口 (PM QOS)。
- 文件 /dev/cpu_dma_latency 是打开时向操作系统注册延迟的服务质量请求的接口。
- 程序应该打开 /dev/cpu_dma_latency,向它写入一个 32 位数字,表示以微秒为单位的最大响应时间,然后在需要低延迟操作时保持文件描述符打开。写入零意味着我们想要尽可能快的响应时间。
- 各种调整的配置文件可以通过连续读取文件并根据提供的输入写入值来实现这一点,例如网络延迟、延迟性能等。
以下是延迟性能调整文件的片段
[cpu] force_latency=1
如我们所见,只要 Tuned 处于运行状态,该文件将始终处于打开状态
# lsof /dev/cpu_dma_latency COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME tuned 1543 root 8w CHR 10,61 0t0 1192 /dev/cpu_dma_latency
这些配置文件将 force_latency 写为 1,以确保 CPU c 状态不会进入除 C1 之外的更深的 C 状态。
如何检查和监控 Linux 中每个 CPU 和内核的 CPU c 状态使用情况?
为此,我们可以使用“turbostat”工具,该工具将为我们提供所有可用 CPU 和内核的 CPU c 状态使用情况的运行时值。
我将使用 'turbostat' 和 'stress' 工具来监控 CPU c 状态并分别给我的 CPU 施加一些负载。
要安装这些 rpm,我们可以使用
注意:在 RHEL 系统上,我们必须有 RHN 的有效订阅,或者我们可以配置本地离线存储库,使用“yum”包管理器可以安装提供的 rpm 及其依赖项。
# yum install kernel-tools # yum install stress
例如
案例 1:使用吞吐量性能调整配置文件
检查当前活动的配置文件
# tuned-adm active Current active profile: throughput-performance
有了这个,我们的延迟值是默认值,例如:2000 秒
# hexdump -C /dev/cpu_dma_latency 00000000 00 94 35 77 |..5w| 00000004
使用涡轮增压器检查输出
# turbostat Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz IRQ SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt RAMWatt PKG_%内存_% - - 6 0.34 1754 2597 2963 640 1.24 0.07 98.35 0.00 54 61 29.33 6.65 0.00 0.00 0 0 5 0.30 1817 2597 116 40 0.76 0.06 98.88 0.00 51 61 15.36 2.62 0.00 0.00 1 8 7 0.39 1722 2597 253 40 1.84 0.08 97.69 0.00 52 2 1 5 0.28 1786 2597 97 40 1.04 0.04 98.64 0.00 51 3 9 4 0.22 1811 2597 45 40 0.45 0.00 99.32 0.00 51 4 2 5 0.29 1883 2597 86 40 0.69 0.06 98.96 0.00 53 5 10 4 0.22 1830 2597 39 40 0.46 0.00 99.31 0.00 52 6 3 7 0.39 1682 2597 279 40 1.67 0.07 97.87 0.00 54 7 11 7 0.39 1762 2597 200 40 1.79 0.08 97.75 0.00 51 0 4 8 0.43 1837 2597 268 40 1.59 0.07 97.91 0.00 37 49 13.97 4.03 0.00 0.00 1 12 7 0.39 1734 2597 251 40 1.49 0.10 98.02 0.00 40 2 5 5 0.27 1727 2597 84 40 0.64 0.06 99.03 0.00 39 3 13 5 0.27 1837 2597 70 40 0.58 0.03 99.12 0.00 40 4 6 6 0.32 1775 2597 164 40 1.07 0.04 98.56 0.00 40 5 14 6 0.37 1675 2597 234 40 1.44 0.07 98.13 0.00 40 6 7 7 0.43 1735 2597 299 40 1.75 0.15 97.68 0.00 39 7 15 9 0.56 1634 2597 478 40 2.63 0.16 96.66 0.00 38
如我们所见,所有可用的 CPU 和内核都处于 c-6 状态,因为它们都是免费的。
现在,如果我开始施加压力,那么 CPU 将开始从 C6 状态过渡到 c0 状态,并且 c6 将变得空闲,因为所有 CPU 都将处于运行状态
Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz IRQ SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt RAMWatt PKG_%内存_% - - 384 13.84 2782 2594 16172 640 2.14 0.17 83.84 0.00 54 58 42.87 8.42 0.00 0.00 0 0 419 15.09 2790 2590 896 40 1.19 0.08 83.64 0.00 50 58 21.18 3.16 0.00 0.00 1 8 255 9.21 2778 2590 1073 40 4.91 0.55 85.34 0.00 51 2 1 439 15.76 2793 2591 892 40 1.29 0.05 82.90 0.00 54 3 9 441 15.81 2800 2591 997 40 0.64 0.02 83.53 0.00 53 4 2 439 15.74 2797 2592 890 40 0.80 0.06 83.39 0.00 54 5 10 258 9.39 2758 2594 1118 40 5.34 0.41 84.86 0.00 51 6 3 317 11.43 2780 2594 962 40 3.47 0.32 84.78 0.00 52 7 11 327 11.86 2764 2594 1236 40 5.00 0.41 82.73 0.00 50 0 4 39 1.46 2660 2594 485 40 2.31 0.22 96.01 0.00 37 47 21.69 5.26 0.00 0.00 1 12 461 16.68 2767 2594 1314 40 2.69 0.16 80.47 0.00 46 2 5 465 16.68 2791 2595 944 40 0.86 0.08 82.38 0.00 41 3 13 458 16.50 2779 2595 1067 40 1.32 0.14 82.04 0.00 46 4 6 463 16.63 2788 2596 1243 40 0.99 0.07 82.31 0.00 46 5 14 452 16.31 2778 2596 1001 40 1.27 0.11 82.31 0.00 46 6 7 462 16.58 2789 2596 1023 40 0.77 0.05 82.60 0.00 44 7 15 452 16.29 2776 2597 1031 40 1.45 0.07 82.19 0.00 41 Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz IRQ SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt RAMWatt PKG_%内存_% - - 2428 86.63 2804 2599 85363 656 6.08 0.96 6.33 0.00 57 60 119.27 17.04 0.00 0.00 0 0 2377 84.85 2802 2600 5756 41 9.47 1.09 4.59 0.00 55 60 55.56 6.59 0.00 0.00 1 8 1835 65.48 2801 2602 5742 41 20.04 2.11 12.37 0.00 54 2 1 2802 99.93 2803 2601 5037 41 0.07 0.00 0.00 0.00 57 3 9 2802 99.93 2803 2601 5035 41 0.07 0.00 0.00 0.00 56 4 2 2802 99.94 2803 2600 5044 41 0.06 0.00 0.00 0.00 57 5 10 1992 71.12 2802 2598 5688 41 16.62 1.77 10.50 0.00 54 6 3 2799 99.94 2803 2599 5049 41 0.06 0.00 0.00 0.00 57 7 11 1914 68.39 2801 2598 5720 41 18.45 2.09 11.07 0.00 51 0 4 2066 73.79 2800 2600 5335 41 9.85 2.19 14.17 0.00 46 53 63.72 10.45 0.00 0.00 1 12 2803 99.86 2807 2600 5088 41 0.14 0.00 0.00 0.00 52 2 5 656 23.46 2800 2597 3312 41 21.81 6.10 48.63 0.00 45 3 13 2799 99.86 2807 2597 5610 41 0.14 0.00 0.00 0.00 53 4 6 2799 99.86 2807 2597 7143 41 0.14 0.00 0.00 0.00 51 5 14 2799 99.86 2807 2597 5044 41 0.14 0.00 0.00 0.00 50 6 7 2799 99.86 2807 2597 5679 41 0.14 0.00 0.00 0.00 50 7 15 2799 99.86 2807 2597 5081 41 0.14 0.00 0.00 0.00 48 Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz IRQ SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt RAMWatt PKG_%内存_% - - 2421 86.42 2807 2595 84373 656 6.28 1.07 6.23 0.00 59 62 120.52 17.00 0.00 0.00 0 0 2798 99.83 2808 2595 5039 41 0.17 0.00 0.00 0.00 57 62 55.92 6.54 0.00 0.00 1 8 1891 67.58 2803 2595 5151 41 16.92 2.72 12.78 0.00 55 2 1 2798 99.83 2808 2595 5032 41 0.17 0.00 0.00 0.00 59 3 9 2798 99.83 2808 2595 6068 41 0.17 0.00 0.00 0.00 58 4 2 2798 99.83 2808 2595 5041 41 0.17 0.00 0.00 0.00 58 5 10 1527 54.56 2804 2595 5540 41 24.02 3.73 17.70 0.00 56 6 3 2793 99.83 2808 2590 5045 41 0.17 0.00 0.00 0.00 58 7 11 1692 60.57 2804 2590 5556 41 20.66 3.24 15.53 0.00 54 0 4 1425 50.99 2800 2595 5251 41 19.20 4.24 25.57 0.00 48 57 64.60 10.46 0.00 0.00 1 12 2799 99.85 2809 2595 5053 41 0.15 0.00 0.00 0.00 54 2 5 2799 99.84 2809 2595 5054 41 0.16 0.00 0.00 0.00 53 3 13 1419 50.79 2800 2595 4642 41 17.88 3.22 28.11 0.00 49 4 6 2799 99.85 2809 2595 5059 41 0.15 0.00 0.00 0.00 55 5 14 2799 99.84 2809 2595 5047 41 0.16 0.00 0.00 0.00 53 6 7 2799 99.84 2809 2595 6206 41 0.16 0.00 0.00 0.00 53 7 15 2801 99.84 2809 2597 5589 41 0.16 0.00 0.00 0.00 50
我们会看到 Busy% 增加,c-6 下的 CPU 状态减少,这意味着 CPU 当前处于运行状态。
案例 2:将调整后的配置文件更改为延迟性能
# tuned-adm profile latency-performance
# tuned-adm active Current active profile: latency-performance
接下来在系统空闲时监控 CPU c-state
Core CPU Avg_MHz Busy% Bzy_MHz TSC_MHz IRQ SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp PkgWatt RAMWatt PKG_%内存_% - - 61 2.17 2800 2597 2923 656 97.83 0.00 0.00 0.00 68 74 78.78 6.14 0.00 0.00 0 0 363 13.00 2800 2597 56 41 87.00 0.00 0.00 0.00 65 74 39.31 2.22 0.00 0.00 1 8 4 0.14 2800 2597 9 41 99.86 0.00 0.00 0.00 68 2 1 4 0.14 2800 2597 23 41 99.86 0.00 0.00 0.00 66 3 9 61 2.17 2800 2597 211 41 97.83 0.00 0.00 0.00 66 4 2 5 0.18 2800 2597 93 41 99.82 0.00 0.00 0.00 67 5 10 4 0.14 2800 2597 20 41 99.86 0.00 0.00 0.00 66 6 3 4 0.15 2800 2597 25 41 99.85 0.00 0.00 0.00 68 7 11 8 0.28 2800 2597 337 41 99.72 0.00 0.00 0.00 64 0 4 4 0.16 2800 2597 68 41 99.84 0.00 0.00 0.00 57 66 39.46 3.93 0.00 0.00 1 12 4 0.14 2800 2597 34 41 99.86 0.00 0.00 0.00 58 2 5 5 0.18 2800 2597 134 41 99.82 0.00 0.00 0.00 58 3 13 38 1.36 2800 2597 928 41 98.64 0.00 0.00 0.00 59 4 6 433 15.50 2800 2597 35 41 84.50 0.00 0.00 0.00 59 5 14 7 0.24 2800 2597 375 41 99.76 0.00 0.00 0.00 59 6 7 4 0.14 2800 2597 17 41 99.86 0.00 0.00 0.00 58 7 15 21 0.74 2800 2597 558 41 99.26 0.00 0.00 0.00 55
如我们所见,即使 CPU 和内核仍然处于空闲状态,CPU 也不会转换到更深的 c 状态,因为我们强制它保持在 C1