我建立了一个示例程序来并行检查任务的性能,与并行运行的任务数量有关。
几个假设: 线程上的操作独立于另一个线程,因此线程之间没有必要的同步机制。
我们的想法是检查它是否有效: 1.尽可能多地完成任务 要么 2.并行限制任务数,并在生成剩余任务之前等待某些任务完成。
以下是该计划:
static void Main(string[] args)
{
System.IO.StreamWriter writer = new System.IO.StreamWriter("C:\\TimeLogV2.csv");
SemaphoreSlim availableSlots;
for (int slots = 10; slots <= 20000; slots += 10)
{
availableSlots = new SemaphoreSlim(slots, slots);
int maxTasks;
CountdownEvent countDownEvent;
Stopwatch watch = new Stopwatch();
watch.Start();
maxTasks = 20000;
countDownEvent = new CountdownEvent(maxTasks);
for (int i = 0; i < maxTasks; i++)
{
Console.WriteLine(i);
Task task = new Task(() => Thread.Sleep(50));
task.ContinueWith((t) =>
{
availableSlots.Release();
countDownEvent.Signal();
}
);
availableSlots.Wait();
task.Start();
}
countDownEvent.Wait();
watch.Stop();
writer.WriteLine("{0},{1}", slots, watch.ElapsedMilliseconds);
Console.WriteLine("{0}:{1}", slots, watch.ElapsedMilliseconds);
}
writer.Flush();
writer.Close();
}
以下是结果:
Y轴是以毫秒为单位的时间,X轴是信号量槽的数量(参见上面的程序)
基本上趋势是:更多的并行任务越多越好。现在我的问题是在什么条件下,确实:
更多并行任务=不太理想(花费时间)?
我认为有一个条件是: 任务是相互依赖的,可能必须等待某些资源可用。
您是否在任何情况下都限制了并行任务的数量?
答案 0 :(得分:2)
TPL将控制一次运行多少个线程 - 基本上你只是排队要在这些线程上运行的任务。你并非真正并行运行所有这些任务。
TPL将使用工作窃取队列使其尽可能高效。如果您拥有所有关于您需要运行的任务的信息,那么您最好将它们排成队列,而不是尝试自己进行微观管理。当然,这将占用内存 - 如果你有大量的任务,那么可能成为一个问题。
但是,为了获得更多任务,我不会试图人为地将你的逻辑任务分解为一点点。作为一般规则,您不应该将“更多任务==更好”视为一种规则。(顺便说一句,我注意到您在测量中花了很多时间将批次行写入控制台。我会删除这些Console.WriteLine
来电并尝试再次 - 他们可能会产生很大的不同。)