मैं इस फ़ॉरच कोड को Parallel.ForEach में कैसे बदल सकता हूँ?


180

मैं थोड़ा उलझन में हूं Parallel.ForEach
क्या है Parallel.ForEachऔर यह वास्तव में क्या करता है?
कृपया किसी भी MSDN लिंक का संदर्भ न लें।

यहाँ एक सरल उदाहरण दिया गया है:

string[] lines = File.ReadAllLines(txtProxyListPath.Text);
List<string> list_lines = new List<string>(lines);

foreach (string line in list_lines)
{
    //My Stuff
}

मैं इस उदाहरण को फिर से कैसे लिख सकता हूं Parallel.ForEach?


इसका जवाब यहां दिया जा सकता है। stackoverflow.com/questions/3789998/…
उज्जवल मनंधर

1
@UjjwalManander वास्तव में काफी अलग है, क्योंकि यह Parallelकक्षा के बीच के अंतर और PLINQ का उपयोग करने के बारे में पूछ रहा है ।
रीड कोपसे

18
दूसरों ने उत्तर दिया है कि आप कैसे फिर से लिख सकते हैं। तो फिर यह क्या करता है? यह संग्रह में प्रत्येक आइटम पर एक "एक्शन" करता है, सामान्य की तरह foreach। अंतर यह है कि समानांतर संस्करण एक ही समय में कई "क्रियाएं" कर सकता है। ज्यादातर मामलों में (यह निर्भर करता है कि कंप्यूटर क्या कोड चला रहा है, और यह कितना व्यस्त है, और अन्य सामान) यह तेजी से होगा, और यह सबसे महत्वपूर्ण लाभ है। ध्यान दें कि जब आप इसे समानांतर में करते हैं, तो आप यह नहीं जान सकते हैं कि आइटम किस क्रम में संसाधित किए जाते हैं। एक सामान्य (धारावाहिक) के साथ foreach, आपको इस lines[0]बात की गारंटी दी जाती है कि पहले, फिर lines[1], और इतने पर आता है।
जेपी स्टिग नीलसन

1
@JeppeStigNielsen यह हमेशा तेज नहीं होगा क्योंकि चीजों को समानांतर बनाने के साथ महत्वपूर्ण ओवरहेड है। यह उस संग्रह के आकार पर निर्भर करता है जिस पर आप पुनरावृत्ति कर रहे हैं और उसके भीतर की क्रिया। सही बात यह है कि वास्तव में Parallel.ForEach () और foreach () का उपयोग करने के बीच अंतर को मापना है। कई बार एक सामान्य फ़ॉरच्यू () तेज़ होता है।
डेव ब्लैक

3
@DaveBlack ज़रूर। प्रत्येक को यह मापना होगा कि यह तेज है या धीमा, प्रत्येक मामले में। मैं सामान्य रूप से समानांतर वर्णन करने का प्रयास कर रहा था।
जेपी स्टिग नीलसन

जवाबों:


126
string[] lines = File.ReadAllLines(txtProxyListPath.Text);
List<string> list_lines = new List<string>(lines);
Parallel.ForEach(list_lines, line =>
{
    //Your stuff
});

6
बस इसे इंगित करना चाहता था (ओपी के लिए अधिक) ताकि कोई गुमराह न हो कि यह केवल काम करता है List<T>;)
रीड कोपसे

1
ध्यान और उत्तर के लिए धन्यवाद। मैं अपने कोड में सूची <string> का इस्तेमाल किया क्योंकि HSH सूचियों का उपयोग कर डुप्लिकेट आइटम को हटाने। नियमित सरणी के साथ हम डुप्लिकेट को आसानी से नहीं हटा सकते हैं :)।
सिल्वरलाइट

119
मुझे भ्रम है कि इस उत्तर को सही उत्तर के रूप में चिह्नित किया गया है, क्योंकि मूल पदों के बारे में कोई स्पष्टीकरण नहीं है सवाल "Parallel.ForEach क्या है और यह वास्तव में क्या करता है?" ...
fose

6
@fosb समस्या यह है कि शीर्षक शीर्षक को पूरी तरह से अर्थ बदलने के लिए संपादित किया गया था ... इसलिए यह उत्तर अब कोई अर्थ नहीं रखता है। कहा जा रहा है कि, यह अभी भी एक खराब जवाब है
aw04

273

फाड़नेवाला लूप:

  • क्रमिक रूप से, एक-एक करके परिवर्तन होते रहते हैं
  • foreach लूप को एक थ्रेड से चलाया जाता है।
  • foreach लूप को .NET के हर फ्रेमवर्क में परिभाषित किया गया है
  • का निष्पादन धीमी प्रक्रियाओं हो सकता है धीमी रूप में वे क्रमानुसार चलाने कर रहे हैं,
    • जब तक 1 नहीं किया जाता है तब तक प्रक्रिया 2 शुरू नहीं हो सकती है। प्रक्रिया 3 तब तक शुरू नहीं हो सकती जब तक 2 और 1 नहीं हो जाते ...
  • त्वरित प्रक्रियाओं का निष्पादन तेजी से हो सकता है , क्योंकि कोई थ्रेडिंग ओवरहेड नहीं है

Parallel.ForEach:

  • निष्पादन समानांतर रूप से होता है।
  • Parallel.ForEach कई थ्रेड का उपयोग करता है।
  • Parallel.ForEach को .Net 4.0 और उससे ऊपर के फ्रेमवर्क में परिभाषित किया गया है।
  • धीमी प्रक्रियाओं का निष्पादन तेज हो सकता है , क्योंकि उन्हें समानांतर में चलाया जा सकता है
    • प्रक्रियाएं 1, 2, और 3 समवर्ती रूप से चल सकती हैं (उदाहरण में पुन: उपयोग किए गए थ्रेड देखें, नीचे)
  • अतिरिक्त थ्रेडिंग ओवरहेड के कारण त्वरित प्रक्रियाओं का निष्पादन धीमा हो सकता है

निम्न उदाहरण स्पष्ट रूप से पारंपरिक फॉरेस्ट लूप और के बीच के अंतर को दर्शाता है

समानांतर .orEach () उदाहरण

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace ParallelForEachExample
{
    class Program
    {
        static void Main()
        {
            string[] colors = {
                                  "1. Red",
                                  "2. Green",
                                  "3. Blue",
                                  "4. Yellow",
                                  "5. White",
                                  "6. Black",
                                  "7. Violet",
                                  "8. Brown",
                                  "9. Orange",
                                  "10. Pink"
                              };
            Console.WriteLine("Traditional foreach loop\n");
            //start the stopwatch for "for" loop
            var sw = Stopwatch.StartNew();
            foreach (string color in colors)
            {
                Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(10);
            }
            Console.WriteLine("foreach loop execution time = {0} seconds\n", sw.Elapsed.TotalSeconds);
            Console.WriteLine("Using Parallel.ForEach");
            //start the stopwatch for "Parallel.ForEach"
             sw = Stopwatch.StartNew();
            Parallel.ForEach(colors, color =>
            {
                Console.WriteLine("{0}, Thread Id= {1}", color, Thread.CurrentThread.ManagedThreadId);
                Thread.Sleep(10);
            }
            );
            Console.WriteLine("Parallel.ForEach() execution time = {0} seconds", sw.Elapsed.TotalSeconds);
            Console.Read();
        }
    }
}

उत्पादन

Traditional foreach loop
1. Red, Thread Id= 10
2. Green, Thread Id= 10
3. Blue, Thread Id= 10
4. Yellow, Thread Id= 10
5. White, Thread Id= 10
6. Black, Thread Id= 10
7. Violet, Thread Id= 10
8. Brown, Thread Id= 10
9. Orange, Thread Id= 10
10. Pink, Thread Id= 10
foreach loop execution time = 0.1054376 seconds

Parallel.ForEach उदाहरण का उपयोग करना

1. Red, Thread Id= 10
3. Blue, Thread Id= 11
4. Yellow, Thread Id= 11
2. Green, Thread Id= 10
5. White, Thread Id= 12
7. Violet, Thread Id= 14
9. Orange, Thread Id= 13
6. Black, Thread Id= 11
8. Brown, Thread Id= 10
10. Pink, Thread Id= 12
Parallel.ForEach() execution time = 0.055976 seconds

62
मैं वास्तव में आपके 'दावे' से सहमत नहीं हूं कि Parallel.ForEach (हमेशा) तेज है। यह वास्तव में लूप के अंदर ऑपरेशन पर भारीपन पर निर्भर करता है। यह पैरालिज्म का परिचय देने के ओवरहेड के लायक हो भी सकता है और नहीं भी।
मार्ताओ

1
खैर, प्रत्येक के लिए समानांतर का मतलब है कि लूप बॉडी में कोड को निष्पादित करने के लिए अलग-अलग थ्रेड स्थापित किए जाते हैं। भले ही .NET के पास ऐसा करने के लिए कुशल तंत्र है, लेकिन यह काफी अधिक है। इसलिए, यदि आपको बस एक साधारण ऑपरेशन (जैसे एक राशि या गुणा) करना है, तो समानांतर फॉर्च्यूनर तेज नहीं होना चाहिए।
मार्ताओ

3
@ जिग्नेश यह अच्छा माप उदाहरण भी नहीं है, इसलिए मैं इसका उल्लेख नहीं करूंगा। निकालें "थ्रेड। स्लीप (10);" प्रत्येक लूप बॉडी से और इसे फिर से आज़माएं।
1

1
@ मर्टाओ सही है, समस्या ऑब्जेक्ट लॉकिंग ओवरहेड्स के साथ है जहां समानांतर दृष्टिकोण अनुक्रमिक से अधिक लंबा हो सकता है।
1

8
@ तेजी से मुझे लगता है कि नींद ठीक यही कारण है कि यह एक अच्छा उदाहरण है। आप तेज एकल पुनरावृत्तियों के साथ एक PFE का उपयोग नहीं करेंगे (जैसा कि मार्ताओ ने समझाया) - इसलिए यह उत्तर पुनरावृत्ति को धीमा कर रहा है, और PFE के (सही) लाभ को उजागर किया गया है। हालांकि मैं मानता हूं कि इस उत्तर में समझाने की जरूरत है, एक बोल्ड "हमेशा तेज होता है" बहुत भ्रामक है।
मफू

43
string[] lines = File.ReadAllLines(txtProxyListPath.Text);

// No need for the list
// List<string> list_lines = new List<string>(lines); 

Parallel.ForEach(lines, line =>
{
    //My Stuff
});

यह लाइनों को समानांतर में, लूप के भीतर पार्स किया जाएगा। यदि आप समानांतर वर्ग के लिए अधिक विस्तृत, कम "संदर्भ उन्मुख" परिचय चाहते हैं, तो मैंने TPL पर एक श्रृंखला लिखी जिसमें Parallel.ForEach पर एक खंड शामिल है ।


9

बड़ी फ़ाइल के लिए निम्न कोड का उपयोग करें (आपको भूख कम लगती है)

Parallel.ForEach(File.ReadLines(txtProxyListPath.Text), line => {
    //Your stuff
});

2

इन पंक्तियों ने मेरे लिए काम किया।

string[] lines = File.ReadAllLines(txtProxyListPath.Text);
var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount * 10 };
Parallel.ForEach(lines , options, (item) =>
{
 //My Stuff
});
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.