2013-06-14 20 views
6

मैं दो घोंसले वाले लूपों को गति देने के लिए समांतर प्रसंस्करण का उपयोग करने की कोशिश कर रहा हूं, लेकिन मुझे सिंटैक्स सही होने में परेशानी हो रही है। मैं बिटमैप में कितने पिक्सेल लाल या सफेद या काले रंग के मूल्यों की गिनती करने की कोशिश कर रहा हूं, जिनके लिए मेरे पास कहीं और है।साझा चर के साथ समानांतर के लिए समानांतर

धारावाहिक प्रसंस्करण में मैं निम्नलिखित कोड है, जो ठीक काम करता है है:

:

 Bitmap image = new Bitmap(@"Input.png"); 
     var colourCount = new int[3]; 

     for (var x = 0; x < image.Width; x++) 
     { 
      for (var y = 0; y < image.Height; y++) 
      { 
       switch (image.GetPixel(x, y).ToArgb()) 
       { 
        case (int)colours.red: colourCount[0]++; break; 
        case (int)colours.white: colourCount[1]++; break; 
        case (int)colours.black: colourCount[2]++; break; 
        default: throw new ArgumentOutOfRangeException(string.Format("Unexpected colour found: '{0}'", image.GetPixel(x, y).ToArgb())); 
       } 
      } 
     } 

मैं माइक्रोसॉफ्ट द्वारा और Stackoverflow से छोरों कि इस तरह के नीचे के रूप में एक साझा चर का अद्यतन के लिए समानांतर के लिए कोड को देखा है

 Parallel.For<int>(0, result.Count,() => 0, (i, loop, subtotal) => 
     { 
      subtotal += result[i]; 
      return subtotal; 
     }, 
      (x) => Interlocked.Add(ref sum, x) 
     ); 

लेकिन सभी उदाहरण एक सरल प्रकार का उपयोग करते हैं जैसे एक साझा चर के रूप में int और मैं बस अपने आकार तीन सरणी को लिखने के लिए वाक्यविन्यास नहीं समझ सकता। क्या मैं यह सब गलत कर रहा हूँ?

वैसे, मुझे प्रदर्शन के संदर्भ में पता है कि GetPixel बिटमैप जैसे कुछ धीमे है। लॉकबिट्स, मैं बस समांतर लूप के सिद्धांत को प्राप्त करने की कोशिश कर रहा हूं।

उत्तर

4

आप Parallel.For का अधिभार उपयोग कर सकते हैं जो आपको थ्रेड-स्थानीय स्थिति को बनाए रखने की अनुमति देता है। इस मामले में, हम उत्पन्न होने वाले प्रत्येक थ्रेड के लिए int[3] सरणी बनाते हैं। समांतर लूप के प्रत्येक पुनरावृत्ति के भीतर, हम केवल स्थानीय सरणी, localColourCount अपडेट करते हैं। अंत में, जब थ्रेड को सेवानिवृत्त किया जाना है, तो हम प्रत्येक स्थानीय सरणी के परिणामों को वैश्विक, colourCount में एकत्रित करते हैं; हालांकि, चूंकि यह एक साझा डेटा संरचना है, इसलिए हम इसे एक्सेस करते समय आपसी बहिष्करण को लागू करते हैं।

Bitmap image = new Bitmap(@"Input.png"); 
var colourCount = new int[3]; 

Parallel.For(0, image.Width, 

    // localInit: The function delegate that returns the initial state 
    //   of the local data for each task. 
    () => new int[3], 

    // body: The delegate that is invoked once per iteration. 
    (int x, ParallelLoopState state, int[] localColourCount) => 
    { 
     for (var y = 0; y < image.Height; y++) 
     { 
      switch (image.GetPixel(x, y).ToArgb()) 
      { 
       case (int)colours.red: localColourCount[0]++; break; 
       case (int)colours.white: localColourCount[1]++; break; 
       case (int)colours.black: localColourCount[2]++; break; 
       default: throw new ArgumentOutOfRangeException(
          string.Format("Unexpected colour found: '{0}'", 
          image.GetPixel(x, y).ToArgb())); 
      } 
     } 
    }, 

    // localFinally: The delegate that performs a final action 
    //    on the local state of each task. 
    (int[] localColourCount) => 
    { 
     // Accessing shared variable; synchronize access. 
     lock (colourCount) 
     { 
      for (int i = 0; i < 3; ++i) 
       colourCount[i] += localColourCount[i]; 
     } 
    }); 

इस कोड को मानता है कि Bitmap.GetPixel, धागा सुरक्षित है जो या मामला नहीं हो सकता है।

एक और चीज़ जो आपको देखने की ज़रूरत है वह यह है कि ArgumentOutOfRangeException उदाहरण AggregateException में संयुक्त हो जाएंगे, इसलिए आपको अपना त्रुटि-कोडिंग कोड समायोजित करने की आवश्यकता होगी।

+0

आपको वास्तव में अपने 'स्थानीय' में 'लॉक' की आवश्यकता नहीं है। आप इसके बजाय अपने लूप में 'Interlocked.Add() 'का उपयोग कर सकते हैं। हालांकि 'लॉक' का उपयोग करना इसे और अधिक स्पष्ट रूप से सही बनाता है। – svick

+0

@svick: 'Interlocked.Add' के एकाधिक आमंत्रण एकल 'लॉक' से कम कुशल हो सकते हैं। (निश्चित रूप से मामला होगा यदि 'colourCount' में तत्वों के दस शामिल होते हैं; 3. के लिए सुनिश्चित नहीं है) प्रति [अल्बाहारी] (http://www.albahari.com/threading/part4.aspx): "सभी' इंटरलाक्ड '' तरीके एक पूर्ण बाड़ उत्पन्न करते हैं। " दोहराया कैश अमान्यता ओवरहेड एकल लॉक की लागत से अधिक हो सकता है। – Douglas

+0

इसे पोस्ट करने के लिए धन्यवाद, यह अब मेरे लिए बहुत अधिक समझ में आता है। आप यह सुझाव देने में सही हैं कि GetPixel थ्रेड-सुरक्षित नहीं है, वास्तव में किसी भी छवि गुणों या विधियों तक पहुंचने के लिए कोई संख्या नहीं है, इसलिए मुझे इसके चारों ओर एक रास्ता पता लगाना होगा, लेकिन मेरे पास लूप खुद ठीक काम कर रहा है। एक बार फिर धन्यवाद! –

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