[英]C++ Initialization of static variable in multithreaded environment
我正在努力尋找一種正確的方法來初始化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循環,以便只有在第一次運行時,所有線程才會等待主線程初始化引擎:
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
的構造 Rng
執行這類初始化。
從字面上看,這就是它的工作。
仍然不清楚為什么首先要在這里擁有static
數據。
為什么不使用成員變量 ?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.