x86 CPU频率

turbostat是intel针对自己的x86 CPU,做的一个CPU频率、能耗监控的用户态程序,位于linux代码

的tools/power/x86/turbostat目录下,编译也很简单,可以直接在这个目录下make,就生成二进制文件了。

这个工具在监控cpu运行频率方面有很大用途。

先直接贴出turbostat的执行结果

[cpp] view plain copy
./turbostat –debug -i 10
turbostat version 4.8 26-Sep, 2015 - Len Brown [email protected]
CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:45:1 (6:69:1)
CPUID(6): APERF, DTS, PTM, EPB
RAPL: 17476 sec. Joule Counter Range, at 15 Watts
cpu2: MSR_PLATFORM_INFO: 0x8083df3011900
8 * 100 = 800 MHz max efficiency frequency
25 * 100 = 2500 MHz base frequency
cpu2: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
cpu2: MSR_TURBO_RATIO_LIMIT: 0x1a1a1a1d
26 * 100 = 2600 MHz max turbo 4 active cores
26 * 100 = 2600 MHz max turbo 3 active cores
26 * 100 = 2600 MHz max turbo 2 active cores
29 * 100 = 2900 MHz max turbo 1 active cores
cpu2: MSR_CONFIG_TDP_NOMINAL: 0x00000013 (base_ratio=3)
cpu2: MSR_CONFIG_TDP_LEVEL_1: 0x0008005c (PKG_MIN_PWR_LVL1=0 PKG_MAX_PWR_LVL1=0 LVL1_RATIO=8 PKG_TDP_LVL1=92)
cpu2: MSR_CONFIG_TDP_LEVEL_2: 0x001900c8 (PKG_MIN_PWR_LVL2=0 PKG_MAX_PWR_LVL2=0 LVL2_RATIO=9 PKG_TDP_LVL2=200)
cpu2: MSR_CONFIG_TDP_CONTROL: 0x00000000 ( lock=0)
cpu2: MSR_TURBO_ACTIVATION_RATIO: 0x00000012 (MAX_NON_TURBO_RATIO=18 lock=0)
cpu2: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000408 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: unlimited)
cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced)
cpu0: MSR_CORE_PERF_LIMIT_REASONS, 0x3d200000 (Active: ) (Logged: Transitions, MultiCoreTurbo, PkgPwrL2, PkgPwrL1, Amps, Auto-HWP, )
cpu0: MSR_GFX_PERF_LIMIT_REASONS, 0x14000000 (Active: ) (Logged: PkgPwrL1, )
cpu0: MSR_RING_PERF_LIMIT_REASONS, 0x0d000000 (Active: ) (Logged: Amps, PkgPwrL1, PkgPwrL2, )
cpu0: MSR_RAPL_POWER_UNIT: 0x000a0e03 (0.125000 Watts, 0.000061 Joules, 0.000977 sec.)
cpu0: MSR_PKG_POWER_INFO: 0x00000078 (15 W TDP, RAPL 0 - 0 W, 0.000000 sec.)
cpu0: MSR_PKG_POWER_LIMIT: 0x4200c800148098 (UNlocked)
cpu0: PKG Limit #1: ENabled (19.000000 Watts, 1.000000 sec, clamp DISabled)
cpu0: PKG Limit #2: DISabled (25.000000 Watts, 0.002441* sec, clamp DISabled)
cpu0: MSR_PP0_POLICY: 0
cpu0: MSR_PP0_POWER_LIMIT: 0x00000000 (UNlocked)
cpu0: Cores Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
cpu0: MSR_PP1_POLICY: 0
cpu0: MSR_PP1_POWER_LIMIT: 0x00000000 (UNlocked)
cpu0: GFX Limit: DISabled (0.000000 Watts, 0.000977 sec, clamp DISabled)
cpu0: MSR_IA32_TEMPERATURE_TARGET: 0x0a640000 (100 C)
cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x88410800 (35 C)
cpu0: MSR_IA32_THERM_STATUS: 0x88440800 (32 C +/- 1)
cpu1: MSR_IA32_THERM_STATUS: 0x88430800 (33 C +/- 1)
Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 Pkg%pc8 Pkg%pc9 Pk%pc10 PkgWatt CorWatt GFXWatt
- - 1 0.08 848 2494 0 0.15 0.00 0.01 99.75 33 35 99.58 0.00 0.00 0.00 0.00 0.00 0.00 1.30 0.00 0.00
0 0 1 0.07 838 2494 0 0.13 0.00 0.00 99.79 33 35 99.58 0.00 0.00 0.00 0.00 0.00 0.00 1.30 0.00 0.00
0 2 1 0.06 860 2494 0 0.14
1 1 2 0.18 848 2494 0 0.09 0.01 0.03 99.70 33
1 3 0 0.02 845 2494 0 0.24
Core CPU Avg_MHz %Busy Bzy_MHz TSC_MHz SMI CPU%c1 CPU%c3 CPU%c6 CPU%c7 CoreTmp PkgTmp Pkg%pc2 Pkg%pc3 Pkg%pc6 Pkg%pc7 Pkg%pc8 Pkg%pc9 Pk%pc10 PkgWatt CorWatt GFXWatt
- - 1 0.07 830 2494 0 0.12 0.00 0.00 99.81 33 37 99.65 0.00 0.00 0.00 0.00 0.00 0.00 1.30 0.00 0.00
0 0 1 0.07 823 2494 0 0.12 0.00 0.00 99.80 31 37 99.65 0.00 0.00 0.00 0.00 0.00 0.00 1.30 0.00 0.00
0 2 1 0.07 836 2494 0 0.13
1 1 1 0.12 830 2494 0 0.07 0.00 0.00 99.81 33
1 3 0 0.02 837 2494 0 0.17

在开始之前,我们先介绍下msr-tools工具的使用,这个工具用来调试intel cpufreq/power相关问题都很方便。

比如,Linux里设置一个cpu的频率是靠 MSR_IA32_PERF_CTL = 0x199,这个寄存器的

bit 0:15表示的是cpu被设置到的频率,即pstate。我们可以用这个命令来获取MSR的特定几位的

值,-a表示获取所有processor的值,–bitfield表示只显示指定位数,这个在调试时非常有用:

[cpp] view plain copy
rdmsr –bitfield 15:8 -a 0x199
8
8
8
8
表示最后一次设置cpu的运行频率是800MHz,注意是从bit8到bit15开始,而非整个bit0-bit15:
[cpp] view plain copy
rdmsr –bitfield 15:0 -a 0x199
800
800
800
800

1.

[cpp] view plain copy
RAPL: 17476 sec. Joule Counter Range, at 15 Watts
看代码:
[cpp] view plain copy
if (debug)
fprintf(stderr, “RAPL: %.0f sec. Joule Counter Range, at %.0f Watts\n”, rapl_joule_counter_range, tdp);
表示的信息是RAPL(Runtime Average Power Limit)的平均功耗是15瓦(耗电速度),然后有一个32位寄存器是专门存储累计耗能(单位是焦耳,即15瓦×时间),

所以最多2^32 / 15W就是溢出的时间,17476秒。 平均功耗的数字保存在MSR_PKG_POWER_INFO=0x614寄存器中,取得这个平均功耗数值,还不是

真正的功耗,还需要乘以功耗的单位,这个单位又保存MSR_RAPL_POWER_UNIT=0x606中。而累计耗能寄存器是32位的MSR_PKG_ENERGY_STATUS=0x611,

所以溢出时间是0xffffffff/15W。

2.

[cpp] view plain copy
cpu2: MSR_PLATFORM_INFO: 0x8083df3011900
8 * 100 = 800 MHz max efficiency frequency
25 * 100 = 2500 MHz base frequency
接下来是MSR_PLATFORM_INFO=0xce, 这个寄存器很重要,用来获取CPU的基础频率即2500MHz
- 也就是最高非turbo的频率 - 也就是TSC的频率,以及最低频率(最节能频率)即800MHz,
3.

然后是

[cpp] view plain copy
cpu2: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
也就是寄存器MSR_POWER_CTL=0x1fc,这个寄存器有一位表示是否使能C1E节能。

4.

[cpp] view plain copy
cpu2: MSR_TURBO_RATIO_LIMIT: 0x1a1a1a1d
MSR_TURBO_RATIO_LIMIT即0x1ad,这个寄存器的意思是,如果有一个core处于active状态,那么能达到的turbo频率是多少,

如果有2个core同时处于active状态,每个core能达到的频率是多少,直到4个core都是active状态,每个core能达到的频率。

这几个值是非递增的,原因是不可能一个package内的所有core都同时达到最高turbo频率,因为有分频,将上面的

值解析一下,就是:

[cpp] view plain copy
26 * 100 = 2600 MHz max turbo 4 active cores
26 * 100 = 2600 MHz max turbo 3 active cores
26 * 100 = 2600 MHz max turbo 2 active cores
29 * 100 = 2900 MHz max turbo 1 active cores
可以看出当只有一个core处于activate(100% load)时,可以达到2.9GHz,
而只要有多于一个core处于activate,就只能到2.6GHz。

5.

接下来的几个是一组互相配合的TDP寄存器:

[cpp] view plain copy

cpu2: MSR_CONFIG_TDP_NOMINAL: 0x00000013 (base_ratio=3) 
cpu2: MSR_CONFIG_TDP_LEVEL_1: 0x0008005c (PKG_MIN_PWR_LVL1=0 PKG_MAX_PWR_LVL1=0 LVL1_RATIO=8 PKG_TDP_LVL1=92)
cpu2: MSR_CONFIG_TDP_LEVEL_2: 0x001900c8 (PKG_MIN_PWR_LVL2=0 PKG_MAX_PWR_LVL2=0 LVL2_RATIO=9 PKG_TDP_LVL2=200)
cpu2: MSR_CONFIG_TDP_CONTROL: 0x00000000 ( lock=0)
cpu2: MSR_TURBO_ACTIVATION_RATIO: 0x00000012 (MAX_NON_TURBO_RATIO=18 lock=0)
这里有一个新名词,TDP,我的理解是,TDP的T代表的时候thermal温度,如果温度比较高,

那么CPU就可能被限流throttling,处于限流状态的CPU的频率就是TDP的level 0, level 1或者level 2

表示的频率。是否开启温度限流模式,由MSR_PLATFORM_INFO的bit33/34来决定,

level 0表示以基础TDP限流模式运行,1表示启动level 1级别, 2表示启动level 2级别。

在level 1和level 2模式下,限流的参数比level 0详细,因为level 0只给了一个基准频率,

而level 1和level 2还给出了power(功率) 的限制,即除了频率,还有电压之类的限制。

MSR_CONFIG_TDP_NOMINAL = 0x648,这个寄存器表示的是基准TDP频率,以100Mhz为单位。
MSR_CONFIG_TDP_LEVEL_1 = 0x649以及MSR_CONFIG_TDP_LEVEL_2 = 0x64a,
分别表示的是TDP level 1和level 2状态下,CPU限流参数(主要还是频率)。

MSR_CONFIG_TDP_CONTROL里存放是当前限流level的值,这个值由BIOS来指定。

MSR_TURBO_ACTIVATION_RATIO表示的是实际的非turbo状态的最大频率,也是由BIOS来设置的,

我估计这个值的来源就是BIOS判断是根据level 1还是level 2,取这两个level相应的频率填充到这个

寄存器。

之前我们曾经说到,非turbo的最大频率是MSR_PLATFORM_INFO里包含的,那么

到底以哪个为准?从Ivybridge以后的client平台上,MSR_PLATFORM_INFO表示的频率不一定就是

最大的非turbo频率了,还要看MSR_TURBO_ACTIVATION_RATIO的值,如果level 1或者level 2开启,

那么最大的频率就是MSR_TURBO_ACTIVATION_RATIO的值,当然为了sanity检查,还需要检查

level 1或者level 2的值是否对应MSR_TURBO_ACTIVATION_RATIO。

猜你喜欢

转载自blog.csdn.net/wdjjwb/article/details/80253935