2009-10-07 5 views
5

.NET'te Random sınıfında sorun yaşıyorum, küçük bir ayrıntı dışında ince bir iş parçacığı koleksiyonu uyguluyorum. Koleksiyon bir Skip list'dur ve bunu bildiğiniz kişiler eklediğim her düğüm için <= CurrentMaxHeight+1 olan yeni bir yükseklik oluşturmamız gerektiğini bilir, bunu yapmak için kullandığım kod (burada çok verimsiz olduğunu biliyorum, ama işe yarıyor) ve buradaRastgele ve Konular ile ilgili sorun. NET

int randomLevel() 
{ 
    int height = 1; 

    while(rnd.NextDouble() >= 0.5 && height < MaxHeight) 
    ++height; 

    return height; 
} 

benim sorundur) artık benim ana öncelik thats bazen atlama listesinin performansını öldürür üst üste birkaç bin elementler için sadece 1 geri bundan alıyorum. Üst üste bu yöntemden sadece 1 tane üretmek için 10.000 öğeye sahip olma şansı çok zayıf görünüyor (oldukça tutarlı bir şekilde gerçekleşiyor).

Yani bir şekilde Random nesne ile ilgili bir sorun olduğunu (tahmin) farz ediyorum, ama etrafta kazma başlamak nerede bilmiyorum. Bu yüzden kimsenin bir fikri olup olmadığını görmek için stackoverflow'a dönüyorum?

Düzenleme

RND-değişken sınıfında SkipList<T> deklare edilmediği ve (her iplik koleksiyonu .Add çağırır ve ifadeleri ekleyin .randomLevel)

+0

"Rnd" nerede bildirildi? – ChrisF

+0

, ayrı bir iş parçacığı denilen randomlevel() nedir? – Benny

+0

, açıklık beyanı ekledi, bir kez ilan edildi ve birkaç farklı ileti dizisinden çağrıldı. – thr

cevap

4

lock deneyin çeşitli iplikler erişilir Random nesnesinin oluşturulması. Birden çok iş parçacığı aynı anda Random nesneye eriştiklerinde

int RandomLevel() 
{ 
    int height = 1; 

    lock(rnd) 
    { 
     while(rnd.NextDouble >= 0.5 && height < MaxHeight) height++; 
    } 

    return height; 
} 

çarpışmaları ile ilgili bir sorun olabilir ve tohum bozuk getting olabilir. özellikle olup bitene ilişkin herhangi bir bilgi veremiyorum, ancak MSDN'a göre, Random türünün örneklerinin iş parçacığı için güvenli olduğu garanti edilmez, bu nedenle her durumda lock görünüyor.

+0

bu şekilde kilitlemelisiniz: çift d; lock (rnd) d = rnd.NextDouble(); Bu daha iyi performans – Benny

+1

Tüm süre döngüsünü kilitlemek biraz kötü bir fikir gibi görünüyor. –

+1

Benny: Senden şüphe etmiyorum, ama nedenini açıklamaya dikkat et? Zihnimde kilitleme işlemini birkaç kez yapmam gerektiğinden daha kötü bir performans sergileyecekti. – thr

1

Döngününüzü çağrılan sürenin yarısından daha az çalıştırıyor gibi görünüyor - aradığınız şey (0 ile 1 arasında rastgele bir sayı> 0 olduğunda? Bu neden aldığınızı açıklayabilir "1 "beklediğinizden daha sık - en azından yarım zaman, hatta yüksekliği artıran döngüde koşmuyor - sadece yüksekliği 1'e ayarlar, değişmez ve" 1 "i döndürür. atlama listelerine aşina olduğu için, bu kasıtlı olabilir, ama sormam gerektiğini düşündüm.

Rasgele sayılar ile çalışmaya çok aşina değilim, ama bir tohumlama probleminiz olabilir mi? Rastgele nesneyi örneklediğinizde rastgele hale getirmiyorsanız, gerçekten rastgele olanların yerine tahmin edilebilir bir sayı dizisi verebiliriz. Belki de davranışa neden olmaz. Burada görüyorsun, ama ilerlemeyi düşünecek bir şey var. Tüm süre boyunca kilitlenmezdim.

3

Sadece rnd.NextDouble() çağrılarını kilitleyin.

int RandomLevel() 
{ 
    int height = 1; 
    double newRand; 

    lock(rnd) { newRand = rnd.NextDouble(); } 

    while(newRand >= 0.5 && height < MaxHeight) 
    { 
    height++; 
    lock(rnd) { newRand = rnd.NextDouble(); } 
    } 

    return height; 
} 

performansı dikkat etmeniz gereken durumlarda iş parçacıklı performans vs tek dişli bir farklılık olabileceğini olarak, kesinlikle her iki çözümleri karşılaştırmak olsa da

.