100000 行の大きな txt ファイルがあります。n カウントのスレッドを開始し、このファイルからすべてのスレッドに固有の行を与える必要があります。
これを行う最善の方法は何ですか?ファイルを1行ずつ読み取る必要があり、イテレータをロックするにはグローバルにする必要があると思います。リストへのテキスト ファイルの読み込みには時間がかかり、OutofMemory
例外が発生する可能性があります。何か案は?
100000 行の大きな txt ファイルがあります。n カウントのスレッドを開始し、このファイルからすべてのスレッドに固有の行を与える必要があります。
これを行う最善の方法は何ですか?ファイルを1行ずつ読み取る必要があり、イテレータをロックするにはグローバルにする必要があると思います。リストへのテキスト ファイルの読み込みには時間がかかり、OutofMemory
例外が発生する可能性があります。何か案は?
61,277,203 行をメモリにロードし、値を Dictionary / ConcurrentDictionary() に押し込むための独自のベンチマークを実行した後、結果は、次のアプローチを使用することが最速であるという上記の @dtb の回答をサポートしているようです。
Parallel.ForEach(File.ReadLines(catalogPath), line =>
{
});
私のテストでは、次のことも示されました。
このページには含まれていないため、参照用にこのパターンの例を含めました。
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);
ここに私のベンチマークがあります:
特定の処理条件下では、生産者/消費者パターンが単純な Parallel.ForEach(File.ReadLines()) パターンよりも優れている可能性があると思います。ただし、この状況ではそうではありませんでした。
何かのようなもの:
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();
}
}
うまくいくと思います。(ここには C# コンパイラ/IDE はありません)
上記の @dtb のように、ファイルを読み取り、ファイル内の個々の行を処理する最速の方法は次のとおりです。1) File.ReadAllLines() を配列に実行する 2) Parallel.For ループを使用して配列を反復処理する.
詳細なパフォーマンス ベンチマークについては、こちらを参照してください。
あなたが書かなければならないコードの基本的な要点は次のとおりです。
string[] AllLines = File.ReadAllLines(fileName);
Parallel.For(0, AllLines.Length, x =>
{
DoStuff(AllLines[x]);
//whatever you need to do
});
.Net4 でのより大きな配列サイズの導入により、十分なメモリがある限り、これは問題になりません。