静态随机数生成器的线程安全

Kai*_*kha 5 c++ random static openmp

我有一堆线程,每个线程都需要一个线程安全的随机数。由于在我的真实程序中,线程是重复生成和连接的,所以我不想创建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();
}
Run Code Online (Sandbox Code Playgroud)

我无法放置它们,threadprivate因为错误 C3057:当前不支持“threadprivate”符号的动态初始化。一些消息来源说random_devicemt19937是线程安全的,但我还没有找到任何可以证明这一点的文档。

  1. 这个随机化线程安全吗?
  2. 如果不是,哪些静态对象可以保留为静态以保持线程安全?

Vic*_*out 0

我认为threadprivate这仍然是正确的方法,您可以通过稍后进行并行分配来避免初始化问题。

static random_device rd;
static mt19937 rng;
#pragma omp threadprivate(rd)
#pragma omp threadprivate(rng)

int main() {

#pragma omp parallel
  rng = mt19937(rd());

#pragma omp parallel
  {
    stringstream res;
    uniform_int_distribution<int> uni(1, 100);
    res << "Thread " << omp_get_thread_num() << ": " << uni(rng) << "\n";
    cout << res.str();
  }

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,请注意stringstream:OpenMP 倾向于在<<运算符处分割输出线。