2013-06-19 15 views
14

मेरे पास 100000 लाइनों के साथ बड़ी txt फ़ाइल है। मुझे धागे की एन-गिनती शुरू करने और इस फ़ाइल से प्रत्येक थ्रेड यूनिक लाइन देने की आवश्यकता है। ऐसा करने का सबसे अच्छा तरीका क्या है? मुझे लगता है कि मुझे लाइन द्वारा फ़ाइल लाइन पढ़ने की जरूरत है और इसे लॉक करने के लिए इटेटरेटर वैश्विक होना चाहिए। सूची में लोड txt फ़ाइल समय लेने वाली होगी और मैं आउटफमेमरी अपवाद प्राप्त कर सकता हूं। कोई विचार? कुछ कोड के साथ कृपया मदद करें।बड़ी txt फ़ाइल multithreaded पढ़ें?

+0

हमें दिखाएं कि आपने क्या – Peter

+0

अद्वितीय n यादृच्छिक संख्या, आरोही क्रम में आदेश बनाने की कोशिश की है, का उपयोग 'File.ReadLines', सही स्थानों पर लाइनों लेते हैं और उन्हें धागे को –

+0

आप इसका उपयोग नहीं किया जा सकता पारित: http://msdn.microsoft.com/en-us/library/dd460720.aspx? –

उत्तर

7

फ़ाइल को एक थ्रेड पर पढ़ें, इसकी लाइन blocking queue पर जोड़ें। उस कतार से पढ़ने वाले N कार्य शुरू करें। मेमोरी त्रुटियों से बचने के लिए कतार के max size सेट करें।

26

आप समानांतर में एक से अधिक थ्रेड में लाइनों पर कार्रवाई करने के File.ReadLines MethodParallel.ForEach Method का उपयोग एक ही बार में स्मृति में पूरे फ़ाइल लोड करने के बिना फ़ाइल पंक्ति-दर-पंक्ति को पढ़ने के लिए कर सकते हैं और:

Parallel.ForEach(File.ReadLines("file.txt"), (line, _, lineNumber) => 
{ 
    // your code here 
}); 
+1

यह उत्तर – Jonesopolis

+0

है मैं सहमत हूं। एकमात्र चीज जो मैं जोड़ना चाहता हूं वह यह है कि रीडलाइन को गणना करने योग्य होना चाहिए। क्योंकि प्रत्येक समांतर निष्पादन कुछ भारी के लिए होना चाहिए। – ozgur

+0

कुछ ध्यान में रखना: समांतर। Foreach 'श्रमिकों' का एक गुच्छा पैदा करेगा, तब तक प्रतीक्षा करें जब तक कि उनमें से सभी * कार्य नहीं किए जाते हैं और केवल तभी श्रमिकों के अगले समूह को जन्म देते हैं। इसलिए यदि प्रति पंक्ति प्रसंस्करण समय भिन्न हो सकता है तो यह जेक ड्रू के दृष्टिकोण (निर्माता/उपभोक्ता पैटर्न) –

2

कुछ की तरह :

public class ParallelReadExample 
{ 
    public static IEnumerable LineGenerator(StreamReader sr) 
    { 
     while ((line = sr.ReadLine()) != null) 
     { 
      yield return line; 
     } 
    } 

    static void Main() 
    { 
     // Display powers of 2 up to the exponent 8: 
     StreamReader sr = new StreamReader("yourfile.txt") 

     Parallel.ForEach(LineGenerator(sr), currentLine => 
      { 
       // Do your thing with currentLine here... 
      } //close lambda expression 
     ); 

     sr.Close(); 
    } 
} 

सोचें कि यह काम करेगा।

string filename = "C:\\TEST\\TEST.DATA"; 
int n = 5; 

foreach (var line in File.ReadLines(filename).AsParallel().WithDegreeOfParallelism(n)) 
{ 
    // Process line. 
} 
+0

thr = new थ्रेड [j] का उपयोग करके इसे फिर से लिखने के बारे में क्या; (; i obdgy

+1

@obdgy: आप ऐसा क्यों करना चाहते हैं? – dtb

+0

100-300 धागे शुरू करें – obdgy

1

आप n को धागे की संख्या को सीमित करना चाहते हैं, सबसे आसान तरीका है धागा गिनती सीमित करने के लिए WithDegreeOfParallelism(n) के साथ AsParallel() उपयोग करने के लिए है ऊपर उल्लिखित, फ़ाइल को पढ़ने का सबसे तेज़ तरीका और फिर फ़ाइल में अलग-अलग पंक्तियों को संसाधित करना है: 1) एक फ़ाइल करें। रीडअललाइन() एक सरणी में 2) समानांतर का उपयोग करें। सरणी पर फिर से चलाने के लिए लूप के लिए।

You can read more performance benchmarks here.

कोड के मूल सार आप लिखने के लिए होता है:

string[] AllLines = File.ReadAllLines(fileName); 
Parallel.For(0, AllLines.Length, x => 
{ 
    DoStuff(AllLines[x]); 
    //whatever you need to do 
}); 
.Net4 में बड़ा सरणी आकार की शुरूआत के साथ

, जब तक आप स्मृति के बहुत सारे है, यह एक मुद्दा नहीं होना चाहिए।

Parallel.ForEach(File.ReadLines(catalogPath), line => 
{ 

}); 

:

+0

अगर मैं 'फ़ाइल। रीडलाइन()' को सही ढंग से समझता हूं तो यह मूल रूप से यील्ड का उपयोग करके पाइथन-जैसे जनरेटर का एक प्रकार है? –

+0

@DanTimmer मुझे पायथन के बारे में कुछ भी पता नहीं है, लेकिन फ़ाइल। रीडलाइन() सिर्फ एक आईनेमेरेबल देता है जिसे 'उपज' –

+0

के माध्यम से कार्यान्वित किया जाता है, उस स्थिति में, आपका उत्तर समेकित किया जा सकता है, हाँ :-) –

2

@dtb के रूप में: (कोई सी # संकलक/आईडीई यहाँ)

11

मेरे अपने बेंचमार्क लोड करने के लिए एक शब्दकोश/ConcurrentDictionary() में मान स्मृति में 61,277,203 लाइनों प्रदर्शन और धकेल कर के बाद परिणाम निम्न दृष्टिकोण का उपयोग कर सबसे तेज है कि इसके बाद के संस्करण @ DTB के जवाब का समर्थन करने लगते हैं मेरे परीक्षण भी निम्न से पता चला है:।

  1. File.ReadAllLines() और File.ReadAllLines() AsParallel() इस आकार के एक फ़ाइल पर पर लगभग ठीक उसी गति से चलाने के लिए दिखाई देते हैं। मेरी सीपीयू गतिविधि को देखते हुए, ऐसा प्रतीत होता है कि वे दोनों मेरे 8 कोरों में से दो का उपयोग करते हैं?
  2. File.ReadAllLines() का उपयोग कर पहले सभी डेटा को पढ़ने के लिए समानांतर में फ़ाइल.ReadLines() का उपयोग करने से बहुत धीमी प्रतीत होती है। ForEach() लूप।
  3. मैंने निर्माता/उपभोक्ता या मैपरेडस शैली पैटर्न की भी कोशिश की जहां डेटा को पढ़ने के लिए एक धागा का उपयोग किया गया था और इसे दूसरी प्रक्रिया के लिए इस्तेमाल किया गया था। यह उपरोक्त सरल पैटर्न से बेहतर प्रदर्शन नहीं कर रहा था।

मैं, संदर्भ के लिए इस पद्धति का एक उदाहरण भी शामिल है के बाद से यह इस पृष्ठ पर शामिल नहीं है:

enter image description here

:

var inputLines = new BlockingCollection<string>(); 
ConcurrentDictionary<int, int> catalog = new ConcurrentDictionary<int, int>(); 

var readLines = Task.Factory.StartNew(() => 
{ 
    foreach (var line in File.ReadLines(catalogPath)) 
     inputLines.Add(line); 

     inputLines.CompleteAdding(); 
}); 

var processLines = Task.Factory.StartNew(() => 
{ 
    Parallel.ForEach(inputLines.GetConsumingEnumerable(), line => 
    { 
     string[] lineFields = line.Split('\t'); 
     int genomicId = int.Parse(lineFields[3]); 
     int taxId = int.Parse(lineFields[0]); 
     catalog.TryAdd(genomicId, taxId); 
    }); 
}); 

Task.WaitAll(readLines, processLines); 

यहाँ मेरी मानक हैं

मुझे संदेह है कि कुछ प्रसंस्करण स्थितियों के तहत, उपज आर/उपभोक्ता पैटर्न सरल समानांतर से अधिक प्रदर्शन कर सकता है। फॉरएच (फ़ाइल। रीडलाइन()) पैटर्न। हालांकि, यह इस स्थिति में नहीं था।

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