2017-03-07 98 views
0

我讀過,爲了保證線程安全,它的方便種子並行區域內的RNG這樣的:Openmp for循環,種子隨機數發生器在哪裏?

int seedbase = 392872; 

#pragma omp parallel 
{ 
    srand(omp_get_thread_id * seedbase); 
    #pragma omp for 
    .... 
} 

但是,如果我的並行部分是另一種循環內?如果我有這樣的情況:

int seedbase = 392872; 
for(int i=0; i<100; ++i) 
{ 
    #pragma omp parallel 
    { 
     srand(omp_get_thread_id * seedbase); 
     #pragma omp for 
     .... 
    } 
} 

我應該在哪裏初始化我RNG

+0

因此,您希望每次迭代都創建一組加入其末尾的線程? – StoryTeller

+0

是的,因爲外部循環範圍可能非常小,所以,假設我有8個線程,如果我把它放在它之前,並且循環範圍是(0,3),那麼我不會讓所有線程都工作,而在這種情況下,因爲我的內循環肯定大於8,我相信我得到所有線程工作 –

+0

相關:[從多個線程使用stdlib的rand()](http://stackoverflow.com/q/6161322/2402272)。 –

回答

1

我讀過,爲了保證線程安全,它的方便,播種RNG並行區域內是這樣的:

便利儘管如此,你的技術是不是有效。不管您撥打srand()的哪個位置,標準rand()函數都不能成爲線程安全的。它依賴於每次調用都會修改的內部靜態數據,所以如果您從多個線程調用它(或srand())而沒有進行某種同步,則會因此創建數據競爭。

一次,POSIX定義了一個函數rand_r()。如果你有這個,那麼它會符合你的目的,但它現在已被標記爲過時。在OpenMP中正確使用rand_r()將涉及在並行區域內部建立私有(OpenMP感知)變量來保存種子。根據每個線程中是否需要相同的隨機數序列,在每個線程中以不同或相同方式對其進行初始化。然後將一個指向該變量的指針作爲參數傳遞給rand_r()。在每次調用之後,您可能想要將返回值或從中派生出來的東西作爲新種子。

+0

如果rand_r現在已過時,標準)功能,我應該打電話嗎? –

+0

這取決於您正在編程的平臺。雖然它已經過時,但不會直接替代'rand_r()',並且在可預見的將來實現實際上不可能將其刪除。無論如何,你可以考慮使用它。另外,如果你只需要支持基於glibc的系統,那麼還有'random_r()'和一個伴隨的'srandom_r()'。 –