为什么操作系统可能会忽略 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

什么是 CPU c 状态?如何检查和监控 Linux 中每个 CPU 和内核的 CPU c 状态使用情况?
日期:2020-06-02 22:17:20 来源:oir作者:oir