转载

随机数(三)

测试程序

在 图灵社区:随机数(二) 中,我们给出了一个 NrRandom 类,能够产生更好的伪随机序列。那么,它与 .NET Framework 中的 Random 类相比,性能如何呢?让我们写一个测试程序吧:

using System; using System.Diagnostics;  namespace Skyiv.Tester {   static class NrRandomTester   {     static readonly Stopwatch timer = new Stopwatch();      static void TestNext1(Random rand, int n)     {       long sum = 0;       timer.Restart();       for (var i = 0; i < n; i++) sum += rand.Next();       timer.Stop();       Console.WriteLine("{0,14} {1,6:F3} {2:N0}", rand.GetType(),         timer.Elapsed.TotalSeconds, (double)sum/n);     }      static void TestNext2(Random rand, int n, int max)     {       long sum = 0;       timer.Restart();       for (var i = 0; i < n; i++) sum += rand.Next(max);       timer.Stop();       Console.WriteLine("{0,14} {1,6:F3} {2:N6}", rand.GetType(),         timer.Elapsed.TotalSeconds, (double)sum/n);     }      static void TestNext3(Random rand, int n, int min, int max)     {       long sum = 0;       timer.Restart();       for (var i = 0; i < n; i++) sum += rand.Next(min, max);       timer.Stop();       Console.WriteLine("{0,14} {1,6:F3} {2,12:N3}", rand.GetType(),         timer.Elapsed.TotalSeconds, (double)sum/n);     }      static void TestNextDouble(Random rand, int n)     {       double sum = 0;       timer.Restart();       for (var i = 0; i < n; i++) sum += rand.NextDouble();       timer.Stop();       Console.WriteLine("{0,14} {1,6:F3} {2:N10}", rand.GetType(),         timer.Elapsed.TotalSeconds, sum/n);     }      static void TestNextBytes(Random rand, int n, int size)     {       long sum = 0;       var bs = new byte[size];       timer.Restart();       for (var i = 0; i < n; i++) {         rand.NextBytes(bs);         foreach (var v in bs) sum += v;       }       timer.Stop();       Console.WriteLine("{0,14} {1,6:F3} {2:N6}", rand.GetType(),         timer.Elapsed.TotalSeconds, (double)sum/n/size);     }      static void Main()     {       Console.WriteLine("{0} {1}-bit", Environment.OSVersion,         Environment.Is64BitOperatingSystem ? 64 : 32);       Console.WriteLine("CLR {0}", Environment.Version);        var r0 = new Random();       var nr = new NrRandom();        Console.WriteLine();  int n = 1000000000, max = int.MaxValue;       Console.WriteLine("Next(): {0,27:N0}", (max-1)/2.0);       TestNext1(r0, n); TestNext1(nr, n);        Console.WriteLine(); max = 10000;       Console.WriteLine("Next(max): {0,23:N6}", (max-1)/2.0);       TestNext2(r0, n, max); TestNext2(nr, n, max);        Console.WriteLine(); max = int.MaxValue; int min = 1 - max;       Console.WriteLine("Next(min,max): {0,19:N3}", (max-1L+min)/2.0);       TestNext3(r0, n, min, max); TestNext3(nr, n, min, max);        Console.WriteLine();       Console.WriteLine("NextDouble(): {0,20:N10}", 1/2.0);       TestNextDouble(r0, n); TestNextDouble(nr, n);        Console.WriteLine(); int size = 1000000, m = n / size;       Console.WriteLine("NextBytes(buffer): {0,13:N6}", byte.MaxValue/2.0);       TestNextBytes(r0, m, size); TestNextBytes(nr, m, size);     }   } }

编译和运行

Linux 64-bit 操作系统

在 Arch Linux 64-bit 操作系统中编译和运行:

$ mcs NrRandomTester.cs NrRandom.cs $ mono NrRandomTester.exe Unix 4.6.3.1 64-bit CLR 4.0.30319.42000  Next():               1,073,741,823  System.Random 14.920 1,073,744,468 Skyiv.NrRandom 16.619 1,073,777,257  Next(max):            4,999.500000  System.Random 19.831 4,999.476177 Skyiv.NrRandom 15.244 4,999.590640  Next(min,max):               0.000  System.Random 41.936    8,672.938 Skyiv.NrRandom 16.405  -13,744.444  NextDouble():         0.5000000000  System.Random 17.517 0.4999909586 Skyiv.NrRandom 14.077 0.5000026850  NextBytes(buffer):    127.500000  System.Random 15.483 127.498822 Skyiv.NrRandom  6.291 127.503321

输出结果中:

方法名称:                期望的平均值  System.Random 运行时间(秒) 实际的平均值 Skyiv.NrRandom 运行时间(秒) 实际的平均值

其中每种方法都生成 10 9 个随机数来进行测试。可以看出:

  • 对于 Next() 方法, NrRandom 类的性能略差于 Random 类。
  • 对于 Next(max) 方法, NrRandom 类的性能优于 Random 类。
  • 对于 Next(min,max) 方法, NrRandom 类的性能大大优于 Random 类。
  • 对于 NextDouble() 方法, NrRandom 类的性能优于 Random 类。
  • 对于 NextBytes(buffer) 方法, NrRandom 类的性能大大优于 Random 类。
  • 对于这两个类,各个方法生成的随机数的平均值都中规中矩。

Windows 64-bit 操作系统

随机数(三)

C> NrRandomTester.exe Microsoft Windows NT 6.1.7601 Service Pack 1 64-bit CLR 4.0.30319.42000  Next():               1,073,741,823  System.Random 11.030 1,073,763,381 Skyiv.NrRandom 11.944 1,073,745,494  Next(max):            4,999.500000  System.Random 16.585 4,999.546877 Skyiv.NrRandom 10.319 4,999.411534  Next(min,max):               0.000  System.Random 31.271   37,382.863 Skyiv.NrRandom 11.942  -39,145.860  NextDouble():         0.5000000000  System.Random 13.122 0.5000071087 Skyiv.NrRandom  9.548 0.4999977242  NextBytes(buffer):    127.500000  System.Random 12.009 127.497139 Skyiv.NrRandom  7.090 127.503601

测试结果与 Linux 64-bit 操作系统一致。

Windows 32-bit 操作系统

随机数(三)

C:> NrRandomTester.exe Microsoft Windows NT 6.1.7601 Service Pack 1 32-bit CLR 4.0.30319.42000  Next():               1,073,741,823  System.Random 11.455 1,073,751,534 Skyiv.NrRandom 35.625 1,073,754,659  Next(max):            4,999.500000  System.Random 18.431 4,999.490003 Skyiv.NrRandom 33.778 4,999.364559  Next(min,max):               0.000  System.Random 50.525   17,712.270 Skyiv.NrRandom 46.544  -10,609.773  NextDouble():         0.5000000000  System.Random 14.538 0.4999985216 Skyiv.NrRandom 26.370 0.4999974172  NextBytes(buffer):    127.500000  System.Random 11.726 127.500430 Skyiv.NrRandom  9.558 127.500100

测试结果出乎意料,除了 Next(min,max)NextBytes(buffer) 方法, NrRandom 类的性能略优于 Random 类,其余方法, NrRandom 类的性能均大大差于 Random 类。我想,这是由于 NrRandom 类生成随机数时,使用 long (64-bit 整数)进行运算,而 32-bit 的操作系统的 64-bit 整数运算的性能低下造成的。

原文  http://www.ituring.com.cn/article/217728
正文到此结束
Loading...