3

Box-Muller 变换是一种从高斯分布中采样随机值的优雅且性能合理的方法。

我正在寻找一种用 C# 清晰编写的更快的方法。

作为参考,这里有一个 Box-Muller 实现的实现,作为性能比较的基准......

public class GaussianGenerator
{
    FastRandom _rng = new FastRandom();
    double? _spareValue = null;

    /// <summary>
    /// Get the next sample point from the gaussian distribution.
    /// </summary>
    public double NextDouble()
    {
        if(null != _spareValue)
        {
            double tmp = _spareValue.Value;
            _spareValue = null;
            return tmp;
        }

        // Generate two new gaussian values.
        double x, y, sqr;

        // We need a non-zero random point inside the unit circle.
        do
        {
            x = 2.0 * _rng.NextDouble() - 1.0;
            y = 2.0 * _rng.NextDouble() - 1.0;
            sqr = x * x + y * y;
        }
        while(sqr > 1.0 || sqr == 0);

        // Make the Box-Muller transformation.
        double fac = Math.Sqrt(-2.0 * Math.Log(sqr) / sqr);

        _spareValue = x * fac;
        return y * fac;
    }

    /// <summary>
    /// Get the next sample point from the gaussian distribution.
    /// </summary>
    public double NextDouble(double mu, double sigma)
    {
        return mu + (NextDouble() * sigma);
    }
}
4

4 回答 4

6

作为记录,这里有一个清晰的实现,带有单元测试:

ZigguratGaussianDistribution.cs

在我的 Intel Core i7 6700T @ 2.8Ghz (Skylake) 上,我在单核测试中获得以下性能结果(使用 BenchmarkDotNet):

  • Box-Muller:54.5M 样本/秒
  • Ziggurat:79.5M 样本/秒

因此,Ziggurat 在这些测试中快了大约 45%。

这两个类都使用Redzen库中的Xoshiro256StarStarRandom类作为伪随机源。

于 2011-09-11T21:26:52.070 回答
1

Ziggurat 在 C 中的实现:

http://www.seehuhn.de/pages/ziggurat

GSL 源(在 C 中)也包含一些高斯随机数生成器的实现。包括 Box-Mueller 和比率方法。

http://gsl.sourcearchive.com/documentation/1.14plus-pdfsg-1/randist_2gauss_8c-source.html

于 2011-08-27T01:10:59.920 回答
1

均匀比率方法的使用非常快。我没有 C# 实现,但我在 Excel VBA 中使用它,它比 Box-Muller 方法快 3 倍:使用 Box-Muller 的 1000 万个样本需要 70 秒,而使用比率为 1000 万个样本需要 20 秒 -统一的方法。

在此处输入图像描述

祝你好运。

于 2015-02-10T21:11:18.870 回答
0

Ziggurat 采样非常快速且内存高效。对于 C/C++ 应用程序,您可以使用 GSL 库

于 2015-08-05T01:03:48.603 回答