【问题标题】:Using pseudo-random number engines in deterministic, multi-threaded applications?在确定性的多线程应用程序中使用伪随机数引擎?
【发布时间】:2013-05-17 16:08:45
【问题描述】:

我正在尝试使用 C++11 随机数生成器来洗牌。我发现(通过查看实现)如果引擎使用相同的值作为种子,则两个引擎产生的随机数序列是相同的。

考虑以下代码:

DECK::DECK()
{
    // Initialize deck to contain the standard 52 cards in an unsorted manner.
}

void DECK::shuffle()
{
    std::default_random_engine e;
    // Use 'e' to shuffle the deck
}

int main(int, char* [])
{
    DECK d1, d2;
    d1.shuffle();
    d2.shuffle(); 

    // 'd1' and 'd2' are identical!
}

以下是规格:

1) 程序输出是确定性的(即相同的输入产生相同的输出)。

2) 多个线程需要同时洗牌。

3) 性能至关重要。我不想使用锁(除非没有其他选择)。

由于规范 #1,我无法使用系统时间为 std::default_random_engine 播种。由于规范 #2 和 #3,使引擎成为单例似乎不是一种选择。有没有人有更好的编码方式?

【问题讨论】:

    标签: multithreading random c++11 stl


    【解决方案1】:

    使用 one RNG 创建种子。用输入的数字播种第一个 RNG,然后从中取出接下来的两个数字作为其他两个 RNG 的种子(每副牌一个)。这样一来,您将拥有两个独立的 RNG,但它们对于原始输入仍然具有确定性。

    RNG 被多个线程使用这一事实并不重要,只要每个线程只使用一个 RNG。 (我假设线程不会以不确定的方式相互交互。)

    【讨论】:

      【解决方案2】:

      我认为您可以通过实现非常简单的XORshift 来尝试使用自己的随机数生成器。可以看到只有 9 行代码,一切都为你搞定。而且速度肯定非常快。

      基本上,每个线程都有自己的 XORshift RNG。您只需要正确播种(只需将 x、y、z 和 w 设置为您想要的任何值,除了 (0,0,0,0))

      【讨论】:

        【解决方案3】:

        解决方案:为每个线程设置一个种子维护对象(例如,生成一个局部变量)。

        在 'seed-maintining-object' 调用 'std::rand()' 内部并将其存储为下一次调用的种子。这样,每个线程始终接收完全相同的序列,即使 'std::rand()' 函数调用因竞速条件而不同。

        struct ThreadDeterministicRandomGenerator {
           ThreadDeterministicRandomGenerator(int seed) : my_seed(seed) {}
           int get() { std::srand(my_seed); my_seed = std::rand(); return my_seed; }
        };
        

        由于每个线程都有自己的ThreadDeterministicRandomGenerator 实例,它会产生一个确定性序列。

        您可以将此随机数生成器用作随机算法的基础。

        【讨论】:

          猜你喜欢
          • 2011-12-16
          • 2023-03-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-05-13
          • 2018-05-20
          • 1970-01-01
          • 2016-01-20
          相关资源
          最近更新 更多