我有一个多线程C ++应用程序,每个线程需要很多随机数。
在C ++ 11之前,我使用了一个“随机函数”,它在主线程中使用rand()
函数生成一些random,并将不同的random传递给每个子线程。然后,所有子线程都加入主线程,再次使用随机数发生器并调用新的子线程,等等N
次。
现在,我想用C ++ 11替换rand()
以避免随机数发生器并在每个线程中生成随机数。
我想为随机数生成器播种,以便: *种子序列从一次运行变为另一次运行 *每个线程中的随机数序列在线程之间是不同的(如果在不同的循环中调用线程,也是如此)
我认为这样播种:mt19937 rng;
rng.seed(this_thread::get_id().hash());
这对我有好处,因为this_thread::get_id().hash()
是一个“随机”数字,但有时候,在不同的循环中,我可以获得相同的ID。
如何随机播种随机数生成器以避免在某些线程中获得相同的随机数序列?
答案 0 :(得分:2)
由于线程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);
答案 1 :(得分: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();
}
}