我有一个包含 100000 行文本的大型 txt 文件。 我需要启动 n 个线程,并为每个线程分配唯一的文件行。
最好的方法是什么?我认为我需要逐行读取文件,迭代器必须是全局变量以进行锁定。将文本文件加载到列表中将耗费时间,我可能会遇到 OutofMemory 异常。有什么想法吗?
我有一个包含 100000 行文本的大型 txt 文件。 我需要启动 n 个线程,并为每个线程分配唯一的文件行。
最好的方法是什么?我认为我需要逐行读取文件,迭代器必须是全局变量以进行锁定。将文本文件加载到列表中将耗费时间,我可能会遇到 OutofMemory 异常。有什么想法吗?
Parallel.ForEach(File.ReadLines("file.txt"), (line, _, lineNumber) =>
{
// your code here
});
在将61,277,203行加载到内存中并将值推入字典/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())模式更优。然而,在这种情况下并不是这样。
File.ReadLines()
来避免大内存消耗的必要性,但是Parallel.ForEach(File.ReadLines())
真的比单线程处理更优吗?流是按顺序设计的,并且硬件只支持一次读取一个东西,因此使用多个线程来处理结果可能会增加阻塞和上下文切换的开销;有趣的是,仅使用单个线程处理File.ReadLines()
的结果的性能指标将会非常有趣。 - dragonfly02Something like:
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)
for (; i < j; i++)
{
thr[i] = new Thread(new ThreadStart(go));
thr[i].IsBackground = true;
thr[i].Start();
}
而不是 Parallel.ForEach。 - obdgyn
,最简单的方法是使用 AsParallel()
和 WithDegreeOfParallelism(n)
来限制线程数量:string filename = "C:\\TEST\\TEST.DATA";
int n = 5;
foreach (var line in File.ReadLines(filename).AsParallel().WithDegreeOfParallelism(n))
{
// Process line.
}
File.ReadLines()
,它基本上是一种类似于Python生成器的东西,内部使用Yield实现的? - Daan Timmeryield
实现的。 - Matthew Watsonstring[] AllLines = File.ReadAllLines(fileName);
Parallel.For(0, AllLines.Length, x =>
{
DoStuff(AllLines[x]);
//whatever you need to do
});
File.ReadLines
方法,获取正确位置的行并将它们传递给线程。 - Ilya Ivanov