您的位置:首页 > 其它

[知其然不知其所以然-3] 为什么在高负载下cpu的温度没有显著提升

2015-08-05 14:07 597 查看
是的,根据常识,如果你在玩一个大型游戏,或者在运算一大组数据,那么cpu的温度应该是要上升许多的。

但最近在我们实验室的机器上,发现了一个问题,就是当我们用stress -c 4 -t 30进行cpu压力测试时,

package cpu的温度相比无负载时的温度,上升的很少。

ps:我们的测试都是在performance policy下,也就是说,在cpu有活干的时候,该cpu按照自己可能的最高频率来运行。

我们先在一台温度变化正常的机器上进行温度测试:

grep . /sys/class/thermal/thermal_zone*/type;grep . /sys/class/thermal/thermal_zone*/temp;stress -c 4 -t                         30;grep . /sys/class/thermal/thermal_zone*/type;grep . /sys/class/thermal/thermal_zone*/temp;
/sys/class/thermal/thermal_zone0/type:acpitz
/sys/class/thermal/thermal_zone1/type:INT3400 Thermal
/sys/class/thermal/thermal_zone2/type:SEN1
/sys/class/thermal/thermal_zone3/type:SEN2
/sys/class/thermal/thermal_zone4/type:SEN3
/sys/class/thermal/thermal_zone5/type:SEN4
/sys/class/thermal/thermal_zone6/type:SEN6
/sys/class/thermal/thermal_zone7/type:SEN7
/sys/class/thermal/thermal_zone8/type:B0D4
/sys/class/thermal/thermal_zone9/type:x86_pkg_temp
/sys/class/thermal/thermal_zone0/temp:48000
/sys/class/thermal/thermal_zone1/temp:20000
/sys/class/thermal/thermal_zone2/temp:41000
/sys/class/thermal/thermal_zone3/temp:46000
/sys/class/thermal/thermal_zone4/temp:40000
/sys/class/thermal/thermal_zone5/temp:42000
/sys/class/thermal/thermal_zone6/temp:42000
/sys/class/thermal/thermal_zone7/temp:34000
/sys/class/thermal/thermal_zone8/temp:48000
/sys/class/thermal/thermal_zone9/temp:50000
stress: info: [2383] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
stress: info: [2383] successful run completed in 30s
/sys/class/thermal/thermal_zone0/type:acpitz
/sys/class/thermal/thermal_zone1/type:INT3400 Thermal
/sys/class/thermal/thermal_zone2/type:SEN1
/sys/class/thermal/thermal_zone3/type:SEN2
/sys/class/thermal/thermal_zone4/type:SEN3
/sys/class/thermal/thermal_zone5/type:SEN4
/sys/class/thermal/thermal_zone6/type:SEN6
/sys/class/thermal/thermal_zone7/type:SEN7
/sys/class/thermal/thermal_zone8/type:B0D4
/sys/class/thermal/thermal_zone9/type:x86_pkg_temp
/sys/class/thermal/thermal_zone0/temp:79000
/sys/class/thermal/thermal_zone1/temp:20000
/sys/class/thermal/thermal_zone2/temp:41000
/sys/class/thermal/thermal_zone3/temp:50000
/sys/class/thermal/thermal_zone4/temp:40000
/sys/class/thermal/thermal_zone5/temp:43000
/sys/class/thermal/thermal_zone6/temp:43000
/sys/class/thermal/thermal_zone7/temp:33000
/sys/class/thermal/thermal_zone8/temp:79000
/sys/class/thermal/thermal_zone9/temp:76000
我们主要关注/sys/class/thermal/thermal_zone9/type:x86_pkg_temp这个值,

因为这个值表示的是一个package core的温度,也就是说,如果你的机器有

4个cpu,这4个cpu是一个整体看作是一个package,那么这个值反应的

就是这个package的温度(摄氏度)。

可以看出,在这台正常的机器上,压力测试下,package core温度从50升高到了76。

那么出问题的机器情况是怎么样呢?

grep . /sys/class/thermal/thermal_zone*/temp;stress -c 4 -t 30;grep . /sys/class/thermal/thermal_zone*/temp
/sys/class/thermal/thermal_zone0/temp:43000
/sys/class/thermal/thermal_zone1/temp:43000
/sys/class/thermal/thermal_zone2/temp:20000
/sys/class/thermal/thermal_zone3/temp:36000
stress: info: [1913] dispatching hogs: 4 cpu, 0 io, 0 vm, 0 hdd
stress: info: [1913] successful run completed in 30s
/sys/class/thermal/thermal_zone0/temp:48000
/sys/class/thermal/thermal_zone1/temp:48000
/sys/class/thermal/thermal_zone2/temp:20000
/sys/class/thermal/thermal_zone3/temp:41000
其中thermal_zone3是package temperature,可以看出,他的温度仅仅提升了5摄氏度。

这是怎么回事呢?

首先我们想到,会不会是我们出问题机器上的风扇散热不好?于是我们做了个测试,

在好的机器和出问题的机器上,通过sysfs把风扇关掉。结果发现,测试结果还是不变,

那么就排除了风扇的影响。

接下来我们想到,在压力测试下,每个cpu都是100%利用率的,那么会不会是两个cpu

在高负载下的频率不同?于是我们用turbostat工具来跟踪一下。

turbostat工具可以监控cpu的各项指标,包括频率,温度,进入cstat的次数,功耗等,

不过只能在intel平台上使用,毕竟是intel的power老大Len Brown开发的,他的代码位于

linux\tools\power\x86\turbostat

下面是一次turbostat的单次执行获取的cpu数据:

$ ./turbostat --debug -i 10
turbostat version 4.7 27-May, 2015 - Len Brown <lenb@kernel.org>
CPUID(0): GenuineIntel 13 CPUID levels; family:model:stepping 0x6:2a:7 (6:42:7)
CPUID(6): APERF, DTS, PTM, EPB
RAPL: 690 sec. Joule Counter Range, at 95 Watts
cpu0: MSR_NHM_PLATFORM_INFO: 0x100060012200
16 * 100 = 1600 MHz max efficiency frequency
34 * 100 = 3400 MHz base frequency
cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
cpu0: MSR_TURBO_RATIO_LIMIT: 0x23242526
35 * 100 = 3500 MHz max turbo 4 active cores
36 * 100 = 3600 MHz max turbo 3 active cores
37 * 100 = 3700 MHz max turbo 2 active cores
38 * 100 = 3800 MHz max turbo 1 active cores
cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e008407 (UNdemote-C3, UNdemote-C1, demote-                                                                                        C3, demote-C1, locked: pkg-cstate-limit=7: unlimited)
cpu0: MSR_IA32_ENERGY_PERF_BIAS: 0x00000006 (balanced)
cpu0: MSR_RAPL_POWER_UNIT: 0x000a1003 (0.125000 Watts, 0.000015 Joules, 0.000977                                                                                         sec.)
cpu0: MSR_PKG_POWER_INFO: 0xa03c001e002f8 (95 W TDP, RAPL 60 - 120 W, 0 .009766 s                                                                                        ec.)
cpu0: MSR_PKG_POWER_LIMIT: 0x83b6001482f8 (UNlocked)
cpu0: PKG Limit #1: ENabled (95.000000 Watts, 1.000000 sec, clamp DISabled)
cpu0: PKG Limit #2: ENabled (118.750000 Watts, 0.000977* 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: 0x00621200 (98 C)
cpu0: MSR_IA32_PACKAGE_THERM_STATUS: 0x883e0000 (36 C)
cpu0: MSR_IA32_THERM_STATUS: 0x88410000 (33 C +/- 1)
cpu1: MSR_IA32_THERM_STATUS: 0x883e0000 (36 C +/- 1)
cpu2: MSR_IA32_THERM_STATUS: 0x88450000 (29 C +/- 1)
cpu3: MSR_IA32_THERM_STATUS: 0x88400000 (34 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 PkgWatt CorWatt GFXWatt
-       -       6    0.36    1605    3392       0    2.44    0.04   97.16                                                                                            0.00      29      30    8.07    0.02   81.85    0.00    4.26    0.69    0.19
0       0       0    0.03    1602    3392       0    0.04    0.00   99.93                                                                                            0.00      29      30    8.07    0.02   81.85    0.00    4.26    0.69    0.19
0       4       0    0.01    1597    3392       0    0.06
1       1       8    0.48    1605    3392       0    2.82    0.15   96.55                                                                                            0.00      29
1       5       5    0.34    1597    3392       0    2.96
2       2       5    0.29    1598    3392       0    0.32    0.00   99.39                                                                                            0.00      29
2       6       1    0.04    1606    3392       0    0.57
3       3       1    0.04    1598    3392       0    7.19    0.01   92.77                                                                                            0.00      29
3       7      27    1.68    1608    3392       0    5.55


在显示数据的最后部分,我们看到有Bzy_MHZ TSC_MHZ, CoreTmp, PkgTmp Pkg%pc2 PkgWatt 等字段,下面挨个来说明。

turbostat输出的主要函数在format_counters,我们选取有代表性的几个输出:

/* %Busy */
outp += sprintf(outp, "%8.2f", 100.0 * t->mperf/t->tsc);

/* Bzy_MHz */
outp += sprintf(outp, "%8.0f",
1.0 * t->tsc / units * t->aperf / t->mperf / interval_float);

/* TSC_MHz */
outp += sprintf(outp, "%8.0f", 1.0 * t->tsc/units/interval_float);

outp += sprintf(outp, "%8.2f", 100.0 * c->c3/t->tsc);
outp += sprintf(outp, "%8d", c->core_temp_c);
outp += sprintf(outp, "%8d", p->pkg_temp_c);
outp += sprintf(outp, "%8.2f", 100.0 * p->pc2/t->tsc);
outp += sprintf(outp, fmt8, p->energy_pkg * rapl_energy_units / interval_float);


首先,每个cpu有一对频率反馈寄存器,叫aperf和mperf,全称就是actual performance msr register 和

max(fix) performance msr register。 这两个寄存器在cpu处于C0运行态势,会单调递增,其中,

aperf是按照cpu实际的频率来增加,而mperf以固定频率(也就是tsc频率来增加),所以,

我们如果要监控一段时间内cpu在c0运行态时的频率, 就按照下面这个公式(delta(aperf)/delta(mperf) )*  TSC,

这也就是Bzy_MHZ的来历,然后我们想看cpu处于c0运行态的比率,那么就直接看mperf变化了多少,

再与固定cpu核心频率tsc相比较就知道了,这就是Busy字段百分比的来历。

另外,还有专门统计处于package Cx和core Cx的增量寄存器,分别是CPU%cx和Pkg%pcx字段的来历。

然后就是跟温度有关的core_temp和package_temp字段,也可以通过相应的msr寄存器根据一个反馈算法

计算出来。

有了turbostat,我们分别对出问题的cpu和正常的cpu进行压力测试(turbostat支持监控一条命令

带来的cpu变化),结果是,在加上负载后,温度上升很少的cpu, C0频率从1512MHZ 升到 1538MHZ,

而在温度上升很多的cpu上,C0运行频率从912MHZ 上升到2085MHZ。所以,目前看来的原因就是,

CPU频率被限制在一个范围内。我们继续查看turbostat的输出,发现还有PkgWatt 这样的字段,

也就是CPU package功率,在两个不同的cpu上,温度上升高的那一款,功率消耗是9.58Watt,而温度上升少的,

是6.98Watt,根据Delta_Temperature = C * P * T, 功率消耗高的那一款温度上升的多。

是谁在控制功率呢? 下面是介绍intel平台RAPL机制的时候了。RAPL是runtime average performance limit

的缩写,顾名思义就是会限制各个cpu,外设,内存条等在一定时间内的功率消耗。我们来看最开始我贴的一套

turbostat的输出,其中的3个MSR寄存器,MSR_PKG_POWER_INFO,MSR PKG Limit #1,MSR PKG Limit #2,

我们把这几个寄存器再贴一下:

cpu0: MSR_PKG_POWER_INFO: 0x00000040 (8 W TDP, RAPL 0 - 0 W, 0.000000
sec.)
cpu0: PKG Limit #1: ENabled (8.000000 Watts, 28.000000 sec, clamp
ENabled)
cpu0: PKG Limit #2: ENabled (10.000000 Watts, 0.002441* sec, clamp
DISabled)<p>
</p>MSR_PKG_POWER_INFO表示的是,在指定时间内,以指定的功耗运行,当时不能超过
MSR PKG Limit #1和MSR PKG Limit #2里的限制,也就是说,在28秒内,最多以8Watts的

速度运行,并且0.002441秒内,不能超过10Watts(峰值),只要没有超过这个峰值,就以8Watt

的额定功率运行。 比较温度升高明显的cpu,和温度升高不明显的cpu的这些数据发现,

前者的限制是8watt / per 28 second, 以及10 watts / per 0.002441 second, 然后根据turbostate

的结果,我故意让turbostat跑了25秒的压力测试(比28秒小),结果发现他消耗的pkg watts达到了

9.6 watts, 大于了额定限制峰值,也就是说,这个配额对他没有生效,他以自己需要的方式按照高频率

执行了压力测试,因此温度提升很多,但在温度提升不大的cpu上,这个额定值是生效了的,因此温度提升不高。

说到最后,原来出问题的反而是温度提升高的那款CPU了,经咨询US team的同事,他也不太清楚怎么回事,可能

是这款cpu的设计问题吧。 先这样,后面有时间再研究。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: