【问题标题】:Simple method call is really slow?简单的方法调用真的很慢吗?
【发布时间】:2012-04-08 19:32:29
【问题描述】:

编辑:我已经解决了我的问题。原因是测试过程中的一个错误,一旦我被允许回答我自己的问题,就会详细说明。

我知道这类问题通常应该避免,但我遇到了一个我无法理解的非常奇怪的情况。我一直在尝试实现 PRNG,并且一直在针对 System.Random 测试它的性能。我发现我的代码慢了约 50 倍,但问题不在于算法,而在于调用方法。即使我只是返回一个常数,它仍然会慢很多倍。

所以我写了一个简单的测试程序,比较调用一个包装random.NextDouble()的方法,一个返回-1的方法,和直接调用random.NextDouble()。我在 Ideone 中进行了测试,it gave the expected results;所有的时间都是相似的,返回一个常数是最快的。时间都在0.1秒左右。

但是,在 Visual Studio 2011 Beta 或 2010 C# Express 中编译的相同代码将分别导致每种情况的 4 秒、4 秒和 0.1 秒。我肯定在发布模式下运行,勾选了优化代码复选框,从 Visual Studio 外部启动会得到相同的结果。那么为什么在 Visual Studio 中如此简单的方法调用比 Ideone 慢得多?这是我用来进行基准测试的代码:

using System;
using System.Diagnostics;

public class Test{
    static Random random = new Random();

    public static Double Random() {
        return random.NextDouble();
    }

    public static Double Random2() {
        return -1;
    }

    public static void Main() {
        {
            Stopwatch s = new Stopwatch();
            Double a = 0;
            s.Start();
            for (Int32 i = 0; i < 5000000; i++)
                a += Random();
            s.Stop();
            Console.WriteLine(s.ElapsedMilliseconds);
        }

        {
            Stopwatch s = new Stopwatch();
            Double a = 0;
            s.Start();
            for (Int32 i = 0; i < 5000000; i++)
                a += Random2();
            s.Stop();
            Console.WriteLine(s.ElapsedMilliseconds);
        }

        {
            Stopwatch s = new Stopwatch();
            Double a = 0;
            s.Start();
            for (Int32 i = 0; i < 5000000; i++)
                a += random.NextDouble();
            s.Stop();
            Console.WriteLine(s.ElapsedMilliseconds);
        }
    }
}

【问题讨论】:

  • 抱歉这个愚蠢的问题,但什么是 PRNG?
  • 你还需要s.Reset()秒表,否则它会从以前的计数恢复。
  • @ja72 你可以看到我通过用括号分隔块为每个案例初始化了一个新的秒表。
  • 无需致电s.Reset() @ja72 --- 他使用大括号进行范围界定,因此实际上有 3 个不同的秒表。顺便说一句,你应该真的将该块放入它自己的方法中......

标签: c# performance prng


【解决方案1】:

您不应该测量对 Random() 和 Random2() 的第一次调用。第一次调用函数时,由 JITTER 处理。相反,调用 Random() 和 Random2() 一次,然后开始测量。 random.NextDouble() 已经在 .NET 安装后编译,所以不会遇到同样的问题。

我认为这不能解释所有差异,但它应该公平竞争。

【讨论】:

  • 我只是将代码包装在一个 for 循环中,这样它就可以运行 10 次。结果与我最初的发现一致。
猜你喜欢
  • 1970-01-01
  • 2022-07-27
  • 1970-01-01
  • 2022-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 1970-01-01
相关资源
最近更新 更多