Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计时器的测量精度(例如秒表/查询性能计数器)_C#_Performance_Benchmarking_Stopwatch_Microbenchmark - Fatal编程技术网

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,这是否意味着我们可以使

考虑到C#中的
秒表
类可以在下面使用三个不同的计时器,例如

  • 系统计时器,例如精度约为
    +-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/调用它)。我同意@lucastrezesniewski
diff_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秒