2010-05-05 30 views
12

में समांतर विशेषताएं। मैं नेट 4.0 में कुछ नई समांतर सुविधाओं की व्यावहारिकता पर जा रहा हूं।.NET 4.0

मैं बहुत की तरह कोड है कहते हैं:

foreach (var item in myEnumerable) 
    myDatabase.Insert(item.ConvertToDatabase()); 

कल्पना कीजिए myDatabase.Insert एक SQL डेटाबेस को सम्मिलित करने के लिए कुछ काम कर रहा है।

सैद्धांतिक रूप से आप लिख सकते हैं:

Parallel.ForEach(myEnumerable, item => myDatabase.Insert(item.ConvertToDatabase())); 

और स्वचालित रूप से आप कोड है कि कई कोर का लाभ लेता है मिलता है।

लेकिन क्या होगा यदि मेरा अनन्य केवल एक धागे से ही बातचीत की जा सके? समांतर वर्ग एक धागे द्वारा गणना करेगा और केवल लूप में कार्यकर्ता धागे के परिणाम को प्रेषित करेगा?

क्या होगा यदि मेराडेटाबेस केवल एक थ्रेड द्वारा ही बातचीत की जा सके? लूप के प्रति पुनरावृत्ति के लिए डेटाबेस कनेक्शन बनाना निश्चित रूप से बेहतर नहीं होगा।

अंत में, यदि मेरा "var item" उपयोगकर्ता नियंत्रण या ऐसा कुछ होता है जिसे यूआई थ्रेड पर इंटरैक्ट किया जाना चाहिए?

इन समस्याओं को हल करने के लिए मुझे किस डिजाइन पैटर्न का पालन करना चाहिए?

यह मुझे देख रहा है कि समानांतर/PLinq/आदि पर स्विच करना बिल्कुल वास्तविक नहीं है जब आप असली दुनिया के अनुप्रयोगों से निपट रहे हैं।

उत्तर

12

IEnumerable<T> इंटरफ़ेस मूल रूप से थ्रेड सुरक्षित नहीं है। Parallel.ForEach स्वचालित रूप से इसे संभालेगा, और केवल आपके गणना से आने वाली वस्तुओं को समानांतर करेगा। (क्रम में हमेशा एक तत्व, ट्रैवर्स किया जाएगा, लेकिन परिणामस्वरूप ऑब्जेक्ट्स समानांतर हो जाते हैं।)

यदि आपकी कक्षाएं (यानी: टी) को एकाधिक धागे से नियंत्रित नहीं किया जा सकता है, तो आपको कोशिश नहीं करनी चाहिए इस दिनचर्या को समानांतर करने के लिए। प्रत्येक अनुक्रम समानांतरता के लिए एक उम्मीदवार नहीं है - यह एक कारण है कि यह संकलक द्वारा स्वचालित रूप से नहीं किया जाता है;)

यदि आप काम कर रहे हैं जिसके लिए यूआई थ्रेड के साथ काम करने की आवश्यकता है, तो यह अभी भी संभव है। हालांकि, आपको वही देखभाल करने की आवश्यकता होगी जब भी आप पृष्ठभूमि थ्रेड पर उपयोगकर्ता इंटरफ़ेस तत्वों से निपट रहे हों, और डेटा को यूआई थ्रेड पर वापस मार्शल करें। इसे नए TaskScheduler.FromCurrentSynchronizationContext एपीआई का उपयोग करके कई मामलों में सरलीकृत किया जा सकता है। मैंने this scenario on my blog here लिखा था।

+1

अब तक का सबसे अच्छा जवाब, साइड सवाल हालांकि: मेरा लूप-बॉडी एक लंबे समय तक चलने वाले आईओ ऑपरेशन (नेटवर्क अनुरोध, डेटाबेस इत्यादि) करता है, क्या समांतर वर्ग नींद/निलंबित धागे का पता लगाएगा और स्वचालित रूप से एक नया शुरू करेगा? या यह मशीन पर कोर की संख्या तक सीमित रहेगा? – jonathanpeppers

+0

@ जोनाथन। पेपर: डिफ़ॉल्ट कार्य शेड्यूलर यह बहुत अच्छी तरह से संभालता है। यह स्थिति में अतिरिक्त काम इंजेक्षन करेगा। (डिफ़ॉल्ट रूप से, थ्रेडपूल धागे की तुलना में कई और तत्वों का उपयोग करता है, और गतिशील रूप से वर्कलोड के आधार पर वापस स्केल करता है) –

2

आप अनुमान लगाया है, Parallel.For या Parallel.ForEach का लाभ लेने की आवश्यकता है आप असतत इकाइयों में अपने काम (अपने लैम्ब्डा बयान है कि Parallel.ForEach को पारित कर दिया है द्वारा सन्निहित) कि स्वतंत्र रूप से क्रियान्वित किया जा सकता रचना करने की क्षमता है।

+0

क्या कोई वास्तविक दुनिया की समस्याएं इस मानदंड को पूरा करती हैं? दूसरे शब्दों में, क्या औसत एप्लिकेशन भी इन समानांतर सुविधाओं का उपयोग करने में सक्षम होगा? – jonathanpeppers

+0

@ जोनाथन: बिलकुल। स्कॉट हंसेलमैन द्वारा इस प्रस्तुति पर नज़र डालें, जहां वह इस काम के बारे में एक ज्वलंत उदाहरण दिखाता है। http://channel9.msdn.com/posts/matthijs/Lap- आसपास-NET-4-with- स्कॉट- हंसेलमैन/प्रदर्शन 38 मिनट, 55 सेकंड में शुरू होता है, और 47:02 पर समाप्त होता है। –

+0

स्पष्ट रूप से उनकी वेबसाइट में 38:55 को छोड़ने में कुछ परेशानी है, मुझे घर पर पूरी चीज देखना होगा और आपको वापस मिलना होगा। मुझे अभी भी संदेह है कि वे एक अच्छा उदाहरण देने जा रहे हैं। – jonathanpeppers

0

यहां उत्तर और टिप्पणियों में एक महान चर्चा है: Parallel.For(): Update variable outside of loop

उत्तर नहीं: समांतर एक्सटेंशन आपके लिए नहीं सोचेंगे। मल्टीथ्रेड मुद्दे अभी भी वास्तविक हैं। यह अच्छा वाक्यविन्यास चीनी है, लेकिन एक पैनसिया नहीं है।

+0

यह सिर्फ वाक्य रचनात्मक चीनी से थोड़ा अधिक है।उदाहरण के लिए, आप समांतरता की डिग्री निर्दिष्ट कर सकते हैं, और एक रद्द दिनचर्या को हुक कर सकते हैं जो सभी धागे को गहराई से खोल देगा। –

6

ये सभी वैध मुद्दे हैं - और PLINQ/TPL उन्हें संबोधित करने का प्रयास नहीं करते हैं। यह अभी भी डेवलपर के रूप में आपका काम कोड लिखने के लिए है जो समानांतर होने पर सही ढंग से कार्य कर सकता है। कोई जादू नहीं है कि संकलक/टीपीएल/PLINQ थ्रेड-सुरक्षित कोड में मल्टीथ्रेडिंग के लिए असुरक्षित कोड को कन्वर्ट करने के लिए कर सकता है ... आपको यह सुनिश्चित करना होगा कि आप ऐसा करते हैं।

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

टीपीएल धाराओं को कई धागे के लिए गणना करने के मामले में, आपका अनुमान सही है। अनुक्रम एक धागे पर गिनती है और प्रत्येक कार्य आइटम तब (संभावित रूप से) एक अलग धागे पर प्रेषित किया जाता है जिस पर कार्य किया जाता है।IEnumerable<T> इंटरफ़ेस मूल रूप से थ्रेडसेफ नहीं है, लेकिन टीपीएल आपके लिए दृश्यों के पीछे इसे संभालता है।

क्या PLINQ/TPL आपको करने में मदद करता है, यह प्रबंधित करता है कि कई धागे पर काम कब और कैसे प्रेषित किया जाए। टीपीएल का पता लगाता है जब मशीन पर एकाधिक कोर होते हैं और automaticaly डेटा को संसाधित करने के लिए उपयोग किए गए धागे की संख्या को स्केल करता है। यदि मशीन में केवल एक ही सीपीयू/कोर होता है, तो टीपीएल चुन सकता है जो काम को समानांतर नहीं करता है। आपके लिए लाभ, डेवलपर को दो अलग-अलग पथ लिखना नहीं है - एक समानांतर तर्क के लिए, एक अनुक्रमिक के लिए। हालांकि, यह सुनिश्चित करने के लिए ज़िम्मेदारी अभी भी आपकी है कि आपके कोड को कई धागे से सुरक्षित रूप से एक्सेस किया जा सकता है।

पर मुझे किस डिजाइन पैटर्न का पालन करना चाहिए इन समस्याओं को हल करना?

इस प्रश्न का कोई जवाब नहीं है ... हालांकि, एक सामान्य अभ्यास immutability को आपके ऑब्जेक्ट डिज़ाइन में नियोजित करना है। अपरिवर्तनीयता एक वस्तु को कई धागे में उपभोग करने के लिए सुरक्षित बनाती है और संचालन को समान बनाने में सबसे आम प्रथाओं में से एक है। वास्तव में, एफ # जैसी भाषाएं समवर्ती प्रोग्रामिंग को आसान बनाने में मदद करने के लिए भाषा को अनुमति देने के लिए अपरिवर्तनीयता का उपयोग करती हैं।

यदि आप .NET 4.0 पर हैं, तो आपको System.Collections.Concurrent में ConcurrentXXX संग्रह कक्षाओं को भी देखना चाहिए। यह वह जगह है जहां आपको कुछ लॉक-फ्री और जुर्माना लॉकिंग संग्रह संरचनाएं मिलेंगी जो मल्टीथ्रेड कोड को लिखना आसान बनाती हैं।

0

यह एक बहुत अच्छा सवाल है और उत्तर 100% स्पष्ट/संक्षिप्त नहीं है। मैं आपको माइक्रोसॉफ्ट से इस संदर्भ में इंगित करता हूं, यह WHEN you should use the parallel items के रूप में विस्तार से थोड़ा सा विवरण देता है।