我有很多线程,每个线程都需要一个安全的随机数。由于在我的真实程序中会反复产生和加入线程,我不想每次进入调用相同函数的新并行区域时都创建random_device
和mt19937
,所以我将它们设为静态变量:
#include <iostream>
#include <random>
#include <omp.h>
void test(void) {
static std::random_device rd;
static std::mt19937 rng(rd());
static std::uniform_int_distribution<int> uni(1, 1000);
int x = uni(rng);
# pragma omp critical
std::cout << "thread " << omp_get_thread_num() << " | x = " << x << std::endl;
}
int main() {
# pragma omp parallel num_threads(4)
test();
}
由于发生了“错误C3057:当前不支持'threadprivate'符号的动态初始化”,我无法将它们作为threadprivate
。有一些资料表明random_device
和mt19937
是线程安全的,但我没有找到任何可以证明它的文档。
- 这个随机化是否是线程安全的?
- 如果不是,哪些静态对象可以保留为静态以保持线程安全?
static thread_local
,但不确定是否与 OpenMP 兼容。如果rd
仅用于初始化,请考虑使用rng(std::random_device{}())
; - Quimbymt19937
和uni
都有内部状态,并修改它们以生成随机数。因为它们会自我修改,如果在多个线程之间共享,需要进行保护。 - NathanOliver{}
创建了一个临时对象,而()
调用了它的调用运算符。 - Quimby