2010-11-20 109 views
6

我正在寫一個並行程序使用開放熔點,其中我生成隨機浮點數的矩陣,然後做了一些計算。我當前想要讓生成矩陣並行運行的步驟,但我有問題,rand()函數並不是要同時運行。我不想在rand上使用鎖來提供互斥鎖,因爲這是循環中唯一要做的事情,它可能會更有效地按順序運行它。有沒有辦法有效地並行執行這一步驟?併發隨機數的生成

這裏如果當前代碼爲這部分(帶蘭特上無互斥鎖);

#pragma omp parallel default(private) 
{ 
    int i= omp_get_thread_num(); 
    for(int j=0; j<cols; j++) 
     matrix[i][j]= rand()%1000 + (float)(rand()%100)/(float)(rand()%1000); 
} 
+0

PRNG從固定的種子生成一致的數字序列。這個順序(可重複性)對你來說很重要,還是你真的想要「隨機」? – 2010-11-20 19:20:30

+0

無論他們是否按照任何特定的順序都沒關係,我遇到的問題是當我順序運行它時,我在整個範圍內獲得了很好的分佈,但是當我將其更改爲平行時,總體上這些數字小於10,當我總結行幾乎所有他們加起來0(我從來沒有負面的順序)。這使我認爲函數調用存在某種併發問題。 – user381261 2010-11-20 19:28:22

+1

堅持一秒 - 平均每1000次迭代一次,rand()%1000將爲零,那麼如何分配呢? – TonyK 2010-11-20 19:47:22

回答

3

如果您使用C++,則應考慮使用Boost library random number classes。您可以爲每個線程創建一個唯一的PRNG實例。如果您需要重複性,您可以用重複生成的種子值初始化主線程中的每個實例。

0

如果僞足夠好(參見本的評論),那麼你可以創建自己的PRNG(例如,一個梅森難題,而不是大多數系統使用的弱模法),並實現每一個獨立的發電機線。如果你這樣做,你必須確保每個發生器都有不同的種子。

0

一個真正的問題是如果你想要再現性,這在測試中經常需要。用給定的種子生成一系列線程種子。然後每個線程將使用自己的種子生成數字。

rand()不是線程安全的事實不是一個問題。有很多可用的算法,並且對於每個線程滾動一個實例(狀態)是微不足道的,例如從http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods開始。鎖定每個rand()調用將是一個併發災難。

3

我想你正在尋找rand_r(),它顯式地將當前的RNG狀態作爲參數。然後每個線程應該擁有它自己的種子數據副本(無論您希望每個線程開始使用相同的種子還是不同的種子取決於您在做什麼,在這裏您希望它們與衆不同或者您會得到相同的行一次又一次)。這裏有一些關於rand_r()和線程安全的討論:whether rand_r is real thread safe?

所以說你想讓每一個線程的種子都以它的線程號開始(這可能不是你想要的,因爲每次你運行相同數量的線程時它會給出相同的矩陣,爲例):

#pragma omp parallel default(none) shared(matrix, cols) 
{ 
    int i= omp_get_thread_num(); 
    unsigned int myseed = i; 
    for(int j=0; j<cols; j++) 
     matrix[i][j]= rand_r(&myseed)%1000 + (float)(rand_r(&myseed)%100)/(float)(rand_r(&myseed)%1000 + 1); 
} 

現在每個線程被完全改變自己的狀態(rand_r()是一個純函數),你應該回家自由。