2017-03-15 12 views
8

Parallel.ForEach()MaxDegreeOfParallelism==1 के साथ इनपुट इनपुट क्रम में संसाधित करने की गारंटी है?समानांतर होगा। MaxEegreeOfParallelism = 1 के साथ प्रक्रिया के लिए प्रक्रिया?

यदि उत्तर "नहीं" है, तो क्या इस व्यवहार को लागू करने का कोई तरीका है?

+0

यह एक अच्छा सवाल है, और मुझे लगता है कि जवाब हां के आधार पर हां है। https://msdn.microsoft.com/en-us/library/system.threading.tasks.paralleloptions.maxdegreeofparallelism(v=vs.110).aspx आप हमेशा कुछ परीक्षण मामलों को स्पिन कर सकते हैं और सत्यापित कर सकते हैं। – mituw16

+4

क्या मैं पूछ सकता हूं कि आप यह क्यों जानना चाहते हैं? सिर्फ अकादमिक जिज्ञासा, या आप किसी वास्तविक दुनिया के मुद्दे का सामना कर रहे हैं? – mason

+1

@ mituw16: मुझे लिंक किए गए एमएसडीएन आलेख में इस पर कोई संकेत नहीं मिल रहा है। कुछ परीक्षणों को कताई भी "हां" के लिए कोई गारंटी नहीं है। –

उत्तर

3
MSDN से

:

Parallel.ForEach विधि निष्पादन के आदेश की गारंटी नहीं है। एक अनुक्रमिक ForEach पाश के विपरीत, आने वाले मान हमेशा क्रम में संसाधित नहीं होते हैं।

https://msdn.microsoft.com/library/ff963552.aspx

10

सबसे पहले, यह Microsoft's official documentation on parallel programming कहा गया है कि कि निष्पादन आदेश इसकी गारंटी नहीं है सही है।

समांतर। फोरेच विधि निष्पादन के आदेश की गारंटी नहीं देता है। एक अनुक्रमिक ForEach पाश के विपरीत, आने वाले मान हमेशा क्रम में संसाधित नहीं होते हैं। एक समानांतर ढंग में आइटम पर कार्रवाई करने के:

यह सबसे अच्छा के रूप में सार्वजनिक एपीआई बनाया गया है Parallel.ForEach उपयोग करने के लिए किया जाएगा। यदि आपको क्रमशः वस्तुओं को संसाधित करने की आवश्यकता है, तो आप नियमित foreach लूप का उपयोग करके बहुत बेहतर हैं। इरादा MaxDegreeOfParallelism = 1 का उपयोग करने से स्पष्ट है।

कहा जा रहा है कि, जिज्ञासा के लिए, मैंने .NET 4.7.1 के लिए स्रोत कोड पर एक नज़र डाली। संक्षिप्त उत्तर हां है, यदि आइटम MaxDegreeOfParallelism = 1 पर क्रमशः संसाधित किए जाएंगे। हालांकि, आपको भविष्य में कार्यान्वयन के लिए इस पर भरोसा नहीं करना चाहिए, क्योंकि यह हमेशा ऐसा नहीं हो सकता है।

Parallel.ForEach पर एक नज़र ले रहा है और इसके माध्यम से निम्नलिखित आपको धीरे-धीरे देखेंगे कि संग्रह से अधिक दोहराया जा करने के लिए विभाजित है (इस प्रक्रिया थोड़ी अलग है कि क्या यह एक TSource[], List<TSource>, या एक IEnumerable<TSource> है।

Task.SavedStateForNextReplica और Task.SavedStateFromPreviousReplica क्रम में चल रहे कार्य के बीच राज्य से संवाद करने में ParallelForReplicaTask में अधिरोहित कर रहे हैं। इस मामले में, वे जो विभाजन कार्य से अधिक पुनरावृति चाहिए संवाद करने के लिए उपयोग किया जाता है।

अंत में, के Task.ExecuteSelfReplicating पर एक नज़र डालते हैं। 012,निर्दिष्ट पैरामीटर के साथ-साथ कार्य शेड्यूलर के MaximumConcurrencyLevel की डिग्री के आधार पर ShouldReplicate ओवरराइड करता है। तो, MaxDegreeOfParallelism = 1 के साथ यह केवल एक ही बच्चा कार्य करेगा। इस प्रकार, यह कार्य केवल एक ही विभाजन पर काम करेगा जो बनाया गया था।

तो, आपके सवाल का जवाब देना: लेखन के रूप में, Parallel.ForEachMaxDegreeOfParallism = 1 साथ संग्रह from beginning to end एक TSource[], एक IList<TSource> के लिए from beginning to end, और use GetEnumerator के लिए एक IEnumerable<TSource> के लिए करता है, तो IEnumerable<TSource> डाली जा सकती है, पर निर्भर करता है थोड़ा अलग रास्तों के साथ की गणना करेगा, OrderablePartitioner<TSource> पर या नहीं। ये तीन पथ Parallel.ForEachWorker में निर्धारित किए गए हैं।

मैं आपको अपने आप को देखने के लिए स्रोत कोड को ब्राउज़ करने के लिए दृढ़ता से प्रोत्साहित करता हूं।

मुझे आशा है कि यह आपके प्रश्न का उत्तर देने में सक्षम है, लेकिन यह याद रखना वाकई महत्वपूर्ण है: इस पर भरोसा न करें। यह बहुत संभव है कि भविष्य में यह कार्यान्वयन बदल सकता है।

संबंधित मुद्दे