【问题标题】:.NET and Task Parallel Library.NET 和任务并行库
【发布时间】:2013-01-29 21:00:42
【问题描述】:

我有一个 for 循环,它创建 4 个任务,每个任务打印其循环索引 - 用于测试性能的简单程序

我有一个外部循环运行上述循环 1000 次(迭代) 我想检查 TASKs 和 Threads 的性能

(1) 测试 1:我认为这只会创建 TASK(不是线程),但我发现它使用 TPL

tasks[i] = Task.Factory.StartNew(() => Console.WriteLine(tmp));

(2)我用TaskCreationOptions.LongRunning重写如下

tasks[i] = Task.Factory.StartNew(() => Console.WriteLine(tmp), TaskCreationOptions.LongRunning);

(3) 然后我尝试使用与上面相同的代码而不是任务测试线程,但现在使用“新线程”而不是工厂

for (int i = 0; i < 4; i++)
{
    var tmp = i;
    tasks[i] = new Thread(new ThreadStart(() => Console.WriteLine(tmp)));
    tasks[i].Start();
    tasks[i].Join();
}

时序结果显示最好的性能是(2),然后是(3),然后是(1)

请解释一下性能结果的原因,并解释一下上面哪一个真正只是一个任务(一个OS进程),哪些正在使用线程?

我尝试使用探查器,但只能访问 Visual Studio 2010 Professional,而且探查器似乎只附带 permium 或 Ultimate 版本。

【问题讨论】:

  • 三个问题,你有没有尝试过更多的循环?你在发布时运行它吗?你是如何衡量所有的?
  • “以上哪一项真正只是一项任务(操作系统进程)”Tasks 和 Processes 是完全不同的东西。如果你想运行一些代码,你必须使用一些线程。
  • 选项 3 具有创建线程的所有开销,但没有任何好处。迭代将在新创建的线程上按顺序运行。

标签: .net task-parallel-library


【解决方案1】:
Task.Factory.StartNew(

使用线程池中的线程

LongRunning 表示,每个任务都应该创建自己的线程,因为它运行时间很长,我们不想干涸池

最后一个选项只是创建线程。

您是否检查了每个案例的内存使用情况?

【讨论】:

    【解决方案2】:

    在这种情况下使用Console.WriteLine 作为测试性能的操作是没有意义的。在所有情况下,每次迭代都会从池中生成或重用一个新线程。这是一个相对昂贵的事情。这意味着,只要您的操作是微不足道的,线程生成的开销或重用成本总是会大大影响您的性能测试。

    如果您在线程中进行真正的、非平凡的操作,那么您的案例之间的生成成本差异将不再重要。除此之外,在使用Task 时,您几乎无法控制何时创建新线程或重用池中的一个线程,顺便说一句,这总是一件好事。我的建议是,当您需要在后台处理某些内容并将令人头疼的内容留给框架时,请使用 Tasks

    我希望这是可以理解的。

    而且,出于实际目的,如果您有大量要计算的内容并想使用多核 cpu,您还可以查看Parallel.ForeachTPL 提供的其他内容。

    编辑:Parallel.Foreach 和喜欢的人将自行决定是否以及何时产生新线程。使用此方法将为您提供最大的灵活性,因为运行时将根据处理器数量、列表的大小等为您决定创建新线程是否有意义,或者开销是否会更大。

    【讨论】:

    • 感谢您的回复。已经知道这几点了。还有 Parallel.Foreach,也知道它。表演的重点是关于一些没有发布的东西,太多的细节我不得不发布。这段代码需要测试。只需要知道为什么一个简单的几行代码就表明 TPL 比其他人做得更差。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    相关资源
    最近更新 更多