*NIX 下 CPU 的能耗控制

BIOS 里面的设置开始谈起。可以在 BIOS 里面看到关于 profile 的几个选项中,跟 CPU power management 相关的如下:

1. Performance Per Watt(DAPC): System DBPM(DAPC)
该模式是无法加载任何的 module 的:
# cpuspeed
Error: Could not find any CPUFreq controlled CPU cores to manage
# /etc/init.d/cpuspeed status
cpuspeed is stopped


2. Performance Per Watt(OS): OS DBPM
启动后可以发现,系统自动的加载了 acpi_cpufreq:
# lsmod | grep cpu
cpufreq_ondemand       10544  24
acpi_cpufreq            7891  1
freq_table              4881  2 cpufreq_ondemand,acpi_cpufreq
mperf                   1557  1 acpi_cpufreq

# /etc/init.d/cpuspeed status
Frequency scaling enabled using ondemand governor


3. Performance: Maximum Performance
该模式同样无法加在任何的 module 的


4. Dense Configuration: System DBPM(DAPC)


5. Custom: System DBPM(DAPC), Maximum Performance, OS DBPM

System DBPM(DAPC) 以及 Maximum performance  表示将 CPU 电源管理移交给 BIOS 负责;而 OS DBPM 则表示的是 OS 负责 CPU 的电源管理,主要包括 processor frequency, performance states(P-states: P0, P1…), processor clock throtting(T-states: T0, T1…)

注:
DAPC: Dell Advanced Power controller
DBPM: demand‐based power management

明白了上面的几点,可以发现,真正能通过 OS 控制 CPU 电源管理的只有 OS DBPM 这个了,其他的是根本无法加在模块的。下面主要看 "performance per watt(DAPC)" 这个 profile。在开始之前先熟悉几个基础的东西。

* CPU idle states
也就是 C-states,主要包括 C0, C1(C1E), C2 等等,这个在之前也提到过。要查看当前系统对 C-states 支持的情况,可以安装 cpupowerutils 这个包:
# cpupower idle-info
CPUidle driver: intel_idle
CPUidle governor: menu

Analyzing CPU 0:
Number of idle states: 5
Available idle states: C0 SNB-C1 SNB-C3 SNB-C6 SNB-C7
C0:
Flags/Description: CPUIDLE CORE POLL IDLE
Latency: 0
Usage: 48
Duration: 44917
SNB-C1:
Flags/Description: MWAIT 0x00
Latency: 1
Usage: 21546
Duration: 4611841
SNB-C3:
Flags/Description: MWAIT 0x10
Latency: 80
Usage: 1420
Duration: 934092
SNB-C6:
Flags/Description: MWAIT 0x20
Latency: 104
Usage: 31
Duration: 76146
SNB-C7:
Flags/Description: MWAIT 0x30
Latency: 109
Usage: 71891
Duration: 37675103069


* cpu freq
对于 CPU 来说,最有效降低其功耗的方式是使用 CPUfreq。这些频率的调节是由 CPUfreq governor 完成。对于 rh6 来说,一共由如下的几种 governor:
1. cpufreq_performance: 该 governor 会让 CPU 尽可能的最大限度的利用 clock frequency,因此明显是最大性能,无能耗节约
2. cpufreq_powersave: 尽可能的降低时钟频率,以牺牲性能为代价取得最大的节能效果
3. cpufreq_ondemand: 介于 performance 跟 powersave 之间,也就是系统闲时降低频率,负载高时升高频率,可以看的出来,这是以牺牲 "latency between frequency switching" 为代价的,如果系统在忙闲之间切换额太频繁的话,latency 足以抵消 ondemand 带来的二者之间的平衡。对于大部分的系统来说,这时一个比较好的选择
4. cpufreq_userspace: 这个允许 userspace 的进程设置 freq,该 governor 通常跟 cpuspeed 这个 daemon 结合起来使用,在所有的 governor 中,userspace 的定制化最强
5. cpufreq_conservative: 跟 ondemand 比较类似,不过更加的 gradually,相对于 ondemand 的 aggressive 来说。ondemand 通常是直接在 maximum 跟 minimum 之间简单的进行切换,而 conservative 会更加的适应于当前的系统负载进行调整,尽管这样做可以节约不少能耗,不过带来的确是更大的 latency

可以通过 cron 设置,闲时设置成比较节约能耗的 governor(powersave/ondemand),而忙时则设置成 performance 优先的 governor。如果发现 /proc/cpuinfo 里面各个 core 的 "cpu MHz" 低于 "model name" 里面定义的值,可以判定是由于 cpu freq(cpu speed scaling) 引起的。开启了的好处是能够节能,减少 CPU 的损耗,但是对于性能的影响也是比较明显的。正常情况下都可以关闭,除非对能耗有十分敏感。


如果确实对能耗比较敏感,可以按照下面的方式进行。
1. 首先需要加载 CPUfreq driver,这些模块是在 /lib/modules/[kernel version]/kernel/arch/[architecture]/kernel/cpu/cpufreq/ 目录下面的:
# ll /lib/modules/2.6.32-279.el6.x86_64/kernel/arch/x86/kernel/cpu/cpufreq/
total 128
-rwxr–r–. 1 root root 23744 Jun 14  2012 acpi-cpufreq.ko
-rwxr–r–. 1 root root  5824 Jun 14  2012 mperf.ko
-rwxr–r–. 1 root root 12296 Jun 14  2012 p4-clockmod.ko
-rwxr–r–. 1 root root 18552 Jun 14  2012 pcc-cpufreq.ko
-rwxr–r–. 1 root root 41960 Jun 14  2012 powernow-k8.ko
-rwxr–r–. 1 root root 13120 Jun 14  2012 speedstep-lib.ko

默认会加载 acpi_cpufreq 这个模块。

2. 接着就是加载 governor 了:
# ll /lib/modules/2.6.32-279.el6.x86_64/kernel/drivers/cpufreq/
total 88
-rwxr–r–. 1 root root 20576 Jun 14  2012 cpufreq_conservative.ko
-rwxr–r–. 1 root root 27096 Jun 14  2012 cpufreq_ondemand.ko
-rwxr–r–. 1 root root  5336 Jun 14  2012 cpufreq_powersave.ko
-rwxr–r–. 1 root root 14528 Jun 14  2012 cpufreq_stats.ko
-rwxr–r–. 1 root root 10920 Jun 14  2012 freq_table.ko

查看当前可用的 governors,默认使用的是 ondemand:
# cpupower frequency-info –governors
analyzing CPU 0:
ondemand userspace performance

# modprobe  cpufreq_conservative
# cpupower frequency-info –governors
analyzing CPU 0:
conservative ondemand userspace performance

可用之后就是 enable 了:
# cpupower frequency-set –governor [governor]

3. 设置完 governor 之后,可以查看 cpu speed 以及使用的 policy:
# cpupower frequency-info
analyzing CPU 0:
  driver: acpi-cpufreq
  CPUs which run at the same hardware frequency: 0
  CPUs which need to have their frequency coordinated by software: 0
  maximum transition latency: 10.0 us.
  hardware limits: 1.20 GHz – 2.30 GHz
  available frequency steps: 2.30 GHz, 2.30 GHz, 2.20 GHz, 2.10 GHz, 2.00 GHz, 1.90 GHz, 1.80 GHz, 1.70 GHz, 1.60 GHz, 1.50 GHz, 1.40 GHz, 1.30 GHz, 1.20 GHz
  available cpufreq governors: conservative, ondemand, userspace, performance
  current policy: frequency should be within 1.20 GHz and 2.30 GHz.
                  The governor "performance" may decide which speed to use
                  within this range.
  current CPU frequency is 1.20 GHz (asserted by call to hardware).
  boost state support:
    Supported: yes
    Active: yes
    2700 MHz max turbo 4 active cores
    2700 MHz max turbo 3 active cores
    2800 MHz max turbo 2 active cores
    2800 MHz max turbo 1 active cores

如果对结果不是很满意,可以使用 cpupower frequency-set 来调节。
如果没有安装 cpupowerutils 这个包,可以在 /sys/devices/system/cpu/[cpuid]/cpufreq/ 这个目录下面进行同样的操作:
# echo 360000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq

还可以对这些 C-states 进行监控

说了这么多,其实完全没有必要这么做,前提的是你的机器数量在五位数以下,我估计大陆 p99 的互联网都是这个量级以下的,创业公司就更普遍了。
因此,最简单的办法是,将 BIOS 设置成 "Performance"(memory freq sets to max, memory patrol scrub sets to standard mode, memory fresh rate sets to 1x, memory operating voltage sets to auto, turbo boost enabled and C1E&C-states disabled) 模式。


ref:
https://www.kernel.org/doc/Documentation/cpu-freq/governors.txt
https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Power_Management_Guide/Core_Infrastructure.html
http://en.community.dell.com/techcenter/power-cooling/w/wiki/best-practices-in-power-management.aspx