7

Görev Paralel Kitaplığı ile oynamaya başladım ve ilginç sorunlara koştum; Neler olup bittiğine dair genel bir fikrim var, ama neler olduğunu anlamak için benden daha yetkin kişilerden gelen yorumları duymak isterim. Biraz uzun kod için özür dilerim.Paralel döngüler ve Rasgele ürünler tek sonuçlar

Ben rastgele yürüyüş olmayan bir paralel simülasyon ile başladı

: Bir sanal makine üzerinde koştum zaman

var localRandom = new Random(); 

stopwatch.Reset(); 
stopwatch.Start(); 

var parallelSimulations = new List<int>(); 
Parallel.For(0, 20, run => 
{ 
    var position = 0; 
    for (var step = 0; step < 10000000; step++) 
    { 
     if (localRandom.Next(0, 2) == 0) 
     { 
      position--; 
     } 
     else 
     { 
      position++; 
     } 
    } 

    Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position)); 
    parallelSimulations.Add(position); 
}); 


Console.WriteLine(string.Format("Average position: {0} .", parallelSimulations.Average())); 
stopwatch.Stop(); 

Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds)); 

Console.ReadLine(); 

:

var random = new Random(); 
Stopwatch stopwatch = new Stopwatch(); 

stopwatch.Start(); 

var simulations = new List<int>(); 
for (var run = 0; run < 20; run++) 
{ 
    var position = 0; 
    for (var step = 0; step < 10000000; step++) 
    { 
     if (random.Next(0, 2) == 0) 
     { 
      position--; 
     } 
     else 
     { 
      position++; 
     } 
    } 

    Console.WriteLine(string.Format("Terminated run {0} at position {1}.", run, position)); 
    simulations.Add(position); 
} 

Console.WriteLine(string.Format("Average position: {0} .", simulations.Average())); 
stopwatch.Stop(); 

Console.WriteLine(string.Format("Time elapsed: {0}", stopwatch.ElapsedMilliseconds)); 
Console.ReadLine(); 

Sonra bir paralel döngü benim ilk girişimi yazdı Sadece 1 çekirdeği kullanacak şekilde ayarladım, benzer bir süre gözlemledim, ancak çalışma sırası artık işlenmiyor - sürpriz yok.

Çift çekirdekli bir makinede çalıştırdığımda, işler tuhaflaştı. Zamanında hiçbir gelişme görmedim ve her koşuda bazı garip sonuçlar gözlemledim. Çoğu çalışma -1,000,000 (ya da çok yakın) sonuçlarla sonuçlanır, bu da Random.Next öğesinin her zaman 0 derece geri döndüğünü gösterir. Her döngü rastgele yerel yaptığınızda

, her şey iyi çalışıyor ve beklediğim süre iyileşme elde edersiniz:

Parallel.For(0, 20, run => 
     { 
      var localRandom = new Random(); 
      var position = 0; 

Benim tahminim sorun gerçeği ile ilgisi var olduğunu Rastgele nesne döngüler arasında paylaşılır ve bazı durumları vardır. “Paralel olmayan başarısız” versiyonunda süregelen gelişme eksikliği, Rastgele çağrıların paralel olarak işlenmemesinden kaynaklanıyor (paralel versiyonun her iki çekirdeği kullandığını görsem de, orjinal değil). . Gerçekten anlamadığım parça, simülasyon sonuçlarının neye benzediğidir.

Tek bir endişe, her döngü için yerel Rastgele örnekleri kullanırsam, aynı tohumdan başlayarak birden fazla döngüye sahip olma sorunuyla karşılaşabilirim (birden çok Rastgele zaman içinde çok yakın bir zamanda oluşturduğunuz sorun , aynı dizilerle sonuçlanır).

Neler olup bittiği hakkında herhangi bir fikir benim için çok değerli olurdu!

cevap

2

Bu yaklaşımlardan hiçbiri size gerçekten iyi rastgele sayılar verecektir.

Bu blog yazısı Bunlar gün uygulamalara birçok gün için iyi olabilir Random

http://blogs.msdn.com/b/pfxteam/archive/2009/02/19/9434171.aspx

daha rasgele sayılar almak için yaklaşımların çok kapsar. Bununla birlikte, aynı rasgele sayı üretecini, farklı tohumlarla () bile birden çok iş parçacığı üzerinde kullanırsanız, yine de rasgele sayılarınızın kalitesini etkileyeceksiniz. Bunun nedeni, üst üste gelebilecek sözde rasgele sayı dizileri oluşturuyor olmanızdır.

http://software.intel.com/en-us/videos/tim-mattson-use-and-abuse-of-random-numbers/

gerçekten rasgele sayılar istiyorsanız o zaman gerçekten kripto rasgele sayı üreteci System.Security.Cryptography.RNGCryptoServiceProvider kullanmanız gerekir: biraz daha ayrıntılı olarak neden

Bu video açıklıyor. Bu threadafe.

+0

Ade, S. Toub makalesinin işaretçisi için teşekkürler, mükemmel. – Mathias

2

Random sınıfı, iş parçacığı için güvenli değildir; Birden fazla iş parçacığı üzerinde kullanırsanız, sorun giderilebilir.

Her iş parçacığına ayrı bir Random10 örneği yapmalı ve aynı tohum kullanarak bitmediğinden emin olmalısınız. (ör. Environment.TickCount * Thread.CurrentThread.ManagedThreadId)

+0

Tohumluk sorunu nasıl giderdiniz? – Mathias

+0

Bu yaklaşımla karşılaşırsanız, sorun yaşayan, çok yakın olan tohumlar üreteceğinden TickCount * ManageThreadId kullanmazdım. Tohum üretmenin daha iyi bir yolu için cevabımı aşağıya bakın. –

1

bir temel sorun:

  • random.Next

    parçacığı güvenli değildir.

İki yansımaları: rastgelelik

  1. Kalite yarış koşulları tarafından yok edilir.
  2. Yanlış paylaşım, çok noktaya yayınlarda ölçeklenebilirliği yok eder.

Çeşitli olası çözümler:

  • random.Next parçacığı güvenli olun: kalite sorunu değil ölçeklenebilirlik çözer.
  • Birden çok PRNG kullanın: ölçeklenebilirlik sorununu çözer, ancak kaliteyi düşürebilir.
  • ...