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

San*_*VEE 1 c# iteration loops

我想明白为什么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 );
}
Run Code Online (Sandbox Code Playgroud)

当我执行代码时,我得到以下内容:

在此输入图像描述

最初我认为这可能是由于秒表类的准确性因素,但那为什么它只适用于第一个元素?如果我错过了什么,请纠正我.

Lua*_*aan 7

这是一个非常有缺陷的基准.首先,Thread.Sleep并不能保证你会睡100毫秒.尝试更长时间的睡眠,你会看到更一致的结果.

所以它甚至可能只是调度 - 下一次迭代总是在睡眠后进行睡眠.由于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 );
}
Run Code Online (Sandbox Code Playgroud)

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

还有许多其他因素可能使这样的基准复杂化,这就是为什么基准测试不是这样做的原因.总是存在偏差,并且它们可能变得相当大,特别是在具有大量工作的系统上.

换句话说,如果您在毫秒级别上获得CPU工作执行时间的差异,则有人会窃取您的工作.在现代CPU中没有什么可以解释如此巨大的差异,仅仅基于i++存在与否.

我可以用你的代码描述更多的问题,但它可能不值得.只需谷歌一些关于C#中CPU工作基准测试的最佳实践,你就可以从中获得更多价值.

哦,而且只是为了帮助点回家更多,在我的电脑上,第一个往往会从99最远到任何地方100.这将是非常不寻常的,因为默认是15.6ms,而不是1ms,但罪魁祸首很容易找到 - Chrome设置它1ms.哎哟.

  • @VikasGupta等等,你认为OP没有*那*出来?他特别指出了*first*迭代,而不是之后的每次迭代都越来越慢.我们谈论的是一个毫秒以下的差异,而不是几百个. (2认同)