c# - 为什么第一次迭代总是比循环中的下一次迭代快?

标签 c# loops iteration

我想了解为什么 loop 中的 first iteration 比其他部分执行得更快。

Stopwatch sw = new Stopwatch ();
sw.Start ();

for(int i=0; i<10; i++)
{
   System.Threading.Thread.Sleep ( 100 );
   Console.WriteLine ( "Finished at : {0}", ((double) sw.ElapsedTicks / Stopwatch.Frequency ) * 1e3 );
}

当我执行代码时,我得到以下信息:

enter image description here

最初我认为这可能是由于 Stopwatch 的精度因素所致类,但为什么它只适用于第一个元素?如果我遗漏了什么,请纠正我。

最佳答案

这是一个非常有缺陷的基准。其一,Thread.Sleep 不能保证您会休眠 100 毫秒。尝试更长的 sleep 时间,您会看到更一致的结果。

所以它甚至可能只是调度 - 下一次迭代总是只是在 sleep 后 sleep 。由于 Sleep 的工作得益于系统中断时钟,第一次之后的 sleep 应该花费类似的时间,而第一次必须首先与时钟“同步”。

如果您在循环之前(以及启动秒表之前)添加另一个 sleep ,您可能会在每次迭代中获得更接近的时间。

或者更好的是,不要使用 sleep 。如果您改为使用一些实际的 CPU 工作,您将避免线程切换(前提是您有足够的 CPU 来执行此操作)和许多其他与循环本身无关的成本。例如,

Stopwatch sw = new Stopwatch ();
sw.Start ();

for(int i=0; i<10; i++)
{
   Thread.SpinWait(10000000);

   Console.WriteLine ( "Finished at : {0}", ((double) sw.ElapsedTicks / Stopwatch.Frequency ) * 1e3 );
}

这将为您提供更加一致的结果,因为它根本不依赖于时钟。

还有许多其他因素会使像这样的基准测试变得复杂,这就是为什么基准测试根本不以这种方式完成的原因。总会有偏差,而且偏差会变得相当大,尤其是在工作量很大的系统上。

换句话说,如果您在 CPU 工作执行时间上出现毫秒级差异,则表明有人在窃取您的工作。现代 CPU 中没有任何东西可以仅基于例如i++ 存在与否。

我可以用您的代码描述更多问题,但这可能不值得。只需在 google 上搜索 C# 中 CPU 工作基准测试的一些最佳实践,您就会从中获得更多值(value)。

哦,为了更清楚地说明这一点,在我的计算机上,第一个往往会出现在 99100 之间的任何位置。这是非常不寻常的,因为默认值为 15.6ms,而不是 1ms,但罪魁祸首很容易找到 - Chrome 将其设置为 1ms .哎哟。

关于c# - 为什么第一次迭代总是比循环中的下一次迭代快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26124177/

相关文章:

ruby.none 的 javascript 替代品?

angularjs - 在 AngularJS 中使用重复键迭代 json 响应

c# - Update 1 RC 降级为 CTP 后,LINQ to Entities 仅支持转换 EDM 基元或枚举类型

excel - 对具有特定条件的excel表进行排序(vba)

R Shiny - 尝试使用响应式(Reactive)和 ActionButton 循环

PHP 在 WordPress 循环中的 DIV 内添加每 2 个项目

json - 在 Django 模板中迭代 JSON

c# - 如何在两个数组中找到共同的最小数字

c# - 使用 C# 应用程序安装 SQL Server Express

c# - 有什么方法可以自动化 Windows 窗体测试吗?