C# 计时器的测量精度(例如秒表/查询性能计数器)
考虑到C#中的C# 计时器的测量精度(例如秒表/查询性能计数器),c#,performance,benchmarking,stopwatch,microbenchmark,C#,Performance,Benchmarking,Stopwatch,Microbenchmark,考虑到C#中的秒表类可以在下面使用三个不同的计时器,例如 系统计时器,例如精度约为+-10 ms,取决于可用其设置的计时器分辨率,精度约为+-1 ms 时间戳计数器(TSC),例如,滴答频率为2.5MHz或1滴答=400 ns,因此理想情况下精度为该值 高精度事件计时器(HPET),例如,滴答频率为25MHz或1滴答=40ns,因此理想情况下为该精度 我们如何测量这一点的可观测精度?精度定义为 精度是指两个或多个测量值之间的接近程度 其他的 现在,如果秒表使用HPET,这是否意味着我们可以使
秒表
类可以在下面使用三个不同的计时器,例如
- 系统计时器,例如精度约为
,取决于可用其设置的计时器分辨率,精度约为+-10 ms
+-1 ms
- 时间戳计数器(TSC),例如,滴答频率为2.5MHz或1滴答=
,因此理想情况下精度为该值400 ns
- 高精度事件计时器(HPET),例如,滴答频率为25MHz或1滴答=
,因此理想情况下为该精度40ns
秒表
使用HPET,这是否意味着我们可以使用秒表
获得与计时器频率相等的精度测量值
我不这么认为,因为这要求我们能够使用零方差或完全固定开销的计时器,据我所知,这对于秒表是不正确的。例如,在使用HPET和调用时:
var before_ticks = Stopwatch.GetTimestamp();
var after_ticks = Stopwatch.GetTimestamp();
var diff_ticks = after_ticks - before_ticks;
然后差值大约为100个刻度
或4000纳秒
,并且也会有一些变化
那么,如何通过实验测量秒表的可观测精度呢?所以它支持所有可能的定时器模式
我的想法是搜索最小滴答数!=0,首先确定系统计时器的秒表
滴答声的开销,这将是0,直到例如10ms
,这是10*1000*10=100000滴答声,因为系统计时器的滴答声分辨率为100ns
,但精度远非如此。对于HPET,它永远不会为0,因为调用Stopwatch.GetTimestamp()
的开销高于计时器的频率
但这并没有说明我们可以用计时器测量的精确程度。我的定义是,我们能够可靠地测量的滴答声差异有多小
可以通过测量不同的迭代次数来执行搜索:
var before = Stopwatch.GetTimestamp();
for (int i = 0; i < iterations; ++i)
{
action(); // Calling a no-op delegate Action since this cannot be inlined
}
var after = Stopwatch.GetTimestamp();
var before=Stopwatch.GetTimestamp();
对于(int i=0;i
首先,可以找到一个下限,即给定次数的迭代的所有10次测量都会产生非零的滴答声,将这些测量保存在长滴答声[10]
中。然后,产生刻度差的最接近可能的迭代次数始终高于前10个测量值中的任何一个,请将其保存在long ticksuper[10]
中
最坏情况下的精度将是ticksuper
中的最高刻度减去ticksleer
中的最低刻度
这听起来合理吗
为什么我想知道秒表的可观测精度?因为这可用于确定需要测量的时间长度,以获得微观基准测量的一定精度。即,对于3位精度,长度应大于计时器精度的1000倍。当然,使用此长度可以测量多次。Stopwatch类公开了一个属性,该属性是调用SafeNativeMethods的直接结果。。以下是属性页的摘录:
频率值取决于基本定时的分辨率
机制。如果安装的硬件和操作系统支持
高分辨率性能计数器,则频率值反映
计数器的频率。否则,频率值将基于
在系统定时器频率上
对于diff\u ticks
,我总是得到0或1。我的秒表。频率是1948294
。你使用什么硬件/操作系统?顺便检查一下函数(你必须P/调用它)。我同意@lucastrezesniewskidiff_ticks
为0或1,在2.66 GHz的i7 920上以释放模式运行,频率为2610117时,约有85%的零。运行测试1000.0次/秒表。频率为秒,您可以保证获得1000次ticks。然而,你必须记住,时钟不是那么精确,你不能测量小于0.0156秒。而且测量经过的时间太昂贵,对结果影响太大。因此,这无法可靠地工作,您唯一能做的就是预先运行action()几次,以估算所需的时间,然后计算迭代次数。它并不一定是完美的。@Lucastzesniewski这只是意味着你正在使用TSC定时器,因为你还没有启用HPET定时器。您可以通过运行“bcdedit/set useplatformclock true”并重新启动来启用。我想您可能会这样做,但您在帖子中没有提到,这似乎是确定底层计时器精度的最准确的方法。不过,秒表是一个用来测量从一个点到另一个点所用时间的类。两次测量之间的最小时间(不是精度)取决于实际测量的时间,与测量时间的类无关。时间的价值也可能根据具体的实现而变大或变小。你的问题有更大的目的吗?也许我们应该从这一点开始。这正是我想要测量/估计计时器精度的原因,以便能够在尽可能短的时间内进行精确的微观基准测试。这不仅仅是为了进行特别的测量,而是为了使用BenchmarkDotNet,但它们采取保守的路线,并运行“长”时间,例如,通过查找给定动作t的给定时间段的迭代次数,每次测量持续1秒