【问题标题】:Deterministic random number generator tied to instance (thread independent)与实例相关的确定性随机数生成器(与线程无关)
【发布时间】:2011-09-21 23:51:31
【问题描述】:

这里已经很好地介绍了随机数,所以我会保持简短。

我使用srandrand 在模拟中生成一些确定性随机数。但是,当在单独的线程上同时运行多个模拟时,单个序列会变得混乱并变得不确定,因为所有线程都来自同一个池。有没有一种简单的方法可以“绑定”rand 以从特定实例中提取?还是我必须切换到Boost.Random 之类的东西?

【问题讨论】:

  • 如果你的srandrand 共享全局状态,你怎么知道它们是线程安全的?
  • 这实际上是一个非常好的点大卫。 0_o
  • 其实,快速跟进问题。我现在使用了来自 boost 的随机标头,但即使我使用种子值,我也会为不同的编译选项(调试与发布等)获得不同的随机数。这是意料之中的吗?
  • 后续问题应显示为新问题。
  • 不,这听起来很奇怪。

标签: c++ multithreading random generator


【解决方案1】:

我的 C++ 随机数库 RandomLib 的文档包含 在 OpenMP 中使用并行数流的图示;看 http://randomlib.sourceforge.net/html/parallel.html。你可能是 能够将那里提出的想法适应您的应用程序。

【讨论】:

    【解决方案2】:

    您可以使用此代码,为每个线程保留一个rnd_state 结构。您可以使用rand() 初始化 rnd_state。这只是一个想法,这是一个合理的 RNG。

    来自linux内核源代码(random32.c)

    rnd_state 中的值应该被初始化为:s1 > 1, s2 > 7, s3 > 15。

    论文声称这是一个最大等分布的组合 Tausworthe 生成器 基于来自 GNU Scientific Library 1.5(2004 年 6 月 30 日)的代码

    struct rnd_state {
        u32 s1, s2, s3;
    };
    
    static u32 __random32(struct rnd_state *state)
    {
    #define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
    
        state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
        state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
        state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
    
        return (state->s1 ^ state->s2 ^ state->s3);
    }
    

    学术界:http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps

    【讨论】:

    • 仅供参考,32 位 4 分量和 64 位 5 分量 Tausworthe 生成器(在this 论文中描述)可以在iro.umontreal.ca/~simardr/rng 找到(分别为lfsr113.clfsr258.c) .它们似乎是对您答案中的 3 个组件生成器的改进。
    • 顺便问一下,你知道你列出的 Tausworthe 的正确性的任何测试吗(即第百万个值应该是 xxx)?
    【解决方案3】:

    您的编译器很可能已经有类似 Boost.Random 的东西。

    C++0x 包含一个基于 Boost.Random 的 &lt;random&gt; 标头(这里和那里有一些调整)。

    在此之前,TR1,一组“半标准”库也可用于大多数编译器,其中包含几乎相同的 &lt;random&gt; 标头。

    【讨论】:

      【解决方案4】:

      我强烈建议使用 &lt;random&gt;&lt;tr1/random&gt; 来细粒度地访问高质量的 PRNG 类,您可以在每个线程中实例化一个,完全控制它们的种子,从而完全控制它们产生的随机数序列。

      【讨论】:

        【解决方案5】:

        在 Linux 上,rand_rrand 的可重入版本,但它是一个相当弱的 PRNG,因此可能需要使用 *rand48_r 系列函数中的一些东西。

        rand_s 是 Windows 上rand 的可重入版本,但由于它的状态是 unsigned int,它也必然是相当弱的。

        长话短说,使用 Boost.Random 可能会更好。

        【讨论】:

          【解决方案6】:

          一堆 PRNG 被添加到标准库中。另一种选择是为每个线程预先生成大量数字,然后一次发出一个。

          【讨论】:

            猜你喜欢
            • 2012-03-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-21
            • 1970-01-01
            • 2020-06-07
            • 1970-01-01
            • 2016-09-04
            相关资源
            最近更新 更多