C# PLINQ内部任务有时会变慢
我正在研究一些文本解析器逻辑,并且有IO和CPU绑定的操作。 通常我做的是:读取文件->处理文本,读取文件2->处理文本2。。。等等 我能做的就是让操作处理文本,并在不同的任务中同时执行读取文件2。然而,当我创建相关任务树时,我注意到PLINQ变得比最初慢。下面是代码的简化示例: 班级计划 { 静态int-idxC# PLINQ内部任务有时会变慢,c#,parallel-processing,C#,Parallel Processing,我正在研究一些文本解析器逻辑,并且有IO和CPU绑定的操作。 通常我做的是:读取文件->处理文本,读取文件2->处理文本2。。。等等 我能做的就是让操作处理文本,并在不同的任务中同时执行读取文件2。然而,当我创建相关任务树时,我注意到PLINQ变得比最初慢。下面是代码的简化示例: 班级计划 { 静态int-idx public static void Main() { idx = 0; Stopwatch sw = new Stopwatch(); sw.Start();
public static void Main()
{
idx = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 10; i++)
{
// here I execute my function with PLINQ
FuncP();
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
idx = 0;
sw.Start();
List<Task> tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
int iLocal = i;
Task tsk;
if (i > 0)
{
// next task depends on previous one
tsk = Task.Run(() =>
{
Task.WaitAll(tasks[iLocal - 1]);
// execute the same function
FuncP();
});
}
else // i = 0
{
// first task does not depend on other tasks
tsk = Task.Run(() =>
{
// execute the same function
FuncP();
});
}
tasks.Add(tsk);
}
tasks.Last().Wait();
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
}
private static void FuncP()
{
Stopwatch sw1 = new Stopwatch();
sw1.Start();
Console.WriteLine(string.Format("FuncP start {0}", ++idx));
string s = new string('c', 2000);
s.AsParallel()
.ForAll(_ =>
{
for (int i = 0; i < 1000000; i++) ;
});
sw1.Stop();
Console.WriteLine(string.Format("FuncP end {0}, Elapsed {1}", idx, sw1.ElapsedMilliseconds));
}
有时它挂起在任务中的第一次运行PLINQ上,有时挂起在第二次运行PLINQ上,但对于任务,它需要比在循环中花费更多的时间。
我不太清楚FuncP执行时间如此之高的确切原因,可能是因为线程池中缺少空闲线程,所以AsParallel不能使其并行吗?
有人能解释一下吗?提前谢谢。这个问题很可能是因为线程池在文章中合理地搜索了有多少空闲线程的线程注入。Matt Warren的文章值得一读 如果将线程池设置为具有最小线程数,例如使用:
ThreadPool.SetMinThreads(100, 100);
然后这两个代码示例的行为大致相同,因为“备用”线程可用
请注意,我不建议在生产中使用100,这只是一个显示对比的示例。整个方法似乎有问题,例如使用Task.WaitAlltasks[iLocal-1];不是线程安全的,因为不同的线程可能同时添加到任务中。可能值得考虑作为替代。或者,如果您不想了解这一点,请将read file add添加到BlockingCollection中,该集合处理在不同线程/任务中读取的文本。请参阅。@mjwills当然,我了解所有这些,只是粗略编写的代码示例,我主要对时间安排的原因感兴趣,谢谢
ThreadPool.SetMinThreads(100, 100);