2

我有一个多线程 C++ 应用程序,每个线程中需要许多随机数。

在 C++11 之前,我使用了一个“随机化器”,它使用函数在主线程中生成一些随机rand()数,并将不同的随机数传递给每个子线程。然后,所有子线程加入主线程,再次使用随机化器并调用新的子线程,依此类推N

现在,我想rand()用 C++11 替换,以避免随机化器并在每个线程中生成随机数。

我想播种随机数生成器,这样:*种子序列从运行到运行*每个线程中的随机数序列因线程而异(如果线程在不同的循环中调用)

我想像这样播种:

mt19937 rng;
rng.seed(this_thread::get_id().hash());

这对我有好处,因为this_thread::get_id().hash()它是一个“随机”数字,但有时,在不同的循环中,我可以获得相同的 id。

如何随机播种随机数生成器以避免在某些线程中获得相同的随机数序列?

4

2 回答 2

3

由于线程 ID 不同,也许只是使用时钟来改变值:

#include <chrono>
...

typedef std::m19937::result_type seed_type;

typename std::chrono::system_clock seed_clock;
auto init_seed = static_cast<seed_type>
    (seed_clock.now().time_since_epoch().count());

init_seed += static_cast<seed_type>(this_thread::get_id());

rng.seed(init_seed);
于 2013-04-04T11:43:12.087 回答
1

播种的适当默认值是:

std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);

您可以简单地在每个线程上执行此操作,它应该可以工作:

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <mutex>
#include <random>
#include <thread>

int main() {
    std::mutex iomutex;

    std::vector<std::thread> threads;

    for (int i = 0 ; i < 10; ++i) {
        threads.emplace_back([&iomutex](int tid) {
            std::random_device r;
            std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};

            std::mt19937 eng(seed);
            std::uniform_int_distribution<> dist(1, 100);

            std::lock_guard<std::mutex> ioguard(iomutex);
            std::cout << "Thread " << tid << ": ";
            std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, std::bind(dist, eng));
            std::cout << '\n';
        }, i);

    }
    for (auto &&t : threads) {
        t.join();
    }
}

或者,您可以在主线程上计算种子并将数据传递给每个工作人员以初始化其引擎。不幸的是,您不能传递 a seed_seq,因此在下面的示例中,我只是传递了一个初始化的引擎。

int main() {
    std::mutex iomutex;
    std::vector<std::thread> threads;
    std::random_device r;

    for (int i = 0 ; i < 10; ++i) {
        std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
        std::mt19937 thread_eng(seed);

        threads.emplace_back([&iomutex](int tid, std::mt19937 init_eng) {
            std::mt19937 eng(std::move(init_eng));
            std::uniform_int_distribution<> dist(1, 100);

            std::lock_guard<std::mutex> ioguard(iomutex);
            std::cout << "Thread " << tid << ": ";
            std::generate_n(std::ostream_iterator<int>(std::cout, " "), 10, std::bind(dist, eng));
            std::cout << '\n';
        }, i, thread_eng);

    }
    for (auto &&t : threads) {
        t.join();
    }
}
于 2016-01-29T21:26:56.680 回答