从高斯分布中抽样随机值的最快方法是什么?

时间:2011-08-24 22:46:39

标签: c# performance math gaussian sampling

Box-Muller transform是一种优雅且性能相当的高斯分布随机值采样方法。

我正在寻找一种用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 个答案:

答案 0 :(得分:6)

这里的记录是一个清晰的书面实施,单元测试:

ZigguratGaussianDistribution.cs

在我的英特尔酷睿i7 6700T @ 2.8Ghz(Skylake)上,我在单核测试(使用BenchmarkDotNet)上获得以下性能结果:

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

因此,在这些测试中,Ziggurat的速度提高了约45%。

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

答案 1 :(得分:1)

C中的Ziggurat实现:

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

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

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

答案 2 :(得分:1)

使用ratio-of-uniforms方法非常快。我没有C#实现,但我在Excel VBA中使用它,与Box-Muller方法相比,它快3倍:使用Box-Muller的1000万个样本为70s,而使用比率为1000的样本为20个样本为20s统一的方法。

enter image description here

祝你好运。

答案 3 :(得分:0)

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