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

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

または、メイン スレッドでシードを計算し、各ワーカーにデータを渡してエンジンを初期化することもできます。残念ながら を渡すことはできない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 に答える