【发布时间】:2018-03-16 11:22:39
【问题描述】:
我正在研究一些文本解析器逻辑,并进行 IO 和 CPU 绑定操作。
一般来说,我做什么:读取文件 -> 处理文本,读取文件 2 -> 处理文本 2... 等等。
我可以做的是让操作“处理文本”和“读取文件 2”在不同的任务中同时执行。然而,当我创建相关任务树时,我注意到 PLINQ 变得比最初慢。这是代码的简化示例:
类程序 { 静态 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() 由于线程池中缺少“空闲”线程而无法并行?
有人可以解释吗?提前致谢。
【问题讨论】:
-
整个方法似乎有问题(例如,
Task.WaitAll(tasks[iLocal - 1]);的使用不是线程安全的,因为可能同时向tasks添加不同的线程)。 docs.microsoft.com/en-us/dotnet/standard/parallel-programming/… 可能值得考虑作为替代方案。或者,如果您不想了解这一点,请将read file添加到BlockingCollection,process text从不同的线程/任务中读取。见stackoverflow.com/questions/6608042/…。 -
@mjwills 当然,我明白这一切,只是粗略的代码示例,主要对时间原因感兴趣,谢谢