简短总结
RDTSC
和REFTSC
的差异是由TurboBoost P状态转换引起的。在这些转换期间,包括固定功能性能计数器REF_TSC
在内的大多数核心都会停止大约20000-21000个周期(8.5微秒),但rdtsc
会以其不变频率继续运行。由于其重要性和记录类似于墙时钟的行为,rdtsc
可能处于隔离的电源和时钟域中。
RDTSC-REFTSC
的差异
差异表现为RDTSC
过度计数REFTSC
的趋势。程序运行时间越长,RDTSC-REFTSC
的差异越大。在非常长的时间段内,它可以高达1%-2%甚至更高。
当禁用TurboBoost时,overcounting
消失,可以通过以下方式禁用:intel_pstate
echo 1 > /sys/devices/system/cpu/intel_pstate/no_turbo
但这并不能确定TurboBoost是造成偏差的罪魁祸首;可能是TurboBoost启用的更高P-State消耗了可用余地,导致热限制和停机。
可能存在限制?
TurboBoost是一种动态频率和电压调节解决方案,可以机会主义地利用操作范围内的余地(热或电)。如果可能,TurboBoost将扩展处理器的核心频率和电压超出其名义值,从而在牺牲更高功耗的情况下提高性能。
当然,更高的功耗会增加核心温度和功耗。最终,某种限制将被触发,TurboBoost将不得不降低性能。
TM1热限制?
我开始调查热控制电路(TCC)是否会导致热限制,包括Thermal Monitor 1(TM1)或2(TM2)。 TM1通过插入TM停止时钟周期来减少功耗,这是导致
REFTSC
停机的已记录条件之一。另一方面,TM2不对时钟进行门控;它只缩放频率。
我修改了
libpfc()
以使我能够读取选择的MSR,特别是
IA32_PACKAGE_THERM_STATUS
和
IA32_THERM_STATUS
MSRs。两者都包含只读状态和可读写、硬件黏性日志标志,用于各种热条件:
(IA32_PACKAGE_THERM_STATUS寄存器基本相同)
尽管有些位偶尔会被设置(特别是在阻止笔记本电脑散热口时!),但它们似乎与RDTSC
的过度计数没有关联,而后者无论热状态如何都会可靠地发生。
硬件循环休眠?C状态驻留?
在SDM中寻找类似于停止时钟的硬件时,我偶然发现了HDC(Hardware Duty Cycle),这是一种机制,通过该机制,操作系统可以手动请求CPU仅在固定比例的时间内运行; HDC硬件通过在16个时钟周期中运行处理器1-15个时钟周期并强制空闲其余的15-1个时钟周期来实现此目的。
HDC提供非常有用的寄存器,特别是MSR:
IA32_THREAD_STALL
: 统计此逻辑处理器因强制空闲而停滞的周期数。
MSR_CORE_HDC_RESIDENCY
: 与上述类似,但是针对物理处理器,计算在该核心的一个或多个逻辑处理器被强制空闲时的周期数。
MSR_PKG_HDC_SHALLOW_RESIDENCY
: 计算包处于 C2 状态且至少有一个逻辑处理器被强制空闲的周期数。
MSR_PKG_HDC_DEEP_RESIDENCY
: 计算包处于更深的(精确配置)C-state 且至少有一个逻辑处理器被强制空闲的周期数。
有关详细信息,请参阅英特尔 SDM 第三卷第14章第14.5.1节“硬件 Duty Cycling 编程接口”。
但是我的 i7-4700MQ 2.4 GHz CPU 不支持 HDC,所以 HDC 就无从谈起了。
其他限制来源?
在英特尔 SDM 中继续查找,我发现了一个非常非常有用的 MSR:MSR_CORE_PERF_LIMIT_REASONS
。此寄存器报告大量有用的状态和粘性日志位:
690H MSR_CORE_PERF_LIMIT_REASONS - 包 - 处理器核心频率限制指示器
- 位
0
: PROCHOT 状态
- 位
1
: 热状态
- 位
4
: 图形驱动程序状态。当设置时,由于处理器图形驱动程序覆盖,频率降低到操作系统请求以下。
- 位
5
: 自治利用率控制状态。当设置时,由于处理器检测到利用率较低,频率降低到操作系统请求以下。
- 位
6
: 电压调节器热警报状态。当设置时,由于来自电压调节器的热警报,频率降低到操作系统请求以下。
- 位
8
: 电气设计点状态。当设置时,由于电气设计点约束(例如最大电流消耗),频率降低到操作系统请求以下。
- 位
9
: 核心功率限制状态。当设置时,由于域级功率限制,频率降低到操作系统请求以下。
- 位
10
: 包级功率限制 PL1 状态。当设置时,由于包级功率限制 PL1,频率降低到操作系统请求以下。
- 位
11
: 包级功率限制 PL2 状态。当设置时,由于包级功率限制 PL2,频率降低到操作系统请求以下。
- 位
12
: 最大 Turbo 限制状态。当设置时,由于多核心 Turbo 限制,频率降低到操作系统请求以下。
- 位
13
: Turbo 过渡衰减状态。当设置时,由于 Turbo 过渡衰减,频率降低到操作系统请求以下。这可以防止由于频繁的操作比例更改而导致性能下降。
- 位
16
: PROCHOT 日志
- 位
17
: 热日志
- 位
20
: 图形驱动程序日志
- 位
21
: 自治利用率控制日志
- 位
22
: 电压调节器热警报日志
- 位
24
: 电气设计点日志
- 位
25
: 核心功率限制日志
- 位
26
: 包级功率限制 PL1 日志
- 位
27
: 包级功率限制 PL2 日志
- 位
28
: 最大 Turbo 限制日志
- 位
29
: Turbo 过渡衰减日志
pfc.ko
现在支持这个MSR,一个demo会打印出哪些日志位是活动的。每次读取时,pfc.ko
驱动程序都会清除粘性位。
我在打印位时重新运行了你的实验,并且我的CPU在非常重载(所有4个核心/8个线程都活跃)的情况下报告了几个限制因素,包括电气设计点和核心功率限制。对于我来说,Package-Level PL2 and Max Turbo Limit位总是设置为always set,原因不明。我还偶尔看到Turbo Transition Attenuation。
虽然这些位中没有一个恰好与RDTSC-REFTSC
差异的存在相关,但最后一位让我思考。Turbo Transition Attenuation的存在仅仅意味着切换P-State具有足够大的成本,必须使用一些滞后机制进行速率限制。当我找不到计数这些转换的MSR时,我决定做下一件最好的事情 - 我将使用RDTSC-REFTSC
过度计数的幅度来表征TurboBoost转换的性能影响。
实验
实验设置如下。在我的i7-4700MQ CPU上,名义速度为2.4GHz,最大Turbo速度为3.4 GHz,我将离线除0(引导处理器)和3(一个方便的受害者核心,不编号为0且不是0的逻辑同级)以外的所有核心。然后,我们将要求intel_pstate
驱动程序为我们提供不低于98%且不高于100%的包性能;这将限制处理器在第二高和最高P状态之间(3.3 GHz和3.4 GHz)振荡。我按照以下方式执行此操作:
echo 0 > /sys/devices/system/cpu/cpu1/online
echo 0 > /sys/devices/system/cpu/cpu2/online
echo 0 > /sys/devices/system/cpu/cpu4/online
echo 0 > /sys/devices/system/cpu/cpu5/online
echo 0 > /sys/devices/system/cpu/cpu6/online
echo 0 > /sys/devices/system/cpu/cpu7/online
echo 98 > /sys/devices/system/cpu/intel_pstate/min_perf_pct
echo 100 > /sys/devices/system/cpu/intel_pstate/max_perf_pct
我运行了demo应用程序,对10000个样本进行了测试
1000, 1500, 2500, 4000, 6300,
10000, 15000, 25000, 40000, 63000,
100000, 150000, 250000, 400000, 630000,
1000000, 1500000, 2500000, 4000000, 6300000,
10000000, 15000000, 25000000, 40000000, 63000000
每次执行add_calibration()
所需的纳秒数,以名义CPU频率计算(将上面的数字乘以2.4即可获得add_calibration()
的实际参数)。
结果
这会产生类似于以下日志的输出(250000纳秒的情况):
CPU 0, measured CLK_REF_TSC MHz : 2392.56
CPU 0, measured rdtsc MHz : 2392.46
CPU 0, measured add MHz : 3286.30
CPU 0, measured XREF_CLK time (s) : 0.00018200
CPU 0, measured delta time (s) : 0.00018258
CPU 0, measured tsc_delta time (s) : 0.00018200
CPU 0, ratio ref_tsc :ref_xclk : 24.00131868
CPU 0, ratio ref_core:ref_xclk : 33.00071429
CPU 0, ratio rdtsc :ref_xclk : 24.00032967
CPU 0, core CLK cycles in OS : 0
CPU 0, User-OS transitions : 0
CPU 0, rdtsc-reftsc overcount : -18
CPU 0, MSR_IA32_PACKAGE_THERM_STATUS : 000000008819080a
CPU 0, MSR_IA32_PACKAGE_THERM_INTERRUPT: 0000000000000003
CPU 0, MSR_CORE_PERF_LIMIT_REASONS : 0000000018001000
PROCHOT
Thermal
Graphics Driver
Autonomous Utilization-Based Frequency Control
Voltage Regulator Thermal Alert
Electrical Design Point (e.g. Current)
Core Power Limiting
Package-Level PL1 Power Limiting
* Package-Level PL2 Power Limiting
* Max Turbo Limit (Multi-Core Turbo)
Turbo Transition Attenuation
CPU 0, measured CLK_REF_TSC MHz : 2392.63
CPU 0, measured rdtsc MHz : 2392.62
CPU 0, measured add MHz : 3288.03
CPU 0, measured XREF_CLK time (s) : 0.00018192
CPU 0, measured delta time (s) : 0.00018248
CPU 0, measured tsc_delta time (s) : 0.00018192
CPU 0, ratio ref_tsc :ref_xclk : 24.00000000
CPU 0, ratio ref_core:ref_xclk : 32.99983509
CPU 0, ratio rdtsc :ref_xclk : 23.99989006
CPU 0, core CLK cycles in OS : 0
CPU 0, User-OS transitions : 0
CPU 0, rdtsc-reftsc overcount : -2
CPU 0, MSR_IA32_PACKAGE_THERM_STATUS : 000000008819080a
CPU 0, MSR_IA32_PACKAGE_THERM_INTERRUPT: 0000000000000003
CPU 0, MSR_CORE_PERF_LIMIT_REASONS : 0000000018001000
PROCHOT
Thermal
Graphics Driver
Autonomous Utilization-Based Frequency Control
Voltage Regulator Thermal Alert
Electrical Design Point (e.g. Current)
Core Power Limiting
Package-Level PL1 Power Limiting
* Package-Level PL2 Power Limiting
* Max Turbo Limit (Multi-Core Turbo)
Turbo Transition Attenuation
CPU 0, measured CLK_REF_TSC MHz : 2284.69
CPU 0, measured rdtsc MHz : 2392.63
CPU 0, measured add MHz : 3151.99
CPU 0, measured XREF_CLK time (s) : 0.00018121
CPU 0, measured delta time (s) : 0.00019036
CPU 0, measured tsc_delta time (s) : 0.00018977
CPU 0, ratio ref_tsc :ref_xclk : 24.00000000
CPU 0, ratio ref_core:ref_xclk : 33.38540919
CPU 0, ratio rdtsc :ref_xclk : 25.13393301
CPU 0, core CLK cycles in OS : 0
CPU 0, User-OS transitions : 0
CPU 0, rdtsc-reftsc overcount : 20548
CPU 0, MSR_IA32_PACKAGE_THERM_STATUS : 000000008819080a
CPU 0, MSR_IA32_PACKAGE_THERM_INTERRUPT: 0000000000000003
CPU 0, MSR_CORE_PERF_LIMIT_REASONS : 0000000018000000
PROCHOT
Thermal
Graphics Driver
Autonomous Utilization-Based Frequency Control
Voltage Regulator Thermal Alert
Electrical Design Point (e.g. Current)
Core Power Limiting
Package-Level PL1 Power Limiting
* Package-Level PL2 Power Limiting
* Max Turbo Limit (Multi-Core Turbo)
Turbo Transition Attenuation
CPU 0, measured CLK_REF_TSC MHz : 2392.46
CPU 0, measured rdtsc MHz : 2392.45
CPU 0, measured add MHz : 3287.80
CPU 0, measured XREF_CLK time (s) : 0.00018192
CPU 0, measured delta time (s) : 0.00018249
CPU 0, measured tsc_delta time (s) : 0.00018192
CPU 0, ratio ref_tsc :ref_xclk : 24.00000000
CPU 0, ratio ref_core:ref_xclk : 32.99978012
CPU 0, ratio rdtsc :ref_xclk : 23.99989006
CPU 0, core CLK cycles in OS : 0
CPU 0, User-OS transitions : 0
CPU 0, rdtsc-reftsc overcount : -2
CPU 0, MSR_IA32_PACKAGE_THERM_STATUS : 000000008819080a
CPU 0, MSR_IA32_PACKAGE_THERM_INTERRUPT: 0000000000000003
CPU 0, MSR_CORE_PERF_LIMIT_REASONS : 0000000018001000
PROCHOT
Thermal
Graphics Driver
Autonomous Utilization-Based Frequency Control
Voltage Regulator Thermal Alert
Electrical Design Point (e.g. Current)
Core Power Limiting
Package-Level PL1 Power Limiting
* Package-Level PL2 Power Limiting
* Max Turbo Limit (Multi-Core Turbo)
Turbo Transition Attenuation
我对日志进行了几次观察,但其中一项突出:
对于纳秒 < ~250000,RDTSC 几乎没有过度计数。对于纳秒 > ~250000,可以可靠地观察到略高于20000个时钟周期的过度计数时钟周期量子。但它们不是由于用户-操作系统转换引起的。
这是一个视觉图:
饱和蓝点:0个标准偏差(接近均值)
饱和红点:+3个标准偏差(高于均值)
饱和绿点:-3个标准偏差(低于均值)
在大约250000纳秒的持续递减之前、期间和之后,存在显着差异。
纳秒 < 250000
在阈值之前,CSV 日志如下所示:
24.00,33.00,24.00,-14,0,0
24.00,33.00,24.00,-20,0,0
24.00,33.00,24.00,-4,3639,1
24.00,33.00,24.00,-20,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,-14,0,0
24.00,33.00,24.00,-14,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,-44,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,-14,0,0
24.00,33.00,24.00,-20,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,-20,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,12,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,10,0,0
24.00,33.00,24.00,-20,0,0
24.00,33.00,24.00,32,3171,1
24.00,33.00,24.00,-20,0,0
24.00,33.00,24.00,10,0,0
Indicating a TurboBoost ratio perfectly stable at 33x, an
RDTSC
that counts in synchrony with
REFTSC
at 24x the rate of
REF_XCLK
(100 MHz), negligible overcounting, typically 0 cycles spent in the kernel and thus 0 transitions into the kernel. Kernel interrupts take approximately 3000 reference cycles to service.
Nanos == 250000
At the critical threshold, the log contains clumps of 20000 cycle overcounts, and the overcounts correlate very well with non-integer estimated multiplier values between 33x and 34x:
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,2,0,0
24.00,33.00,24.00,22,0,0
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,-2,0,0
24.00,33.05,25.11,20396,0,0
24.00,33.38,25.12,20212,0,0
24.00,33.39,25.12,20308,0,0
24.00,33.42,25.12,20296,0,0
24.00,33.43,25.11,20158,0,0
24.00,33.43,25.11,20178,0,0
24.00,33.00,24.00,-4,0,0
24.00,33.00,24.00,20,3920,1
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,-4,0,0
24.00,33.44,25.13,20396,0,0
24.00,33.46,25.11,20156,0,0
24.00,33.46,25.12,20268,0,0
24.00,33.41,25.12,20322,0,0
24.00,33.40,25.11,20216,0,0
24.00,33.46,25.12,20168,0,0
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,-2,0,0
24.00,33.00,24.00,22,0,0
Nanos > 250000
当纳秒数超过250000时,TurboBoost会可靠地从3.3 GHz提升到3.4 GHz。随着纳秒数的增加,日志中填充了大约整数倍于20000周期量子的记录。最终,纳秒数变得如此之多,以至于Linux调度程序中断成为永久性固定物,但可以轻松使用性能计数器检测到抢占,并且其效果与TurboBoost停止完全不同。
24.00,33.75,24.45,20166,0,0
24.00,33.78,24.45,20302,0,0
24.00,33.78,24.45,20202,0,0
24.00,33.68,24.91,41082,0,0
24.00,33.31,24.90,40998,0,0
24.00,33.70,25.30,58986,3668,1
24.00,33.74,24.42,18798,0,0
24.00,33.74,24.45,20172,0,0
24.00,33.77,24.45,20156,0,0
24.00,33.78,24.45,20258,0,0
24.00,33.78,24.45,20240,0,0
24.00,33.77,24.42,18826,0,0
24.00,33.75,24.45,20372,0,0
24.00,33.76,24.42,18798,4081,1
24.00,33.74,24.41,18460,0,0
24.00,33.75,24.45,20234,0,0
24.00,33.77,24.45,20284,0,0
24.00,33.78,24.45,20150,0,0
24.00,33.78,24.45,20314,0,0
24.00,33.78,24.42,18766,0,0
24.00,33.71,25.36,61608,0,0
24.00,33.76,24.45,20336,0,0
24.00,33.78,24.45,20234,0,0
24.00,33.78,24.45,20210,0,0
24.00,33.78,24.45,20210,0,0
24.00,33.00,24.00,-10,0,0
24.00,33.00,24.00,4,0,0
24.00,33.00,24.00,18,0,0
24.00,33.00,24.00,2,4132,1
24.00,33.00,24.00,44,0,0
结论
TurboBoost机制是导致RDTSC-REFTSC
出现差异的原因。这种差异可以用来确定从3.3 GHz到3.4 GHz的TurboBoost状态转换需要大约20500个参考时钟周期(8.5us),并且在进入add_reference()
后不迟于约250000 ns(250us; 600000个参考时钟周期)触发,当处理器决定工作负载足够强烈以值得进行频率电压缩放时。
未来工作
需要进行更多研究以确定转换成本如何随频率变化,并且是否可以调整选择电源状态的硬件。我特别感兴趣的是“Turbo衰减单元”,我在网络的边缘看到了一些提示。也许Turbo硬件有一个可配置的时间窗口?目前决策花费时间与过渡花费时间的比例为30:1(600us:20us)。它可以被调整吗?
mwait
而不是hlt
进行睡眠。不同的mwait
寄存器值将CPU置于不同的C状态。但是,无论如何,相同的区别是:当线程准备运行时,操作系统发起的睡眠不应该发生。 - Peter CordesMSR_CORE_PERF_LIMITS_REASONS
,它能很好地显示当前的限制情况。目前,我的CPU套装报告有 Power Limiter 2 和 Max Turbo Limit 的限制情况,但偶尔也会出现 Electrical Design Point 和 Turbo Transition Attenuation 的限制情况。最后一个存在的意义表明英特尔人希望通过某种方式添加滞后来避免过度的 TurboBoost 状态转换。这可能可以配置,也可能不行。 - Iwillnotexist Idonotexist