【问题标题】:What is the fastest method of sampling random values from a Gaussian distribution?从高斯分布中采样随机值的最快方法是什么?
【发布时间】:2011-11-03 05:41:16
【问题描述】:

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);
    }
}

【问题讨论】:

  • 你有没有用 C# 优雅地实现 Ziggurat 算法?
  • 您想要速度和优雅?实施制服比例! Ziggurat(在我看来)丑陋且非常难以调整。
  • @Alexadre。到目前为止,我已经花了几天时间编写一个尽可能优雅的版本,但是是的,它很多比例如复杂。 Box-Muller,尤其是在优化之后!没听说过制服比例,我去研究一下,谢谢指点。
  • 不知道为什么关闭它 - 对我来说似乎是一个完全有效的与编程相关的问题,即生成高斯噪声是一个非常普遍的要求,高效/快速地这样做也是如此。

标签: c# performance math gaussian sampling


【解决方案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

【讨论】:

    【解决方案2】:

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

    ZigguratGaussianDistribution.cs

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

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

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

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

    【讨论】:

    • 我已更正所有链接。编辑正在审核队列中。
    • @Xharlie 我已经编辑了您的编辑。那些 sourceforge 链接是我可能应该删除的旧版本软件。现在一切都在github.com/colgreen/Redzen/tree/master/Redzen/Numerics
    • @Xharlie 实际上,该 sourceforge 版本中存在一个错误,它使连续的高斯值相关,如果您在 (x,y) 笛卡尔图上绘制两个连续的值,这一点就会变得很明显。
    • @redcalx 太棒了。现在我知道哪个是最好的版本了。顺便说一句 - Redzen 版本包含一条评论说 RNG 是在 Math.NET 中分叉的,但我检查了 Math.NET 代码库,其中的 XorShift RNG 与 Redzen 完全不同。我想 Redzen 可能是更好用的那个。
    • @Xharlie yeh 它是分叉的,然后有人用乘法移位 RNG 替换了文件的全部内容,但没有更改类名!
    【解决方案3】:

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

    祝你好运。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2020-10-07
        • 2014-02-01
        • 2012-03-14
        • 2018-11-07
        • 1970-01-01
        • 2014-03-09
        • 2014-07-26
        • 2015-02-13
        • 2013-10-12
        相关资源
        最近更新 更多