C# 充分利用.NET任务并行库

C# 充分利用.NET任务并行库,c#,.net,performance,task-parallel-library,C#,.net,Performance,Task Parallel Library,问题1. 使用Parallel.For和Parallel.ForEach是否更适合处理有序或无序的任务 我问这个问题的原因是,我最近更新了一个串行循环,其中使用StringBuilder根据各种参数生成SQL语句。结果是,与使用标准foreach循环时相比,SQL有点混乱(甚至包含语法错误),因此我的直觉是,TPL不适合执行数据必须以特定顺序出现的任务 问题2. TPL是否在执行之前自动使用多核体系结构 我提出这个问题的原因与我之前提出的一个与第三方物流运营的性能分析有关的问题有关。对这个问题的

问题1.

使用Parallel.For和Parallel.ForEach是否更适合处理有序或无序的任务

我问这个问题的原因是,我最近更新了一个串行循环,其中使用StringBuilder根据各种参数生成SQL语句。结果是,与使用标准foreach循环时相比,SQL有点混乱(甚至包含语法错误),因此我的直觉是,TPL不适合执行数据必须以特定顺序出现的任务

问题2.

TPL是否在执行之前自动使用多核体系结构


我提出这个问题的原因与我之前提出的一个与第三方物流运营的性能分析有关的问题有关。对这个问题的回答让我明白了一个事实,即TPL并不总是比标准串行循环更高效,因为应用程序可能无法访问多个内核,因此与标准串行循环相比,创建额外线程和循环的开销会导致性能下降。

关于第1点,如果使用TPL,您不知道运行任务的顺序。这就是并行与顺序之美。有办法控制事物的顺序,但是你可能会失去平行的好处

第二,第三方物流利用多核开箱即用。但是在使用多个线程时确实会有开销。调度程序上的负载增加,线程(上下文)切换不是免费的。为了保持数据同步以避免竞争条件,您可能需要一些锁定机制,这也会增加开销

使用TPL制作快速并行算法变得容易多了,但仍然是一门艺术。

我的直觉是,TPL不适合执行数据必须以特定顺序出现的任务

对。如果您希望事情按顺序进行,那么您可能会对将循环“并行化”时会发生什么产生误解

TPL是否在执行之前自动使用多核体系结构

请参阅msdn杂志上的以下文章:

使用该库,您可以方便地表示潜在的并行性 在现有的顺序代码中,公开的并行任务将 在所有可用处理器上并发运行

  • 如果必须对结果进行排序,那么为了并行化循环,您需要能够以任何顺序执行实际工作,然后对结果进行排序。根据具体情况,这可能比一开始就连续地工作效率更高,也可能不会更高。如果并行化可以按任何顺序完成的工作的好处大于排序结果的成本,那么这就是净收益。如果该任务不够复杂,您的硬件不允许大量并行化,或者如果并行化不好(即,由于数据依赖性,您有大量等待),则排序结果可能需要比并行化循环所获得的时间更长的时间(或者更糟糕的是,即使没有排序,并行化循环也需要更长的时间,请参见问题2),因此您不应该并行化它

    请注意,如果实际的工作单元需要以特定的顺序运行,而不仅仅是需要以特定的顺序运行结果,那么您将无法并行化它,或者您将无法几乎同样有效地并行化它。如果您没有正确地同步对共享资源的访问,那么您实际上将得到错误的r为此,你需要记住,如果你不能得到正确的结果,那么性能优化是没有意义的

  • 你真的不需要为你的TPL硬件担心太多。你不需要显式地添加或限制任务。虽然有几种方法可以,但几乎任何时候你做这样的事情都会影响性能。当你做这样的事情时,你是在给TPL添加限制,这样它就不能做它想做的事情。通常是这样的我比你更清楚

    这里还涉及到另一点,即并行化循环通常需要更长的时间(您只是没有给出导致这种行为的可能原因)。通常需要完成的实际工作非常小,以至于创建线程、管理线程、根据需要处理上下文转移和同步数据的工作可能比并行工作所获得的工作要多。这就是为什么在决定并行一些线程时,实际做大量测试非常重要的原因努力确保它确实从中受益

  • 对于无序的列表来说,这并不是更好或更糟的——您在#1中的问题是您对
    StringBuilder
    有一个共享依赖关系,这就是并行查询失败的原因。TPL在独立的工作单元上运行得非常好。即使如此,您也可以使用一些简单的技巧强制计算并行查询并保留原始查询当并行操作全部完成时,对结果进行排序

  • TPL和PLINQ在技术上是不同的东西;PLINQ使用TPL来实现它的目标。也就是说,PLINQ尝试检查您的体系结构,并尽可能地构造集合的执行。TPL只是任务体系结构的包装器。创建任务的开销是否由您决定(这相当于1MB内存),执行任务的上下文切换的开销比简单地串行运行任务要大


  • 显然,TPL不是构建有序集(如查询)的好工具

    如果要对一组项目执行一系列任务,则可以使用BlockingCollection。这些任务可以并行执行,但顺序不同