2010-11-20 26 views
6

Açık mp'yi kullanarak, rasgele kayan nokta sayılarının bir matrisini oluşturduğum ve sonra üzerinde bir dizi hesaplama yaptığım bir paralel program yazıyorum. Şu anda matrisi paralel olarak oluşturduğum adımı yapmak istiyorum, ancak rand() işlevinin eşzamanlı olarak çalışması için bir sorun yaratmadım. Mutex'e randıman sağlamak için kilitleri kullanmak istemiyorum çünkü bu döngüde yapılan tek şey ve muhtemelen sıralı olarak çalıştırmak için daha verimli olacaktır. Bu adımı paralel olarak verimli bir şekilde yapmak için herhangi bir yolu var mı?Eşzamanlı rasgele sayı üretimi

Bu bölümün geçerli kodu (rand sırasında mutex dışında); Yalancı rasgele (Bkz Ben'in yorum) yeterince iyi ise

#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'ler sabit bir tohumdan tutarlı bir sayı dizisi oluşturur. Bu düzen (tekrarlanabilirlik) sizin için önemli mi yoksa gerçekten "rastgele" mi istiyorsun? –

+0

Belirli bir sırada olup olmadıkları önemli değil, sorun şu ki, sıralı olarak koştuğum zaman aralığımda oldukça iyi bir yayılımım oldu ama genel olarak paralel olarak değiştirdiğimde sayıları 10'dan azdı ve satırları topladığımda hemen hemen hepsi 0'a kadar eklendi (sırayla hiç negatif olmadım). Bu, işlev çağrısı ile bir çeşit eşzamanlılık sorunu olduğunu düşünmemi sağlıyor. – user381261

+1

Bir saniye bekle - her bin yinelemede ortalamada, rand()% 1000 sıfır olacak, bu yüzden nasıl bölebilirsiniz? – TonyK

cevap

3

C++ kullanıyorsanız, Boost library random number classes numaralı telefonu kullanmayı düşünmelisiniz. Her iş parçacığı için benzersiz bir PRNG örneği oluşturabilirsiniz. Tekrarlanabilirliğe gereksiniminiz varsa, her bir örneği ana iş parçanızda tekrarlanabilir şekilde oluşturulmuş tohum değerleri ile başlatabilirsiniz.

0

, o zaman (çoğu sistemler tarafından kullanılan zayıf modülo yöntem yerine mesela. Bir Mersenne Twister) Kendi PRNG oluşturabilir ve başına bir bağımsız jeneratör uygulamak iplik. Bunu yaparsanız, her bir jeneratörün farklı bir tohuma sahip olduğundan emin olmalısınız.

0

Testte sıklıkla ihtiyaç duyulan tekrarlanabilirlik istiyorsanız, asıl sorun şu ki. Verilen bir tohum ile bir dizi tohum çekirdeği üretilir. Daha sonra her bir iplik, sayı üretmek için kendi tohumunu kullanacaktır.

rand() iş parçacığının güvenli olmadığı gerçeği bir sorun değildir. Çok sayıda algoritma vardır ve iş parçacığı başına bir örnek (durum) döndürmek önemsizdir, örneğin http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods'dan başlayabilirsiniz. Her bir rand() numaralı çağrı için kilitleme, bir eş zamanlılık felaketi olacaktır.

3

Sanırım geçerli RNG durumunu bir parametre olarak açıkça alan rand_r() öğesini arıyorsunuz. Daha sonra her bir iş parçacığı kendi tohum verisi kopyasına sahip olmalıdır (her bir iş parçacığının aynı tohumla başlamasını isteyip istemediğinizi veya farklı olanları yaptığınız şeye bağlıdır. Burada farklı olmalarını istersiniz veya aynı satırı alırsınız. tekrar ve tekrar). Burada rand_r() ve iş parçacığı güvenliği hakkında bazı tartışmalar var: whether rand_r is real thread safe?.

Her bir iş parçacığının kendi çekirdek numarasıyla tohumunun başlatılmasını istediğinizi varsayalım (ki bu muhtemelen istediğiniz kadar değil, aynı sayıda iş parçacığıyla koşturduğunuz her seferde aynı matrisi verecektir, ancak bir örnek):

#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); 
} 

Şimdi her iplik münhasıran (rand_r() kendi durumunu değiştirerek bir saf fonksiyondur) ve eve özgür olmalıdır.

İlgili konular