> Coreinfo.exe
Coreinfo v3.2 - Dump information on system CPU and memory topology
Sysinternals - www.sysinternals.com
<unrelated text removed>
RDTSCP * Supports RDTSCP instruction
TSC * Supports RDTSC instruction
TSC-DEADLINE - Local APIC supports one-shot deadline timer
TSC-INVARIANT * TSC runs at constant rate
整数除法将失去余数。 在某些情况下,这可能会导致精度损失。
64 位整数与浮点 (双) 之间的转换可能会导致精度损失,因为浮点 mantissa 无法表示所有可能的整数值。
64 位整数的乘法可能会导致整数溢出。
作为一般原则,应尽可能长时间地延迟这些计算和转换,以避免使引入的错误复杂化。
如何将 QPC 转换为 100 纳秒时钟周期,以便将其添加到 FILETIME?
文件时间是一个 64 位值,表示自 1601 年 1 月 1 日凌晨 12:00(协调世界时 (UTC) )以来经过的 100 纳秒间隔数。 文件时间由返回当天时间的 Win32 API 调用使用,例如 GetSystemTimeAsFileTime 和 GetSystemTimePreciseAsFileTime。 相比之下, QueryPerformanceCounter 返回的值表示时间(单位为 1/ (从 QueryPerformanceFrequency) 获取的性能计数器的频率)。 两者之间的转换需要计算 QPC 间隔和 100 纳秒间隔的比率。 请小心避免丢失精度,因为值可能较小, (0.0000001 / 0.000000340) 。
是否需要将线程相关性设置为单个核心才能使用 QPC?
否。 有关详细信息,请参阅 获取时间戳的指南。 此方案既没有必要也不必要。 如果多个线程在调用 QueryPerformanceCounter 时将其相关性设置为同一个核心,则执行此方案可能会对应用程序的性能产生负面影响,方法是将处理限制为一个核心,或者在单个核心上造成瓶颈。
低级别硬件时钟特征
这些部分显示了低级别硬件时钟特征。
绝对时钟和差异时钟
绝对时钟提供准确的一天中的时间读数。 它们通常基于协调世界时 (UTC) ,因此其准确性在一定程度上取决于它们与外部时间参考的同步程度。 差异时钟测量时间间隔,通常不基于外部时间纪元。
QPC 是一个差异时钟,不会同步到外部时间纪元或引用。 使用 QPC 进行时间间隔度量时,通常比使用派生自绝对时钟的时间戳获得更好的准确度。 这是因为同步绝对时钟的时间的过程可能会引入相位和频率偏移,从而增加短期时间间隔测量的不确定性。
分辨率、精度、准确性和稳定性
QPC 使用硬件计数器作为其基础。 硬件计时器由三个部分组成:时钟周期生成器、计数时钟周期的计数器和检索计数器值的方法。 这三个分量的特征决定了 QPC 的分辨率、精度、准确性和稳定性。
如果硬件生成器以恒定速率提供时钟周期,则只需计算这些时钟周期即可测量时间间隔。 时钟周期的生成速率称为频率,以Hz (Hz) 表示。 频率的倒数称为周期或刻度间隔,以适当的国际单位制 (SI) 时间单位 (表示,例如秒、毫秒、微秒或纳秒) 。
QueryPerformanceFrequency 返回 QPC 的频率,并且周期和分辨率等于此值的倒数。
QueryPerformanceFrequency 返回的性能计数器频率在系统初始化期间确定,在系统运行时不会更改。
通常,QueryPerformanceFrequency 不会返回硬件时钟周期生成器的实际频率。 例如,在某些较旧版本的 Windows 中,QueryPerformanceFrequency 返回除以 1024 的 TSC 频率;在实现虚拟机监控程序版本 1.0 接口的虚拟机监控程序 (或始终在某些较新版本的 Windows) 下运行时,性能计数器频率固定为 10 MHz。 因此,不要假定 QueryPerformanceFrequency 将返回派生自硬件频率的值。
QueryPerformanceCounter 读取性能计数器并返回自 Windows 操作系统启动以来发生的时钟周期总数,包括计算机处于睡眠状态(如待机、休眠或连接待机)的时间。
这些示例演示如何计算时钟周期间隔和分辨率,以及如何将刻度计数转换为时间值。
QueryPerformanceFrequency 在特定计算机上返回值 3,125,000。 此计算机上的 QPC 测量的刻度间隔和分辨率是多少? 刻度间隔(或周期)是 3,125,000 的倒数,即 0.000000320 (320 纳秒) 。 因此,每个刻度表示 320 纳秒的传递。 在此计算机上无法测量小于 320 纳秒的时间间隔。
时钟周期间隔 = 1/ (性能频率)
时钟周期间隔 = 1/3,125,000 = 320 ns
在与前面的示例相同的计算机上,连续两次调用 QPC 返回的值之差为 5。 两个调用之间已经过去了多少时间? 5 个刻度乘以 320 纳秒产生 1.6 微秒。
ElapsedTime = Ticks * Tick Interval
ElapsedTime = 5 * 320 ns = 1.6μs
访问 (从软件读取) 计时周期计数器需要一些时间,并且此访问时间可能会降低时间度量的精度。 这是因为最小间隔时间 (可以测量的最小时间间隔) 是分辨率和访问时间的较大。
Precision = MAX [ Resolution, AccessTime]
例如,假设硬件计时器的分辨率为 100 纳秒,访问时间为 800 纳秒。 如果使用平台计时器而不是 TSC 寄存器作为 QPC 的基础,则可能发生这种情况。 因此,精度为 800 纳秒,而不是 100 纳秒,如此计算所示。
精度 = MAX [800 ns,100 ns] = 800 ns
这两个数字描绘了这种效果。
由于 QPC 使用硬件计数器,因此了解硬件计数器的一些基本特征后,即可了解 QPC 的功能和限制。
最常用的硬件时钟周期生成器是晶体振荡器。 晶体是一小块石英或其他陶瓷材料,具有压电特性,提供廉价的频率参考,具有出色的稳定性和准确性。 此频率用于生成时钟计数的计时周期。
计时器的准确性是指与 true 或标准值的一致性程度。 这主要取决于晶体振子以指定频率提供滴答声的能力。 如果振荡频率过高,时钟将“快速运行”,测量的间隔看起来比实际更长:如果频率太低,时钟将“运行缓慢”,测量的间隔看起来比实际时间短。
对于持续时间较短的典型时间间隔度量 (例如响应时间度量、网络延迟度量等) ,硬件振子的准确度通常已足够。 但是,对于某些测量,振荡频率精度变得很重要,尤其是对于较长时间间隔或想要比较不同计算机上的度量值时。 本部分的其余部分探讨振荡精度的影响。
晶体的振荡频率在制造过程中设置,由制造商根据指定频率加减以“百万分之几” (ppm) (称为最大频率偏移量)表示的制造容差来指定。 指定频率为 1,000,000 Hz 且最大频率偏移量为 ± 10 ppm 的晶体,如果其实际频率介于 999,990 Hz 到 1,000,010 Hz 之间,则其实际频率在规范范围内。
通过将每百万个短语部分替换为微秒/秒,我们可以将此频率偏移误差应用于时间间隔度量。 偏移量为 + 10 ppm 的振子的误差为每秒 10 微秒。 因此,在测量 1 秒间隔时,它会快速运行,并将 1 秒间隔测量为 0.999990 秒。
一个方便的参考是,100 ppm 的频率误差会导致 24 小时后 8.64 秒的错误。 此表显示了由于累积误差在较长时间间隔内造成的测量不确定性。
时间间隔持续时间
+/- 10 PPM 频率容差累积误差导致的测量不确定性
上表显示,对于较小的时间间隔,通常可以忽略频率偏移误差。 但是,在较长的时间间隔内,即使频率偏移较小,也可能导致较大的测量不确定性。
在个人电脑和服务器中使用的晶体振荡器通常以± 30 到 500 万分之一的频率容差制造,而且很少,晶体的偏差高达 500 ppm。 尽管提供频率偏移容差要小得多的晶体,但它们更昂贵,因此在大多数计算机中不使用。
为了减少此频率偏移误差的不利影响,最新版本的 Windows(尤其是Windows 8)使用多个硬件计时器来检测频率偏移并尽可能对其进行补偿。 此校准过程在 Windows 启动时执行。
如以下示例所示,硬件时钟的频率偏移误差会影响可实现的准确度,而时钟的分辨率可能不那么重要。
假设使用分辨率为 1 微秒的 1 MHz 振动器执行时间间隔测量,最大频率偏移误差为 ±50 ppm。 现在,假设偏移量正好为 +50 ppm。 这意味着实际频率为 1,000,050 Hz。 如果我们测量的时间间隔为 24 小时,则测量时间太短 4.3 秒 (23:59:55.7000000,而实际) 为 24:00:00.00.000000 秒。
一天中的秒数 = 86400
频率偏移误差 = 50 ppm = 0.00005
86,400 秒 * 0.00005 = 4.3 秒
假设处理器 TSC 时钟由晶体振动器控制,其指定频率为 3 GHz。 这意味着分辨率为1/3,000,000,000或约333皮秒。 假设用于控制处理器时钟的晶体的频率容差为 ±50 ppm,实际上为 +50 ppm。 尽管分辨率令人印象深刻,但 24 小时的时间间隔测量仍然太短 4.3 秒。 (23:59:55.70000000000,实际) 为 24:00:00.0000000000。
一天中的秒数 = 86400
频率偏移误差 = 50 ppm = 0.00005
86,400 秒 * 0.00005 = 4.3 秒
这表明高分辨率 TSC 时钟不一定比较低分辨率的时钟提供更准确的测量。
请考虑使用两台不同的计算机来测量相同的 24 小时时间间隔。 两台计算机都具有最大频率偏移量为 ± 50 ppm 的振动。 这两个系统上同一时间间隔的测量可以相距多远? 与前面的示例一样,± 50 ppm 在 24 小时后产生最大误差± 4.3 秒。 如果一个系统运行速度快 4.3 秒,另一个系统运行速度慢 4.3 秒,则 24 小时后的最大误差可能是 8.6 秒。
一天中的秒数 = 86400
频率偏移误差 = ±50 ppm = ±0.00005
± (86,400 秒 * 0.00005) = ±4.3 秒
两个系统之间的最大偏移量 = 8.6 秒
总之,在测量较长的时间间隔以及比较不同系统之间的度量值时,频率偏移误差变得越来越重要。
计时器的稳定性描述滴答频率是否随时间而变化,例如,温度变化的结果。 用作计算机上滴答生成器的硅晶体将随着温度的函数而表现出微小的频率变化。 与常见温度范围的频率偏移误差相比,热偏移引起的误差通常较小。 但是,便携式设备或受较大温度波动影响的设备的软件设计人员可能需要考虑这种影响。
硬件计时器信息
TSC 寄存器 (x86 和 x64)
所有现代 Intel 和 AMD 处理器都包含一个 TSC 寄存器,该寄存器是一个 64 位寄存器,该寄存器以高速率增加,通常等于处理器时钟。 可以通过 RDTSC 或 RDTSCP 计算机指令读取此计数器的值,从而提供非常低的访问时间和计算成本(以几十或数百个计算机周期的顺序,具体取决于处理器)。
尽管 TSC 寄存器似乎是一种理想的时间戳机制,但在以下情况下,它无法可靠地运行以实现计时:
并非所有处理器都具有可用 TSC 寄存器,因此在软件中使用 TSC 寄存器会直接产生可移植性问题。 在这种情况下, (Windows 将为 QPC 选择备用时间源,从而避免可移植性问题。)
某些处理器可能会改变 TSC 时钟的频率或停止 TSC 寄存器的提升,这使得 TSC 不适合在这些处理器上用于计时目的。 这些处理器据说具有非固定 TSC 寄存器。 (Windows 会自动检测到此问题,并为 QPC) 选择备用时间源。
即使虚拟化主机具有可用 TSC,当目标虚拟化主机没有或利用硬件辅助 TSC 缩放时,实时迁移正在运行的虚拟机也可能导致 TSC 频率的变化,而来宾可以看到。 (如果来宾可以进行这种类型的实时迁移,则虚拟机监控程序应清除 CPUID.)
在多处理器或多核系统上,某些处理器和系统无法将每个内核上的时钟同步到相同的值。 (Windows 会自动检测到此问题,并为 QPC) 选择备用时间源。
在某些大型多处理器系统上,即使处理器具有固定 TSC,也可能无法将处理器时钟同步到相同的值。 (Windows 会自动检测到此问题,并为 QPC) 选择备用时间源。
某些处理器将无序执行指令。 当使用 RDTSC 对指令序列进行计时时,这可能会导致错误的周期计数,因为 RDTSC 指令的执行时间可能与程序中指定的时间不同。 为了响应此问题,已在某些处理器上引入了 RDTSCP 指令。
与其他计时器一样,TSC 基于一个事先不知道其确切频率且具有频率偏移误差的晶体晶体。 因此,在使用它之前,必须使用另一个计时参考对其进行校准。
在系统初始化期间,Windows 会检查 TSC 是否适合计时目的,并执行必要的频率校准和核心同步。
pm 时钟 (x86 和 x64)
ACPI 计时器(也称为 PM 时钟)已添加到系统体系结构中,以提供独立于处理器速度的可靠时间戳。 由于这是此计时器的单一目标,因此它在单个时钟周期中提供时间戳,但不提供任何其他功能。
HPET 计时器 (x86 和 x64)
高精度事件计时器 (HPET) 由 Intel 和 Microsoft 联合开发,以满足多媒体和其他时间敏感型应用程序的计时要求。 与 TSC(按处理器资源)不同,HPET 是平台范围的共享资源,尽管一个系统可能具有多个 HPET。 自 Windows Vista 起,HPET 支持一直在 Windows 中,Windows 7 和 Windows 8 硬件徽标认证需要硬件平台中的 HPET 支持。
通用计时器系统计数器 (Arm)
基于 Arm 的平台没有 TSC、HPET 或 PM 时钟,因为基于 Intel 或 AMD 的平台上有。 相反,Arm 处理器提供泛型计时器 (有时称为泛型间隔计时器,或 GIT) ,其中包含系统计数器寄存器 (例如,CNTVCT_EL0) 。 通用计时器系统计数器是固定频率的平台范围时间源。 它在启动时从零开始,以较高的速度增加。 在 Armv8.6 或更高版本中,这定义为恰好 1 GHz,但应通过读取由早期启动固件设置的时钟频率寄存器来确定。 有关详细信息,请参阅 DDI 0487) (“AArch64 状态中的通用计时器”一章。
循环计数器 (Arm)
基于 Arm 的平台提供性能监视器周期计数器寄存器 (例如,PMCCNTR_EL0) 。 此计数器对处理器时钟周期进行计数。 它是非固定的,其单位可能与实时不相关。 不建议使用此寄存器来获取时间戳。