C++多线程环境下静态变量的初始化

标签 c++ multithreading class static initialization

我正在努力寻找一种正确的方法来初始化 C++ 中的类的静态成员。上下文是随机数生成。我想做的是创建一个用于随机数生成的类,并为每个线程创建一个引擎。

现在看起来像这样:

template<typename T, int MIN, int MAX>
class Rng {
 public:
  T operator()() {
    return get_random_number(omp_get_thread_num());
  }

 private:
  static T get_random_number(int id);
};

template<typename T, int MIN, int MAX>
T msl::Rng<T, MIN, MAX>::get_random_number(int id) {
  static std::vector<std::mt19937> engines;
  static std::vector<std::uniform_real_distribution<T>> dists;

  if (engines.empty()) { 
    int threads = omp_num_threads();
    engines.reserve(threads);
    dists.reserve(threads);

    for (int i = 0; i < threads; ++i) {
      std::random_device rd;
      std::mt19937 engine(rd());
      engines.push_back(engine);
      std::uniform_real_distribution<T> unif(MIN, MAX);
      dists.push_back(unif);
    }
  }

  return dists[id](engines[id]);
}

我这样使用它:

int main(){

Rng<double, 0, 10> rng{};
auto init = rng();

int n = 100;
int a[n];

#pragma omp parallel for
  for(int i = 0; i < n; ++i){
    a[i] = rng();
  }
}

现在我想摆脱 main 方法中的前期初始化(auto init = rng()),但我不想引入不必要的开销,即线程不应该互相等待等,因为目前初始化只完成一次(很明显),但是生成发生了很多次。

我尝试的一件事是添加一个 while 循环,这样只有在第一次运行时,所有线程才会等待 master 初始化引擎:

template<typename T, int MIN, int MAX>
T msl::Rng<T, MIN, MAX>::get_random_number(int id) {
  static std::vector<std::mt19937> engines;
  static std::vector<std::uniform_real_distribution<T>> dists;

  int threads = omp_num_threads();

#pragma omp master
{
  if (engines.empty()) { 
    engines.reserve(threads);
    dists.reserve(threads);

    for (int i = 0; i < threads; ++i) {
      // init stuff...
    }
  }
}

  while(engines.size() < threads)
    continue; 

  return dists[id](engines[id]);
}

然而,这只会导致僵局。解决这个问题的典型方法是什么?我还考虑过使用互斥锁和条件变量来唤醒线程,但由于锁定,这可能代价高昂,实际上只在第一次调用函数时才需要。

最佳答案

典型的方法是使用构造函数

Rng构造函数执行这些初始化。

这实际上就是它的工作。

不管怎样,你一开始就不清楚为什么这里有 static 数据。
为什么不使用成员变量

关于C++多线程环境下静态变量的初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44244406/

相关文章:

java - 将 Class 对象传递给方法

java - 如何让代码更灵活

c++ - C++类/结构中的函数相关属性

c++ - 计算整数十进制表示中不同数字的数量

java - 在线程中定期调用 Handler.Postdelayed

同步、 volatile 和(标记)锁的 Java 内存模型交互

java - 在程序中得到不一致/错误的输出多线程java

c++ - 如何将整数转换为字符串

c++ - 读取DICOM文件到double-array,最简单的方法

c++ - 为 Windows Phone 8.1 商店应用程序 (WinRT) 构建 unqlite