2017-02-10 80 views
13

我有一些代碼,看起來有點像這樣:線程安全:: random_device

std::random_device rd; 

#pragma omp parallel 
{ 
    std::mt19937 gen(rd()); 
    #pragma omp for 
    for(int i=0; i < N; i++) 
    { 
     /* Do stuff with random numbers from gen() */ 
    } 
} 

我有幾個問題:

  • std::random_device線程安全的?即當多個線程同時調用它時,它會做些什麼沒有幫助的事情?
  • 這通常是一個好主意嗎?我應該擔心重疊的隨機數字流嗎?
  • 有沒有更好的方法來實現我想要的(每個線程中獨立的隨機數字流 - 我現在不擔心重複性)?

如果它做出我主要在Windows上運行的std::random_device運作有什麼區別,不過我想代碼在Linux和OSX同樣出色的工作爲好。

+0

您可以實現再現性,但使用特定的種子而不是使用'std :: random_device'。 – Galik

+0

'random_device'很可能被阻塞。如果你想要的是並行性,那麼使用它就沒有多少意義。你可以使用一個用'random_device'播種的全局PRNG來播種'mt19937'(但它需要明確的鎖定)。 – sbabbi

回答

3

注:這個答案適用於一般GCC LinuxOpenMP不能保證與std線程模型互操作,使功能,如thread_local可能無法正常工作。

(會刪除這個答案,如果它會讓我)

我可能會做出PRNG線程局部靜態與初始化一個臨時std::random_device

#pragma omp parallel 
{ 
    // different gen for each thread 
    thread_local static std::mt19937 gen(std::random_device{}()); 
    #pragma omp for 
    for(int i=0; i < N; i++) 
    { 
     /* Do stuff with random numbers from gen() */ 
    } 
} 

這會給你只有一個std::mt19937每個線程並通過多次調用函數來構建它們可節省時間。

+1

謝謝,我不知道'thread_local'關鍵字。更一般地說,當使用openmp並行區域來做這種事情時,我應該使用'thread_local'來正確地將線程變成本地的嗎?我想只是聲明並行區域內的變量就足夠了? – Theolodus

+0

@Theolodus其實是的,你是對的,在一個平行區域使它已經具有特定的線程。我想從這裏得到的結論是,線程特定意味着如果經常調用該函數,可以使其成爲「靜態」,從而提供潛在的性能提升,並且可以暫時初始化該生成器而無需花費構建臨時的多次(每線程) – Galik

+0

你確定'#pragma omp'完全服從C++ 11線程模型嗎?線程本地程序保證在'std'線程中工作,但是爲了讓它們在其他線程系統中工作,您需要該線程系統的編寫者的保證...... – Yakk