将晦涩难懂的技术讲的通俗易懂
分类: LINUX
2019-06-15 21:59:55
linux电源管理——C-state,P-state,turbo
{BANNED}最佳近在进行网络性能测试的时候进程会遇到系统C-state,P-state以及turbo的相关设置,虽然知道都是和CPU功耗有关,但具体有什么联系以及对当前进程的影响并不是很清楚,于是查了一下相关资料做一个总结记录。
首先C-state和P-state是完全不同的概念和维度,官方解释是“C-states are idle states and P-states are operational states”。,此外C-States(CPU Power states)指CPU电源状态,而P-States(CPU Performance states)则指CPU性能状态。下面我们逐个分析一下。
C-state有C0,C1...Cn多种模式,但只有C0是正常工作模式(active),其他方式都是idle状态,只是idle的程度不同,C后的数越高,CPU睡眠得越深,CPU的功耗被降低得越多,同时需要更多的时间回到C0模式。 那么是什么决定了idle的程度或者说睡眠的程度呢?答案是stop CPU功能的多少,CPU的功能被阉割的越多就越省电,当然恢复正常状态就需要越长时间。每一个模式都有一个对应的名字,有的模式还有子模式,子模式又具有不同功耗和唤醒时间。在下表所列的模式中,C1到C3通过切断CPU内部的时钟,C4到C6模式通过降低CPU的电压。"Enhanced"模式两种方式都采用。
总结来说,C-state是控制CPU的睡眠状态的。只有C0状态的CPU是running状态的,其他C状态全部是睡眠状态,只是睡眠的程度不同,即C-state控制CPU在空闲时进入的睡眠级别。
那么如何查看当前CPU的C状态呢?这就需要turbostat工具了,如下所示
[ec2-user ~]$ sudo vim /etc/default/grub
2. 编辑该GRUB_CMDLINE_LINUX_DEFAULT行并添加 intel_idle.max_cstate=1和processor.max_cstate=1选项以设置C1为空闲内核的{BANNED}最佳深 C 状态。
GRUB_CMDLINE_LINUX_DEFAULT="console=tty0 console=ttyS0,115200n8 net.ifnames=0 biosdevname=0 nvme_core.io_timeout=4294967295 intel_idle.max_cstate=1 processor.max_cstate=1"
GRUB_TIMEOUT=0
该intel_idle.max_cstate=1选项为基于 Intel 的CPU生效,processor.max_cstate=1配置则为基于 AMD 的CPU C 状态限制。
3. 保存文件并退出编辑器。
4. 运行以下命令来重建引导配置。
[ec2-user ~]$ grub2-mkconfig -o /boot/grub2/grub.cfg
5. 重新启动您的实例以启用新的内核选项。
[ec2-user ~]$ sudo reboot
从Linux Kernel 3.9(2009年4月),一个新的加入到内核中,从SandbyBridge处理器开始,后续多代Intel处理器都得到了支持。
前面说了C-state是控制CPU的睡眠状态的,那么P-state就是控制CPU运行(running)状态的,即控制CPU以多高的频率运行,也就是说任何P-state都是处于C0状态的。
处理器P-state是处理器在不同电压和/或频率级别下运行的能力。通常P0是导致{BANNED}最佳大性能的{BANNED}最佳高状态,而P1、P2等将节省电能,但会对CPU性能造成一些损失。P 状态从 P0(允许内核使用 Intel Turbo Boost 技术尽可能提高频率的{BANNED}最佳高性能设置)开始编号,它们从 P1(请求{BANNED}最佳大基线频率的 P 状态)到 P15 (可能的{BANNED}最佳低频率)。
为什么都是运行状态还有区分呢?因为虽然CPU在C0状态时都会会执行指令,但是即使在C0状态下仍然可以通过调整CPU的工作电压和频率的方式,以此降低整个平台的功耗。
P-state是一组预定义的CPU频率/电压,如下图中表格给出了处理器不同P-state的例子,该处理器拥有5个P-state,P0-P5,每个P-state level定义了该level下对应的运行电压、运行频率及功耗。处理器可以在这些频率和电压组合下正确运行,但性能水平有所不同。频率越高,性能越好,但是为了达到这个目的,电压也需要更高,这就使得处理器消耗更多的电源(电力功耗与电压平方和工作频率的乘积成正比)。功耗计算公式:P=C×V?×F(可以参考intel手册)
上图右侧的流程图表示了处理器从P0状态到P4的变化过程。
那么为什么要用P-state表示,而不是直接cpu frequency呢?
在十几年前,单核,也没有超线程的世界,事情相对简单。你基本上可以将P状态映射到某个你会得到的“频率”上,就像销售告诉我们的,更高的频率意味着更高的性能。
但今天,事情变得复杂,intel 处理器一代又一代,发生着巨大的变化。与10年前不同……CPU有了C-state,无论您请求的是哪种P状态,当处理器处于空闲状态(C状态)时,其频率通常为0,CPU frequency是个变数...。
所以,事实上P状态是一个数字,是操作系统告诉硬件它希望在某个cpu上看到多少性能,P状态请求是具有前瞻性的。并不是设置了P-state就能看到对应性能,这跟当时的运行环境密切相关。另外要记住,CPU frequency是处理运行时的状态,如果CPU在睡觉(非C0状态),那么它没有频率。
另外一方面,由于硬件原因,在当前的Intel处理器上,一个package中的所有核心共享相同的电压。而且,由于在一定电压下以低于可能的频率运行是低效的,所以所有核心在任何时候都将共享相同的时钟频率。
举一个简单的例子:
一个系统,两个CPU核心(Core A和Core B,它们{BANNED}最佳初都很忙)。Core A希望有一个在1Ghz频率的时钟,而Core B希望有一个在2Ghz频率的时钟。1Ghz和2Ghz的{BANNED}最佳大值是…2Ghz,因此Core A和Core B都将运行在2Ghz下,尽管Core A只要求1Ghz。
一段时间后,在X时刻,Core B处于空闲状态。因为一个空闲核的频率是0,而0和1Ghz的{BANNED}最佳大值是1Ghz……Core A现在运行的时钟频率为1Ghz。
这里的一个关键:Core A得到了一个可变的CPU运行行为,和它所请求的CPU p-state级别无关,而是在于核心B在做什么。换句话说,CPU上P-state的设定,似乎是一个期望值。实时的P-state状态和运行负载、硬件电压、兄弟核、温度等等都有一定联系。对于用户来说,我们熟知的CPU主频,同样也高度依赖系统各个内部部件。
可以通过修改grub启动文件开启P-state。
修改/etc/default/grub配置行GRUB_CMDLINE_LINUX添加intel_idle.max_cstate=1 intel_pstate=enable processor.max_cstate=1
grub2-mkconfig -o /boot/grub2/grub.cfg
但是我们发现我们无法指定CPU到底处于那个P-state或者{BANNED}最佳大的P-state,这个完全是OS来控制的。
硬件提供了动态变更CPU性能,对应到linux操作系统,是由CPU frequency driver来完成处理器performance动态变化的。linux中有一套ACPI cpufreq driver,这种适用于大数平台及架构。
而在linux-3.9内核中,intel为P-state引入了一个新的控制器驱动程序,原因很简单,因为之前的10多年的算法已经不再适用了,变化太大了。同时intel在自己硬件上做了特殊节能优化,Intel cpu通过MSR寄存器公开了很多power manager相关的状态信息,方便驱动程序访问。p-state驱动程序特定生成于intel CPU,同时实现了p-state选择策略和调优算法,据说比通用的算法做得更好(30%以上)。
当然intel平台也同样支持使用通用的ACPI cpufreq driver。
上面所描述很多东西在intel一代一代之间是有很大不同的……也许,在接下来的几年里,处理器将发生更大的变化。但这对于一些对PM感兴趣的人,理解一些基本概念已经足够……
P-state可以和turbo(睿频)相结合,如果/sys/devices/system/cpu/intel_pstate/no_turbo被设置为0,说明使能了turbo P-state。
P-state支持的所有频率范围可以分为两个部分,有一个分界的阈值turbo threshold(一般为P1),超过这个阈值的P-state称之为turbo P-states。
有些人称之为“超频”,但它并不是超频,它完全运行在硬件规格之内。Turbo之所以存在,是因为在多核系统中,单核的运行速度可能比购买处理器时盒子标签上的频率更快。这与你的电源功耗有关,当你买了一个35瓦的TDP cpu, cpu不应该使用超过35瓦。因此,如果你有4个核心,这意味着每个核心本身可以使用不到9瓦来满足。
那如果处理器中单一核心被限制在9瓦,而不是完整的35W,那么即使其他核心是空闲的,active CPU也只能工作在9瓦范围内,许多潜在的性能没有被激发……。
那么我想,你应该知道turbo技术是什么了吧,也就是单一核心可以超过9W运行,而不是局限在一个固定的平均值。所以当处理器中其他核心idle的情况下,某一个active cpu才可以发挥出更大的潜能(当然和当前的负载有关),那么这个时候,意味着CPU超频了……。
如下图所示,P0:{BANNED}最佳佳性能状态,代表CPU处于turbo状态(turbo状态只能是在P0),{BANNED}最佳大频率运行。(由硬件控制)P1-Pn:硬件提供了可用的P-state范围,可由OS来管理。
在我们的x86环境下,可以通过turbostat工具来看到cpu的turbostat boost能力:
关注{BANNED}最佳后4行,当只有1个核是active的时候,那么这个核可以达到2.6Ghz;而当有3个active核时,这3个核可以达到2.5Ghz,那如果4个核或4个核以上active时,那么只能达到2.4Ghz。
下面是一个测试,其中两个内核主动执行工作,通过stress命令给两个CPU加负载,达到其{BANNED}最佳大处理器 Turbo Boost 频率。
在此示例中,vCPU 21 和 28 以其{BANNED}最佳大 Turbo Boost 频率运行,因为其他内核已进入C6睡眠状态以节省功耗并为工作内核提供功率和热空间。vCPU 3 和 10(每个与 vCPU 21 和 28 共享一个处理器内核)处于C1等待指令状态。
在以下示例中,所有 18 个内核都在积极执行工作,因此没有{BANNED}最佳大 Turbo Boost 的空间,但它们都以 3.2 GHz 的“全核 Turbo Boost”速度运行。
在介绍ISS和SST前首先看几个关键概念:
(1) ISS:Intel Speed Select,Intel新推出的调频技术
(2) P0N:PState 0 ON N Core on full Stress, 将所有核都加压情况下,CPU所能达到的Turbo频率
(3) P01: PState 0 ON 1 Core on full Stress, 加压一个核的时候,CPU所能达到的Turbo频率
(4) P1: Guaranteed Base Frequency(P1) CPU的基准频率。
(5) SST: Speed Select Technology, 即ISS V2
我们前面知道,通过Turbo可以在性能需求较小时降低频率,节省功耗,在性能需求较高时提升CPU频率,满足性能需求。不过这也会导致当所有CPU都有性能需求时,Turbo频率P0N会比P01低不少。而ISS/SST就是为了提升P0N的技术。
ISS是2018年intel在Purley平台,Cascade CPU上推出的一个新功能,而到了2020年,在Whitley平台,Icelake CPU 又推出了ISS V2,即SST。SST相对ISS的关键变化就是引入了Dynamic PP(Proformance Profile),即相当于将SST Profile的时间从BIOS POST阶段调整到了OS阶段。所以我们知道ISS的原理也就知道了SST的原理。而ISS的核心原理就是通过将一部分CPU core disable来提升其他CPU的P0N。这个也很好理解,一部分CPU不工作,在{BANNED}最佳大功耗一定的情况下,其他CPU就可以跑到更高的频率。不过这里具体enable或disable哪几个core是通过算法,将对应的core在CPU DIe中平均分布,已实现散热和性能的{BANNED}最佳优化。
那ISS/SST有什么价值呢?在没有这项技术前,我们采购一批服务器作为通用服务器,但是如果特殊场景需要更高的性能/主频,就只能再采购高主频的CPU,而有了此项技术就可以为CPU配置不同的核数和频率组合来满足业务需求,只需要采购一款CPU服务器即可满足。
如何确认当前系统使能了SST呢?{BANNED}最佳简单的方式就是查看你的CPU,CPU不连续大概率就是因为开启了SST部分被disable,当然{BANNED}最佳直观的方式还是通过BISO配置查看。
cpufreq 为在Linux 内核中更好的支持不同 CPU 的变频技术提供了一个统一的设计框架,其软件结构如下:
cpufreq 在设计上主要分为以下三个模块:
1) cpufreq 模块(cpufreq module)对如何在底层控制各种不同 CPU 所支持的变频技术以及如何在上层根据系统负载动态选择合适的运行频率进行了封装和抽象,并在二者之间定义了清晰的接口,从而在设计上完成了前文所提到的对 mechanism 与 policy 的分离。
2) 在 cpufreq 模块的底层,各个 CPU 生产厂商只需根据其变频技术的硬件实现和使用方法提供与其 CPU 相关的变频驱动程序(CPU-specific drivers),例如 Intel 需要提供支持 Enhanced SpeedStep 技术的 CPU 驱动程序,而 AMD 则需要提供支持 PowerNow! 技术的 CPU 驱动程序。
3) 在 cpufreq 模块的上层,governor 作为选择合适的目标运行频率的决策者,根据一定的标准在适当的时刻选择出 CPU 适合的运行频率,并通过 cpufreq 模块定义的接口操作底层与 CPU 相关的变频驱动程序,将 CPU 设置运行在选定的运行频率上。目前{BANNED}最佳新的 Linux 内核中提供了 performance 、powersave 、userspace、conservative 和 ondemand 五种 governors 供用户选择使用,它们在选择 CPU 合适的运行频率时使用的是各自不同的标准并分别适用于不同的应用场景。用户在同一时间只能选择其中一个 governor 使用,但是可以在系统运行过程中根据应用需求的变化而切换使用另一个 governor 。
这种设计带来的好处是使得 governor 和 CPU 相关的变频驱动程序的开发可以相互独立进行,并在{BANNED}最佳大限度上实现代码重用,内核开发人员在编写和试验新的 governor 时不会再陷入到某款特定 CPU 的变频技术的硬件实现细节中去,而 CPU 生产厂商在向 Linux 内核中添加支持其特定的 CPU 变频技术的代码时只需提供一个相对来说简单了很多的驱动程序,而不必考虑在各种不同的应用场景中如何选择合适的运行频率这些复杂的问题。
内核中的 cpufreq 子系统通过 sysfs 文件系统向上层应用提供了用户接口,对于系统中的每一个 CPU 而言,其 cpufreq 的 sysfs 用户接口位于 /sys/devices/system/cpu/cpuX/cpufreq/ 目录下,其中 X 代表 processor id ,与 /proc/cpuinfo 中的信息相对应。以 cpu0 为例,用户一般会在该目录下观察到以下文件:
$ ls -F /sys/devices/system/cpu/cpu0/cpufreq/ affected_cpus cpuinfo_cur_freq cpuinfo_max_freq
cpuinfo_min_freq ondemand/ scaling_available_frequencies scaling_available_governors scaling_cur_freq scaling_driver scaling_governor scaling_max_freq scaling_min_freq stats/
|
1. cpupower monitor -l可以列出所有可以监控的模块,如:
2. cpupower frequency-info可以检查处理器主频:
#cpupower frequency-info
analyzing CPU 0:
driver: intel_pstate
CPUs which run at the same hardware frequency: 0
CPUs which need to have their frequency coordinated by software: 0
maximum transition latency: 0.97 ms.
hardware limits: 1000 MHz - 3.10 GHz
available cpufreq governors: performance, powersave
current policy: frequency should be within 1000 MHz and 3.10 GHz.
The governor "powersave" may decide which speed to use
within this range.
current CPU frequency is 2.70 GHz (asserted by call to hardware).
boost state support:
Supported: yes
Active: yes
其中hardware limits表示CPU支持的频率范围;
current policy表示当前配置下CPU的支持的频率波动范围;
注意:使用cpupower frequency-info显示的当前cpu 0主频是一个约数,不精确且有延迟。{BANNED}最佳好采用 cpupower monitor -m Mperf 检查能够获取精确的CPU主频,且即使没有使用intel_pstate驱动也能够准确获取频率。
3. 检查处理器主频cpupower monitor -m Mperf
$sudo cpupower monitor -m Mperf
|Mperf
PKG |CORE|CPU | C0 | Cx | Freq
0| 0| 0| 7.85| 92.15| 2820
0| 0| 32| 0.38| 99.62| 2825
0| 1| 1| 42.75| 57.25| 2891
0| 1| 33| 6.98| 93.02| 2890
...
可以看到Cx显示的就是处理器idle的状态
4. cpupower idle-info命令列出支持的C-State
cpupower idle-info
CPUidle driver: intel_idle
CPUidle governor: menu
Analyzing CPU 0:
Number of idle states: 2
Available idle states: POLL C1-SKX
POLL:
Flags/Description: CPUIDLE CORE POLL IDLE
Latency: 0
Usage: 2667
Duration: 296902700
C1-SKX:
Flags/Description: MWAIT 0x00
Latency: 2
Usage: 776606
Duration: 14056122480
以上信息表示当前系统支持POLL,C1-SKX两种idle C-state,并且都没有disable。注意:系统必须加载了intel_idle驱动之后才能列出支持的C-state。
5. intel_pstate/no_turbo
可以在intel_pstate驱动中关闭turob(设置intel_pstate/no_turbo值为1)
echo 1|sudo tee /sys/devices/system/cpu/intel_pstate/no_turbo
要检查是否启用和停止Turbo,可以通过:
cat /sys/devices/system/cpu/intel_pstate/no_turbo 来检查
Turbo Boost也可以在运行时通过禁止intel_pstate驱动来关闭:
echo off |sudo tee /sys/devices/system/cpu/intel_pstate/status
注意:这里禁用intel_pstate之后,处理器主频会跌到物理主频的{BANNED}最佳小值,此时需要通过MSR寄存器199H来静态设置目标性能状态值(Target performance State Value)
也可以激活intel_pstate驱动:
echo active |sudo tee /sys/devices/system/cpu/intel_pstate/status
注意:这个intel_pstate/status入口必须在激活Turbo Boost之后才会存在
6. cpupower frequency-info读取CPU主频
注意,默认没有指定cpu参数则读取cpu 0主频。要读取指定cpu的主频,需要使用-c参数,例如,读取cpu 31的主频
cpupower -c 31 frequency-info
不过,cpupower frequency-info 是通过intel_pstate驱动来获取信息的,所以如果使用 echo off |sudo tee /sys/devices/system/cpu/intel_pstate/status 禁用了intel_pstate驱动,则该指令失效。
可以通过cpupower monitor指令来获取CPU主频,该指令是直接读取MSR 198H 来直接获取CPU主频信息,所以即使禁用了intel_pstate驱动也可以获得准确的数据。
cpupower monitor
7. 使用turbostat读取主频
turbostat默认10秒刷新一次,可以使用-i 1可以1秒刷新一次。
1) Avg_MHz是平均主频,基于APERF
2) Busy%表示处理器繁忙百分比
3) Bzy_MHz是实际的busy frequency,基于MPERF
4) TSC_MHz是固定主频,TSC基于
5) APERF (average) and MPERF (maximum) 是MSR寄存器可以提供当前CPU主频信息。
8. 通过cpupower frequency-set设置cpu的频率
可以通过cpupower frequency-set --min/--max $freq 来设置当前系统的cpu频率范围。
9. 查看设置系统的governor
同样通过cpupower frequency-info可以查看当前系统支持的governor,已经在使用的governor。
#cpupower frequency-info
analyzing CPU 0:
……
available cpufreq governors: performance, powersave
current policy: frequency should be within 1000 MHz and 3.10 GHz.
The governor "powersave" may decide which speed to use
within this range.
如上,表示当前系统支持performance, powersave两种governor,而当前正在使用的是powersave。
可以通过cpupower frequency-set --governor $governor来设置当前系统使用的governor。比如一般人都会用cpupower frequency-set -g performance这个命令这个命令使能后,某个cpu会达到睿频{BANNED}最佳大的频率。