Intel的丢失周期?rdtsc和CPU_CLK_UNHALTED.REF_TSC之间的不一致。

35

在最近的CPU(至少过去十年)中,英特尔提供了三个固定功能的硬件性能计数器,以及各种可配置的性能计数器。这三个固定计数器是:

INST_RETIRED.ANY
CPU_CLK_UNHALTED.THREAD
CPU_CLK_UNHALTED.REF_TSC

第一个计数器统计退休指令的数量,第二个计数器统计实际周期数,最后一个计数器是我们感兴趣的。Intel软件开发手册第3卷对此进行了描述:

当核心不处于停机状态且不处于TM stop-clock状态时,此事件会计算以TSC速率为参考时钟的参考周期数。当核心运行HLT指令或MWAIT指令时,它会进入停机状态。此事件不受核心频率变化(例如P状态)的影响,但计数器的频率与时间戳计数器相同。该事件可以近似计算在核心不处于停机状态和不处于TM stop-clock状态时经过的时间。

因此,对于CPU绑定的循环,我希望这个值与从rdstc读取的自由运行TSC值相同,因为它们只应在停机周期指令或“TM stopclock状态”下分歧。

我使用以下循环进行测试(整个standalone demo is available on github):

for (int i = 0; i < 100; i++) {
    PFC_CNT cnt[7] = {};

    int64_t start = nanos();
    PFCSTART(cnt);
    int64_t tsc =__rdtsc();
    busy_loop(CALIBRATION_LOOPS);
    PFCEND(cnt);
    int64_t tsc_delta   = __rdtsc() - tsc;
    int64_t nanos_delta = nanos() - start;

    printf(CPU_W "d" REF_W ".2f" TSC_W ".2f" MHZ_W ".2f" RAT_W ".6f\n",
            sched_getcpu(),
            1000.0 * cnt[PFC_FIXEDCNT_CPU_CLK_REF_TSC] / nanos_delta,
            1000.0 * tsc_delta / nanos_delta,
            1000.0 * CALIBRATION_LOOPS / nanos_delta,
            1.0 * cnt[PFC_FIXEDCNT_CPU_CLK_REF_TSC]/tsc_delta);
}

在定时区域中唯一重要的是 busy_loop(CALIBRATION_LOOPS);,它只是一个紧密循环的易失性存储器,由gcc和clang编译,在最近的硬件上每次迭代执行一个周期:
void busy_loop(uint64_t iters) {
    volatile int sink;
    do {
        sink = 0;
    } while (--iters > 0);
    (void)sink;
}
PFCSTARTPFCEND命令使用libpfc读取CPU_CLK_UNHALTED.REF_TSC计数器。__rdtsc()是通过rdtsc指令读取TSC的内置函数。最后,我们使用nanos()来测量实际时间,其简单表示为:
int64_t nanos() {
    auto t = std::chrono::high_resolution_clock::now();
    return std::chrono::time_point_cast<std::chrono::nanoseconds>(t).time_since_epoch().count();
}

是的,我不发出 cpuid,事情也没有以精确的方式交错,但是校准循环是一整秒钟,因此这样的纳秒级问题只会被稀释成几乎无影响的状态。
启用 TurboBoost 后,以下是在我的 i7-6700HQ Skylake CPU 上进行典型运行时的前几个结果:
CPU# REF_TSC   rdtsc Eff Mhz     Ratio
   0 2392.05 2591.76 2981.30  0.922946
   0 2381.74 2591.79 3032.86  0.918955
   0 2399.12 2591.79 3032.50  0.925660
   0 2385.04 2591.79 3010.58  0.920230
   0 2378.39 2591.79 3010.21  0.917663
   0 2355.84 2591.77 2928.96  0.908970
   0 2364.99 2591.79 2942.32  0.912492
   0 2339.64 2591.77 2935.36  0.902720
   0 2366.43 2591.79 3022.08  0.913049
   0 2401.93 2591.79 3023.52  0.926747
   0 2452.87 2591.78 3070.91  0.946400
   0 2350.06 2591.79 2961.93  0.906733
   0 2340.44 2591.79 2897.58  0.903020
   0 2403.22 2591.79 2944.77  0.927246
   0 2394.10 2591.79 3059.58  0.923723
   0 2359.69 2591.78 2957.79  0.910449
   0 2353.33 2591.79 2916.39  0.907992
   0 2339.58 2591.79 2951.62  0.902690
   0 2395.82 2591.79 3017.59  0.924389
   0 2353.47 2591.79 2937.82  0.908047

在这里,REF_TSC是上述描述的固定TSC性能计数器,rdtsc是来自rdtsc指令的结果。Eff Mhz是区间内有效计算出的真实CPU频率,大多数情况下仅用于好奇心和快速确认有多少Turbo正在启动。RatioREF_TSCrdtsc列的比率。我希望这个比值非常接近1,但实际上我们看到它在0.90到0.92左右徘徊,并且有很大的变化(我在其他运行中看到它低至0.8)。

图形上看起来像这样2

PMU tsc vs rdstc

< p > rdstc 调用返回几乎 精确 的结果1,而 PMU TSC 计数器则随意变动,有时甚至低至 2300 MHz。

然而,如果我关闭 Turbo,结果会更加一致:

CPU# REF_TSC   rdtsc Eff Mhz     Ratio
   0 2592.26 2592.25 2588.30  1.000000
   0 2592.26 2592.26 2591.11  1.000000
   0 2592.26 2592.26 2590.40  1.000000
   0 2592.25 2592.25 2590.43  1.000000
   0 2592.26 2592.26 2590.75  1.000000
   0 2592.26 2592.26 2590.05  1.000000
   0 2592.25 2592.25 2590.04  1.000000
   0 2592.24 2592.24 2590.86  1.000000
   0 2592.25 2592.25 2590.35  1.000000
   0 2592.25 2592.25 2591.32  1.000000
   0 2592.25 2592.25 2590.63  1.000000
   0 2592.25 2592.25 2590.87  1.000000
   0 2592.25 2592.25 2590.77  1.000000
   0 2592.25 2592.25 2590.64  1.000000
   0 2592.24 2592.24 2590.30  1.000000
   0 2592.23 2592.23 2589.64  1.000000
   0 2592.23 2592.23 2590.83  1.000000
   0 2592.23 2592.23 2590.49  1.000000
   0 2592.23 2592.23 2590.78  1.000000
   0 2592.23 2592.23 2590.84  1.000000
   0 2592.22 2592.22 2588.80  1.000000

基本上,比例为1.000000到6位小数。 图形上(Y轴刻度被强制与前一个图形相同):

PMU vs rdtsc (no turbo)

现在代码只是在运行一个热循环,不应该有“hlt”或“mwait”指令,当然也不会有任何暗示超过10%变化的东西。我不能确定“TM stop-clock cycles”是什么,但我敢打赌它们是“thermal management stop-clock cycles”,这是一种用于在达到最高温度时临时限制CPU的技巧。但是,我查看了集成热敏电阻器的读数,从未看到CPU超过60C,远低于热管理启动的90C-100C(我想)。你有什么想法吗?是否有暗示在不同的Turbo频率之间转换的“halt cycles”?这肯定会发生,因为机箱不安静,所以Turbo频率会上下跳动,其他核心在后台工作(最大Turbo频率直接取决于活动核心数:在我的机器上,分别为1、2、3或4个活动核心时为3.5、3.3、3.2、3.1 GHz)。

1实际上,有一段时间我确实得到了精确的结果,保留两位小数: 2591.97 MHz - 迭代后的结果。然后某些事情发生了变化,我不确定是什么原因,在rdstc结果中有约0.1%的小变化。一个可能性是逐渐进行的时钟调整,由Linux定时子系统进行,以使本地晶体衍生的时间与ntpd确定的时间相一致。也许,这只是晶体漂移 - 上面的最后一个图显示每秒钟测量周期的稳定增加。

2图表与文本中显示的值不对应,因为我不会在更改文本输出格式时更新图表。然而,每次运行时的定性行为基本相同。


评论不适合进行长时间的讨论;此对话已被移至聊天室 - Bhargav Rao
1
现代操作系统使用mwait而不是hlt进行睡眠。不同的mwait寄存器值将CPU置于不同的C状态。但是,无论如何,相同的区别是:当线程准备运行时,操作系统发起的睡眠不应该发生。 - Peter Cordes
1
假设:当CPU改变频率/电压时,时钟会停止,直到稳定在新的频率上。 - Peter Cordes
@peter 还请看一下我在聊天中的评论:当所有核心都处于活动状态时,问题几乎消失了,而如果与温度有关,你会期望相反的情况。 - BeeOnRope
4
@PeterCordes 是的,我也发现了这一点。关于限制,我还找到了一个很棒的 MSR_CORE_PERF_LIMITS_REASONS ,它能很好地显示当前的限制情况。目前,我的CPU套装报告有 Power Limiter 2Max Turbo Limit 的限制情况,但偶尔也会出现 Electrical Design PointTurbo Transition Attenuation 的限制情况。最后一个存在的意义表明英特尔人希望通过某种方式添加滞后来避免过度的 TurboBoost 状态转换。这可能可以配置,也可能不行。 - Iwillnotexist Idonotexist
显示剩余8条评论
1个回答

32

简短总结

RDTSCREFTSC的差异是由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_STATUSIA32_THERM_STATUS MSRs。两者都包含只读状态和可读写、硬件黏性日志标志,用于各种热条件:

IA32_THERM_STATUS register contents (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个时钟周期的过度计数时钟周期量子。但它们不是由于用户-操作系统转换引起的。

这是一个视觉图:

显示量化TurboBoost转换惩罚的图像 饱和蓝点: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)。它可以被调整吗?


3
这段话来自“CORE_PERF_LIMIT_REASONS MSR”的文档。其中的第13位是关于“Turbo Transition Attenuation Status(增压转换衰减状态)”的说明。当被设置时,频率会因为增压转换衰减而降低到操作系统请求以下。这可以防止由于频繁的操作比例变化导致的性能下降。对我而言,这意味着硬件处于其他条件下的下限,但在最近过渡中检测到了太多的变化,因此在我们处于较低的P状态时拒绝了一个升级;它起到一种振荡阻尼器的作用。 - Iwillnotexist Idonotexist
@BeeOnRope,我刚想到一种用手术般精度测量转换时间的方法 - 持续同时轮询 rdtsc 和 reftsc,并尝试通过 rdtsc 相对于 reftsc 的 20k 周期明显跳变来检测 TB 硬件导致的“抢占”。问题在于如何确保“抢占”不会发生在读取 rdtsc 和 reftsc 之间。 - Iwillnotexist Idonotexist
1
应该可以。对我来说,抢占发生的时间并不太重要,如果你像“ABABA”这样来轮询“TSC_REF”(A)和“rdtsc”(B),那么无论抢占(x)是像“ABxABA”还是“ABAxBA”,你都会看到一个大的“B->B”间隔,而所有的“A->A”间隔应该看起来正常,或者如果不正常,那就是两个“A->A”间隔之一,你可以检查两个间隔。从某种意义上说,你甚至不需要“ABABA”,只需要“BBBB”(即只轮询“rdstc”)。 - BeeOnRope
这将捕获所有进程因任何原因而停止的情况,但您始终可以排除其他情况,例如通过检查中断计数。 - BeeOnRope
1
硬件循环占空比仅用于达到TDP水平,低于它们可以使用最大效率最慢的时钟速度。可能甚至常规的ULV笔记本电脑芯片(ix-6xxxU)也不支持它,但是也许能够降至3.5W TDP-down的Core-M CPU可以。请参见http://myeventagenda.com/sessions/0B9F4191-1C29-408A-8B61-65D7520025A8/7/5#sessionID=155(来自Skylake的领先客户端功率架构师Efraim Rotem的IDF2015演讲音频+幻灯片)。16个周期非常短,也许不是那种循环占空比。@BeeOnRope:其中有一些关于SKL其他频率切换决策的相关内容。 - Peter Cordes
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接