2011-07-05 15 views
12

std :: random_shuffle threadsafe mi? Düzenli rand(), threadafe olmadığı için değil. Öyleyse, rand_r'i random_shuffle ile nasıl kullanırdım, böylece her thread'a benzersiz bir tohum verebilirim. Random_shuffle ile özel rastgele jeneratörler kullanmanın örneklerini gördüm, ama hala bana açık değil.Random_shuffle threadsafe mi? ve rand_r kullanmıyorsa

Teşekkürler.

+4

:

class rand_x { unsigned int seed; public: rand_x(int init) : seed(init) {} int operator()(int limit) { int divisor = RAND_MAX/(limit+1); int retval; do { retval = rand_r(&seed)/divisor; } while (retval > limit); return retval; } }; 

Sen gibi random_shuffle şey ile kullanmak istiyorum Belgeleme aksi belirtilmedikçe, iş parçacığı güvenlidir. –

+1

Ayrıca, 'threadafe' çok aşırı yüklü bir terimdir. Bazı algoritmalar, yalnızca güvenli veriler üzerinde çalışıyorlarsa güvenlidir. Bazıları sadece 1 yazar olduğu sürece iş parçacıkları için güvenlidir ve çoğu bunu garanti edemez. Genel olarak, neyin güvenli olduğuna karar verirken (örneğin, doğru), çeşitli okuma/yazma gereksinimlerini belirtmeniz gerekir. – Kylotan

+0

Sadece açıklığa kavuşturmak için, farklı listelerde paralel olarak karıştırmak istiyorum.Bu yüzden veri yapısındaki ırklar hakkında endişe duymuyorum, sadece karışıklık için rastgele sayıların yaratılması. – Mark

cevap

4

std::random_shuffle ile rand_r kullanmak için, bir (oldukça önemsiz) sarmalayıcı yazmak gerekir. random_shuffle'a ilettiğiniz rasgele sayı üretecinin, üretilecek sayı aralığını belirten bir parametreyi kabul etmesi gerekir; bu, rand_r'un yapmamasıdır.

Kişisel sarıcı şöyle görünecektir: Genellikle * C++ kütüphanede hiçbir şey * olduğunu varsayımını yapmak zorundadır

std::random_shuffle(whatever.begin(), whatever.end(), rand_x(some_seed)); 
+0

Teşekkürler. Tohum imzasız bir int olmalıdır. Ayrıca, neden rand_r (& tohum)% sınırının geri döndürülmesinin tersine bir döngü var? Eksik olduğum bir şey var mı? – Mark

+0

@Mark: Oops - düzeltildi. Do döngüsü hakkında, 10 şekerlemeyi 3 çocuk arasında eşit olarak nasıl böldüğünüzü düşünün (ve bir şekeri parçalara ayıramazsınız). Cevap şu ki yapamazsınız - sadece 9'u dağıtabilirsiniz. Bu, temelde 'RAND_MAX' şekerlerini 'limit' çocuklar arasında bölmek ve herhangi bir sola atmak için aynı şeyi yapıyor, böylece tüm yığınlar eşittir. ''% Limit' (veya '/ divisor') 'un kendi başına kullanılması,' RAND_MAX''nın' limit''in tam olarak bir katı olması (ve 'RAND_MAX' genellikle asaldır. * Birden fazla * anlamlı * limit ”). –

+0

Jerry'nin söylediği her şeye katılıyorum olsa da, eğer 'rand_r' kullanıyorsanız, o zaman bunun korunacak düzgün bir dağılım olduğunu varsayamazsınız. Ama en azından bu şekilde, eğer * 'rand_r' iyi ise, o zaman senin karmaşınız da iyi, yeni bir önyargı getirmiyorsun. –

3

Entegre bir değer türü alan ve işlevin içine geçirdiğiniz yineleyicilerin kapsayıcının sınırlarını aşmayacak bazı tümleşik türden başka bir değer döndüren rasgele sayı üreteci işlevi veya functor nesnesi sağlamanız gerekir. ile yinelenen. Ayrıca bir functor nesnesi durumunda, bir fonksiyon gibi çağrılabilmesi için operator()'u uygulamalıdır. srand ve'dan rand'u kullanarak bir iş parçacığı güvenli rasgele sayı üretecine gereksiniminiz kötü bir fikirdir ... bunun yerine, bir iş parçacığı güvenli rasgele sayı üreteci veya rasgele sayı üreteci uygulayan bir functor nesnesi oluşturmanız gerekir. Küresel olarak erişilebilir değişkenleri uygulamamaktadır, böylece her şey iplik yerel depolama alanı olarak kalmaktadır.

Örneğin, bunun işe yaramasının bir yolu, başka bir kitaplıktan aldığınız bir çeşit rasgele sayı üretecine sahip olmanızdır; bu, yalnızca sabit bir değerler aralığı arasında rastgele değerler üretecek ve böylece kapsayıcının sınırlarını tanımlayabilirsiniz. rasgele erişim yineleyicileri için random_shuffle algoritması kullanır. Şimdi kullandığınız kütüphane bağlı olarak, funktoru gibi bir şey olabilir şunlardır:

Şimdi
class my_rand_gen 
{ 
    private: 
     random_gen_type random_range_gen; 
     int min; 
     int max; 

    public: 
     my_rand_gen(const random_gen_type& gen, int min_range, int max_range): 
        random_range_gen(gen), min(min_range), max(max_range) {} 

     int operator()(int value) 
     { 
      //ignore the input value and use our own defined range 
      //returns a value between min and max 
      return random_range_gen(min, max); 
     } 
}; 

sizin gibi algoritma arayabilirsiniz:

random_shuffle(my_vector_start_iter, my_vector_end_iter, 
       my_rand_gen(rand_generator_lib, 
          vector_start_index, 
          vector_end_index)); 

ve başından arasına-vektör olarak karıştırılır ve vektörün sınırlarını taşmadan yineleyicilerinizi sonlandırın ... diğer bir deyişle, yalnızca vector_start_index ve vector_end_index arasındaki shuffle değerlerini kullanır.

+0

Yeni' 'sınıfları bunun için iyi bir başlangıç ​​olacaktır. iş parçacığı başına bir PRNG. –

İlgili konular