多次调用后,C#代码会加速

时间:2016-09-09 14:12:27

标签: c# algorithm optimization branch-prediction

我想测试算法的不同C#实现的执行时间。由于测试环境(我的计算机)有几个不受我控制的环境变量(如操作系统时间切片),我想获得大量数据点,然后查看分布。基本上,我想多次运行算法,测量每个算法的时间,然后以某种方式汇总结果。

代码看起来像这样:

    public void TestSpeed()
    {
        var sw = new System.Diagnostics.Stopwatch();
        MyTestAlgorightm(); // "warm up" system

        for (var i = 0; i < 10000; i++)
        {
            sw.Reset();

            sw.Start();
            MyTestAlgorightm();
            sw.Stop();

            AddExecutionDuration(sw.ElapsedTicks);
        }

        AggregateResults();
    }

然而,当我看结果时,他们似乎有点欺骗......我得到这样的时间:

84,23,19,22,19,18,17,17,......

我总是看到这种模式,第一次通话(实际上是第二次,在&#34;热身&#34;之后)需要一个&#34; long&#34;时间,然后后续呼叫都相对较快,并且都需要相同的持续时间才能运行。

我的猜测是,我所看到的与分支预测相似(我知道此代码中没有分支,但可能类似......),如this excellent question所示。< / p>

如果是这种情况,那么有没有办法将其关闭&#34;所以我可以看到通常每次从生产代码中调用MyTestAlgorithm()需要多长时间,但是在此时间测试中仍能连续多次调用它以便我可以收集指标?

如果它不是类似于分支预测的东西,那么导致第一次定时呼叫需要更长时间的原因是什么?或者换一种说法,为什么后续呼叫运行得更快?

由于有人说,在不知道MyTestAlgorithm()包含哪些内容难以回答这个问题(公平点)的情况下,这里是我测试的简化示例:

    private AlgorithmTest _test;
    private PropertyInfo _pi;
    private int MyTestAlgorithm()
    {
        if (_pi == null)
        {
            _pi = typeof (AlgorithmTest).GetProperty("Prop1");
            _test = new AlgorithmTest() {Prop1 = 42};
        }
        return (int)_pi.GetValue(_test);
    }

    public class AlgorithmTest
    {
        public int Prop1 { get; set; }
    }

这是我的测试号码:

5,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,......

请注意,if的正文未定时,因为它仅在&#34;预热&#34;期间第一次执行,然后结果被缓存。

0 个答案:

没有答案