2008-09-19 19 views
13

में मल्टीथ्रेडिंग का उपयोग करके लूप को गति दें कल्पना कीजिए कि मेरे पास एक ऐसा कार्य है जो दस लाख/अरब तारों से गुजरता है और उनमें smth की जांच करता है।सी # (प्रश्न)

f.ex:

foreach (String item in ListOfStrings) 
{ 
    result.add(CalculateSmth(item)); 
} 

खपत बहुत समय के, क्योंकि CalculateSmth बहुत समय लगता कार्य है।

मैं पूछना चाहता हूं: इस तरह की प्रक्रिया में मल्टीथ्रेडिंग को एकीकृत कैसे करें?

f.ex: मैं 5 धागे को फायर-अप करना चाहता हूं और उनमें से प्रत्येक कुछ परिणाम देता है, और जब तक सूची में आइटम नहीं होते हैं तब तक चलता है।

मैं इसे में की जरूरत है हो सकता है कि किसी को भी कुछ उदाहरण या लेख .. दिखा सकते हैं

उल्लेख करने के लिए भूल .NET 2.0

+0

क्या आपको परिणामों को उसी क्रम में वापस करने की आवश्यकता है? – Keith

+0

क्या आप कई पृष्ठभूमि श्रमिकों का उपयोग कर सकते हैं? कुछ प्रकार के तर्क पैदा करते हैं जो तारों की सूची की गणना करेंगे और फिर बीडब्ल्यू की एक्स मात्रा बनायेंगे और इस मामले में प्रत्येक – Crash893

उत्तर

17

आप Parallel extensions (.NET 4.0 का हिस्सा)

ये अनुमति देते हैं की कोशिश कर सकते आप कुछ लिखने के लिए:

Parallel.Foreach (ListOfStrings, (item) => 
    result.add(CalculateSmth(item)); 
); 

बेशक परिणामस्वरूप। थ्रेड को सुरक्षित होने की आवश्यकता होगी।

+0

को विभाजित करेंगे, परिणाम संग्रह में कोई दौड़ स्थिति होगी? सभी एकाधिक धागे परिणाम निष्पादित हो सकते हैं। साथ ही साथ ... – cruizer

+0

परिणाम.add धागा सुरक्षित हाँ होना चाहिए .. – Tobi

+0

उल्लेख करना भूल गया मुझे इसकी आवश्यकता है .NET 2.0 –

1

यह नहीं कि मेरे पास अभी कोई अच्छा लेख है, लेकिन आप जो करना चाहते हैं वह थ्रेडपूल के साथ निर्माता-उपभोक्ता के साथ कुछ है।

निर्माता काम करता है और कार्यों को बनाता है (जो इस मामले में केवल सूची या ढेर में वस्तुओं को कतारबद्ध कर सकता है)। उपभोक्ता कहते हैं, पांच धागे जो स्टैक से एक वस्तु को पढ़ते हैं, इसे गणना करके इसका उपभोग करते हैं, और फिर इसे और स्टोर करते हैं।

इस तरह मल्टीथ्रेडिंग केवल उन पांच धागे तक ही सीमित है, और स्टैक खाली होने तक वे सभी काम करने के लिए काम करेंगे। इनपुट और आउटपुट सूची पर

  • रखें संरक्षण, इस तरह के एक म्युटेक्स के रूप में:

    हालात के बारे में सोचना।

  • यदि आदेश महत्वपूर्ण है, तो सुनिश्चित करें कि आउटपुट ऑर्डर बनाए रखा गया है। एक उदाहरण उन्हें सॉर्टेडलिस्ट या उस तरह कुछ स्टोर करने के लिए हो सकता है।
  • सुनिश्चित करें कि CalculateSmth थ्रेड सुरक्षित है, यह किसी भी वैश्विक स्थिति का उपयोग नहीं करता है।
2

पहला सवाल आप का जवाब देना होगा कि क्या आप

सूत्रण यदि आपका समारोह CalculateSmth() मूल रूप से सीपीयू बाध्य, यानी सीपीयू के उपयोग में भारी और मूल रूप से कोई आई/ओ-उपयोग है का उपयोग करना चाहिए है, तो मुझे थ्रेड का उपयोग करने के बिंदु को देखने में कठिनाई होती है, क्योंकि धागे उसी स्रोत पर प्रतिस्पर्धा कर रहे हैं, इस मामले में सीपीयू।

यदि आपकी गणना एसएमटी() दोनों सीपीयू और आई/ओ दोनों का उपयोग कर रही है, तो यह थ्रेडिंग का उपयोग करने में एक बिंदु हो सकती है।

मैं पूरी तरह से मेरे उत्तर की टिप्पणी से सहमत हूं। मैंने एक गलत धारणा की है कि हम एक कोर के साथ एक सिंगल सीपीयू के बारे में बात कर रहे थे, लेकिन इन दिनों हमारे पास बहु-कोर CPUs हैं, मेरा बुरा।

+1

निर्भर करता है कि यह एक बहु-कोर सिस्टम है या नहीं। यदि आपके पास चार कोर उपलब्ध हैं, उदाहरण के लिए, फिर चार धागे का उपयोग करके प्रसंस्करण में लगभग चार गुना गति-अप देखना चाहिए (धागे के बीच कोई अंतर-निर्भरता नहीं मानना)। –

18

समानांतर एक्सटेंशन शांत है, लेकिन यह भी सिर्फ इस तरह ThreadPool का उपयोग करके किया जा सकता है:

using System.Collections.Generic; 
using System.Threading; 

namespace noocyte.Threading 
{ 
    class CalcState 
    { 
     public CalcState(ManualResetEvent reset, string input) { 
      Reset = reset; 
      Input = input; 
     } 
     public ManualResetEvent Reset { get; private set; } 
     public string Input { get; set; } 
    } 

    class CalculateMT 
    { 
     List<string> result = new List<string>(); 
     List<ManualResetEvent> events = new List<ManualResetEvent>(); 

     private void Calc() { 
      List<string> aList = new List<string>(); 
      aList.Add("test"); 

      foreach (var item in aList) 
      { 
       CalcState cs = new CalcState(new ManualResetEvent(false), item); 
       events.Add(cs.Reset); 
       ThreadPool.QueueUserWorkItem(new WaitCallback(Calculate), cs); 
      } 
      WaitHandle.WaitAll(events.ToArray()); 
     } 

     private void Calculate(object s) 
     { 
      CalcState cs = s as CalcState; 
      cs.Reset.Set(); 
      result.Add(cs.Input); 
     } 
    } 
} 
+1

और यह कब समाप्त होता है जब आप जानते हैं? mmm। – leppie

+0

एक मैनुअल रीसेट इवेंट हो सकता है कि WaitCallback फ़ंक्शन कॉल और मुख्य थ्रेड WaitOne चालू हो। –

+0

यह दिखाने के लिए कोड जोड़ा गया है कि आप ऐसा करने के लिए एमआरई का उपयोग कैसे कर सकते हैं। – noocyte

12

ध्यान दें कि संगामिति जादुई आप और अधिक संसाधन नहीं देता है। आपको गणना करना चाहिए कि गणना करना धीमा हो रहा है।

उदाहरण के लिए, यदि यह सीपीयू-बाध्य है (और आप एक ही कोर पर हैं) तो सीपीयू टिक की एक ही संख्या कोड पर जाएगी, चाहे आप अनुक्रमिक रूप से या समानांतर में निष्पादित हों। इसके अलावा आप धागे के प्रबंधन से कुछ ओवरहेड प्राप्त करेंगे। वही तर्क अन्य बाधाओं पर लागू होता है (उदा। I/O)

यदि आप गणना निष्पादन के दौरान संसाधन मुक्त छोड़ रहे हैं तो आपको केवल प्रदर्शन लाभ मिलेगा, जिसका उपयोग किसी अन्य उदाहरण द्वारा किया जा सकता है। यह असामान्य नहीं है। उदाहरण के लिए, यदि कार्य में कुछ सीपीयू सामानों के बाद आईओ शामिल है, तो प्रक्रिया 1 सीपीयू सामान कर सकती है जबकि प्रक्रिया 2 आईओ कर रही है। चूंकि मैट बताते हैं, यदि आपके पास बुनियादी ढांचा है तो निर्माता-उपभोक्ता इकाइयों की एक श्रृंखला इसे प्राप्त कर सकती है।

5

आपको उस काम को विभाजित करने की आवश्यकता है जिसे आप समानांतर में करना चाहते हैं। यहां एक उदाहरण दिया गया है कि आप कैसे काम को दो में विभाजित कर सकते हैं:

List<string> work = (some list with lots of strings) 

// Split the work in two 
List<string> odd = new List<string>(); 
List<string> even = new List<string>(); 
for (int i = 0; i < work.Count; i++) 
{ 
    if (i % 2 == 0) 
    { 
     even.Add(work[i]); 
    } 
    else 
    { 
     odd.Add(work[i]); 
    } 
} 

// Set up to worker delegates 
List<Foo> oddResult = new List<Foo>(); 
Action oddWork = delegate { foreach (string item in odd) oddResult.Add(CalculateSmth(item)); }; 

List<Foo> evenResult = new List<Foo>(); 
Action evenWork = delegate { foreach (string item in even) evenResult.Add(CalculateSmth(item)); }; 

// Run two delegates asynchronously 
IAsyncResult evenHandle = evenWork.BeginInvoke(null, null); 
IAsyncResult oddHandle = oddWork.BeginInvoke(null, null); 

// Wait for both to finish 
evenWork.EndInvoke(evenHandle); 
oddWork.EndInvoke(oddHandle); 

// Merge the results from the two jobs 
List<Foo> allResults = new List<Foo>(); 
allResults.AddRange(oddResult); 
allResults.AddRange(evenResult); 

return allResults; 
संबंधित मुद्दे