मैं C#, Parallel.ForEach, और सामान्य रूप से .NET में नया हूं। मैं एक ऐसी खोज को समानांतर बनाना चाहता हूं जिसमें हजारों स्थान शामिल हों। प्रत्येक स्थान के लिए, मैं महान सर्कल दूरी की गणना करता हूं। यह एक गणना है जिसे मैं अलग-अलग कोर में फैलाना चाहता हूं। मेरा प्रश्न यह है कि मैं यह कैसे करूं यदि मेरे पास केवल एक थ्रेड-स्थानीय चर है, जैसा कि इस एमएसडीएन टीपीएल उदाहरण? परिणाम के लिए, मैंने Interlocked को देखा, और इसके विकल्प जोड़ें, CompareExchange, Decrement, देखे। एक्सचेंज, <कोड>इंक्रीमेंट और <कोड>पढ़ें, लेकिन मैं सिर्फ समानता के लिए जोड़, वृद्धि, कमी या परीक्षण नहीं कर रहा हूं। मैं ऑब्जेक्ट को समानांतर में चल रहे कई थ्रेड्स पर वापस करना चाहता हूं, जिसमें सबसे कम समग्र दूरी है। मेरा पेट कहता है कि यह आसान होना चाहिए, कि मैं कुछ छोटी वस्तु बनाने में सक्षम होना चाहिए जो एक स्थान और एक दूरी को लपेटता है, लेकिन मैं प्रत्येक धागे से सबसे अच्छा उत्तर कैसे प्राप्त करूं और फिर< /em> उनमें से सबसे छोटी दूरी चुनें? यहाँ गैर-समानांतर संस्करण है:

Location findClosestLocation(Location myLocation, List<Location> allLocations)
{
  double closest = double.MaxValue;
  Location closestLoc = null;
  foreach (Location aLoc in allLocations)
  {
    if (aLoc != myLocation)
    {
      double d = greatCircle(myLocation, aLoc);
      if (d < closest)
      {
        closest = d;
        closestLoc = aLoc;
      }
    }
  }
  return closestLoc;
}

मुझे एक DDJ ब्लॉग पोस्ट दिखाई दी जो अच्छी सलाह देती प्रतीत होती है , लेकिन मुझे आश्चर्य हुआ कि क्या यह सबसे अच्छी सलाह थी। मैं लेखक को सरणी पर लूपिंग देखता हूं, और आश्चर्य करता हूं कि ऐसा करने का कोई और अधिक कार्यात्मक तरीका नहीं है। कार्यात्मक दुनिया में मैं map, lambda और min का उपयोग करूंगा।

6
gknauth 24 जुलाई 2010, 02:17

1 उत्तर

सबसे बढ़िया उत्तर

यहां सबसे आसान विकल्प PLINQ पर स्विच करना होगा:

Location findClosestLocation(Location myLocation, List<Location> allLocations)
{
     return allLocations
               .AsParallel()
               .Min(location => greatCircle(myLocation, location));
}

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

बेहतर विकल्प Parallel.ForEach विधियों का उपयोग करना है जो स्थानीय राज्य। वे आपको इसे इस प्रकार फिर से लिखने की अनुमति देंगे:

Location findClosestLocation(Location myLocation, List<Location> allLocations)
{
  double closest = double.MaxValue;
  Location closestLoc = null;
  object sync = new object();

  Parallel.ForEach<Location, Tuple<double,Location>(
      allLocations,
      () => new Tuple(double.MaxValue, null),
      (location, loopState, localState) =>
      {
          double d = greatCircle(myLocation, aLoc);
          if (d < localState.Item1)
              return new Tuple(d, aLoc);
          else
              return localState;
      },
      localState =>
      {
          lock(sync)
          {
              if (localState.Item1 < closest)
              {
                  closest = localState.Item1;
                  closestLoc = localState.Item2;
              }
          }
      }
  );
  return closestLoc;
}

मैं के लिए स्थानीय स्थिति का उपयोग करके कवर करता हूं मेरे ब्लॉग पर विस्तार से एकत्रीकरण। यह मूल रूप से ऑपरेशन को एक लॉक ऑपरेशन प्रति थ्रेड के बजाय एक लॉक प्रति प्रोसेसिंग तत्व में बदल देता है, इसलिए आपको एक भोले लॉकिंग समाधान की तुलना में बहुत अधिक थ्रूपुट मिलता है।

11
Reed Copsey 24 जुलाई 2010, 02:44
वाह, यह लगभग उतना ही छोटा और मीठा है जितना इसे मिलता है। यह मेरे कार्यात्मक हृदय को गाता है। धन्यवाद!
 – 
gknauth
24 जुलाई 2010, 02:29
@gknauth: हाँ - मैंने (सही/निष्पादक) समानांतर जोड़ा। प्रत्येक विकल्प के लिए भी। मेरा सुझाव है कि दूसरा विकल्प कैसे काम करता है, और इसे समझने की कोशिश करें। यह मूल्यवान है, हालांकि, इनमें से अधिकतर परिचालनों के लिए, मैं सिर्फ PLINQ का उपयोग करता हूं क्योंकि यह बहुत बढ़िया है।
 – 
Reed Copsey
24 जुलाई 2010, 02:30
मुझे अपने ब्लॉग में शामिल करने के लिए धन्यवाद, बहुत अच्छा लग रहा है। एक किताब लिखो, मैं इसे खरीद लूंगा! या अगर वह बहुत अधिक काम है, तो मैं तुम्हारे लिए रात का खाना खरीद लूँगा।
 – 
gknauth
24 जुलाई 2010, 02:41
@gknauth: हे, धन्यवाद - मैंने इसे माना है, लेकिन कुछ अच्छे लोग जल्द ही बाहर आ रहे हैं। पैटर्न और व्यवहार टीपीएल पुस्तक अगस्त में इलेक्ट्रॉनिक रूप से प्रकाशित होगी (अक्टूबर में प्रिंट)। मैंने इसकी समीक्षा करने में मदद की - यह एक अच्छा है। इस बीच, मेरे पास इस विषय पर मेरे ब्लॉग पर बहुत सारी चीज़ें हैं (रास्ते में और अधिक के साथ;))
 – 
Reed Copsey
24 जुलाई 2010, 02:45