我正在研究一些文本解析器逻辑,并具有IO和CPU绑定操作。
一般来说我做的是:读取文件 - >处理文本,读取文件2 - >处理文本2 ...等等。
我能做的是让操作“进程文本”和“读取文件2”在不同的任务中同时执行。然而,当我创建相关任务树时,我注意到PLINQ变得比最初慢。以下是代码的简化示例:
课程计划 { static int idx;
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));
}
}
输出是:
FuncP start 1
FuncP end 1, Elapsed 409
FuncP start 2
FuncP end 2, Elapsed 345
FuncP start 3
FuncP end 3, Elapsed 344
FuncP start 4
FuncP end 4, Elapsed 337
FuncP start 5
FuncP end 5, Elapsed 344
FuncP start 6
FuncP end 6, Elapsed 343
FuncP start 7
FuncP end 7, Elapsed 348
FuncP start 8
FuncP end 8, Elapsed 351
FuncP start 9
FuncP end 9, Elapsed 343
FuncP start 10
FuncP end 10, Elapsed 334
3504
FuncP start 1
FuncP end 1, Elapsed 5522 --> here is high execution time
FuncP start 2
FuncP end 2, Elapsed 368
FuncP start 3
FuncP end 3, Elapsed 340
FuncP start 4
FuncP end 4, Elapsed 347
FuncP start 5
FuncP end 5, Elapsed 351
FuncP start 6
FuncP end 6, Elapsed 347
FuncP start 7
FuncP end 7, Elapsed 353
FuncP start 8
FuncP end 8, Elapsed 337
FuncP start 9
FuncP end 9, Elapsed 341
FuncP start 10
FuncP end 10, Elapsed 345
12160
有时它会在第一次运行PLINQ时挂起,有时会在第二次运行时挂起,但是对于任务,循环中需要花费更多时间。
我不确定我是否完全理解FuncP
执行时间如此之高的原因,是不是AsParallel()
由于线程池中缺少“空闲”线程而无法使其成为parellel?
谁能解释一下?提前谢谢。
答案 0 :(得分:0)
这个问题很可能是因为线程池合理conservative (搜索文章中的Thread Injection
)它所包含的备用线程数。 Matt Warren的article值得一读。
如果您将ThreadPool设置为最小个线程数,例如使用:
ThreadPool.SetMinThreads(100, 100);
然后两个代码示例的行为大致相同,因为'备用'线程可用。
请注意,我不会建议在制作中使用100 - 这只是展示对比度的一个例子。