7

मैंने अभी कार्य समानांतर लाइब्रेरी के साथ खेलना शुरू किया, और दिलचस्प मुद्दों में भाग गया; मेरे पास क्या हो रहा है इसका एक सामान्य विचार है, लेकिन क्या हो रहा है यह समझने में सहायता के लिए लोगों से टिप्पणियों को मुझसे अधिक सक्षम बनाना चाहते हैं। कुछ हद तक लंबे कोड के लिए मेरी माफ़ी।समांतर लूप और यादृच्छिक परिणाम अजीब परिणाम

मैं एक यादृच्छिक चलने के एक गैर समानांतर सिमुलेशन के साथ शुरू किया:

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(); 

मैं तो एक समानांतर पाश में अपने पहले ही प्रयास लिखा है:

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(); 

जब मैं एक आभासी मशीन पर यह भाग गया केवल 1 कोर का उपयोग करने के लिए सेट, मैंने एक समान अवधि देखी, लेकिन रन अब क्रम में संसाधित नहीं किए गए हैं - कोई आश्चर्य नहीं।

जब मैंने इसे दोहरी कोर मशीन पर चलाया, तो चीजें अजीब हो गईं। मैंने समय में कोई सुधार नहीं देखा, और प्रत्येक रन के लिए कुछ अजीब परिणाम देखे। अधिकांश रन -1,000,000 के परिणाम के साथ समाप्त होते हैं, (या बहुत करीब), जो इंगित करता है कि Random.Next हर समय 0 quasi लौटा रहा है।

जब मैं प्रत्येक पाश के लिए यादृच्छिक स्थानीय बनाना, सब कुछ ठीक काम करता है, और मैं उम्मीद अवधि सुधार मिलती है:

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

मेरा अनुमान समस्या तथ्य के साथ क्या करना है कि यह है कि रैंडम वस्तु लूप के बीच साझा किया जाता है, और कुछ राज्य है। "असफल समानांतर" संस्करण में अवधि में सुधार की कमी मुझे लगता है कि रैंडम को कॉल समानांतर में संसाधित नहीं किया जाता है (भले ही मैं देखता हूं कि समांतर संस्करण कोर दोनों का उपयोग करता है, जबकि मूल नहीं है) । जिस टुकड़े को मैं वास्तव में नहीं मिला वह सिमुलेशन के परिणाम हैं जो वे हैं।

मेरी एक अलग चिंता यह है कि यदि मैं प्रत्येक लूप के लिए स्थानीय यादृच्छिक उदाहरणों का उपयोग करता हूं, तो मैं उसी बीज से शुरू होने वाले एकाधिक लूप होने की समस्या में भाग सकता हूं (जब आप कई रैंडोम्स को समय में बहुत करीब उत्पन्न करते हैं तो समस्या , जिसके परिणामस्वरूप समान अनुक्रम)।

क्या हो रहा है में कोई अंतर्दृष्टि मेरे लिए बहुत मूल्यवान होगी!

उत्तर

2

न तो इन तरीकों का क्या तुम सच में अच्छा यादृच्छिक संख्या दे देंगे।

इस ब्लॉग पोस्ट ये दिन आवेदन करने के लिए कई दिन के लिए ठीक हो सकता है रैंडम

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

के साथ बेहतर यादृच्छिक संख्या प्राप्त करने के लिए दृष्टिकोण का एक बहुत शामिल हैं।

हालांकि यदि आप कई थ्रेड पर एक ही यादृच्छिक संख्या जनरेटर का उपयोग करते हैं तो विभिन्न बीज के साथ भी आप अपने यादृच्छिक संख्याओं की गुणवत्ता को प्रभावित करेंगे। ऐसा इसलिए है क्योंकि आप छद्म-यादृच्छिक संख्याओं के अनुक्रम उत्पन्न कर रहे हैं जो ओवरलैप हो सकते हैं।

इस वीडियो बताता है कि क्यों एक सा और अधिक विस्तार से:

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

तुम सच में यादृच्छिक संख्या चाहते हैं तो आपको वास्तव में क्रिप्टो यादृच्छिक संख्या जनरेटर System.Security.Cryptography.RNGCryptoServiceProvider उपयोग करने के लिए की जरूरत है। यह थ्रेडसेफ है।

+0

एडी, एस टब लेख के सूचक के लिए धन्यवाद, यह उत्कृष्ट है। – Mathias

2

Random कक्षा थ्रेड-सुरक्षित नहीं है; यदि आप इसे एकाधिक धागे पर उपयोग करते हैं, तो यह गड़बड़ हो सकता है।

आप प्रत्येक धागे पर एक अलग Random उदाहरण बनाने के लिए, और यह सुनिश्चित करें कि वे एक ही बीज का उपयोग न करना पड़े बनाना चाहिए। (जैसे, Environment.TickCount * Thread.CurrentThread.ManagedThreadId)

+0

आप बीज मुद्दे के बारे में कैसे जाएंगे? – Mathias

+0

यदि आप इस दृष्टिकोण के साथ जाते हैं, जिसमें समस्याएं हैं, तो मैं टिककंट * प्रबंधन थ्रेड आईडी का उपयोग नहीं करता क्योंकि यह बीज पैदा करेगा जो बहुत करीब हैं। बीज पैदा करने के बेहतर तरीके के लिए नीचे मेरा उत्तर देखें। –

1

एक कोर समस्या:

  • random.Next सुरक्षित थ्रेड नहीं है।

दो असर:

  1. अनियमितता की गुणवत्ता दौड़ की स्थिति से नष्ट हो जाता है।
  2. गलत साझाकरण मल्टीकोर पर स्केलेबिलिटी को नष्ट कर देता है।

कई संभव समाधान:

  • random.Next धागा सुरक्षित बनाओ: गुणवत्ता की समस्या नहीं बल्कि scalability को हल करती है।
  • एकाधिक पीआरएनजी का प्रयोग करें: स्केलेबिलिटी समस्या हल करती है लेकिन गुणवत्ता खराब हो सकती है।
  • ...
संबंधित मुद्दे