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

red*_*alx 3 c# math performance gaussian sampling

所述盒-缪勒变换,是从高斯分布随机采样值的优雅和合理高性能方法.

我正在寻找一种更清晰的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);
    }
}
Run Code Online (Sandbox Code Playgroud)

red*_*alx 6

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

ZigguratGaussianDistribution.cs

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

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

所以Ziggurat在这些测试中的速度提高了约45%.

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