TPL数据流的最大并行度

4

我正在使用TPL Dataflow构建一条流水线。假设我有一个由四个TransformBlocks组成的流水线。

GetDataFromDatabase
ProcessData1
ProcessData2
SendDataToRestService

每个操作可能会是长时间运行的操作。GetDataFromDatabase 可能大部分时间都在等待数据库响应,SendDataToRestService 则是等待服务响应。ProcessData1 和 ProcessData2 将是长时间本地 CPU 密集型处理。

现在,我的意图是在每个块上设置 maxdegreeofparalellism 为机器上的核心数(可能是 4)。

但我想到这意味着它将同时执行 4 个 GetDataFromDatabases,4 个 ProcessData1,4 个 ProcessData2 和 4 个 SendDataToRestService。这意味着我可能会有 16 个线程同时运行。加上我实际上有 3 个不同的流同时做类似的事情。

问题:什么是最好的方法,以获得最佳性能?根据我所读的,如果我尝试做太多,由于上下文切换,实际上可能会减慢性能。是否有最佳方法,或者只能“试一试”?


在我看来,后面的三个步骤可以在一个“ActionBlock”中完成。不需要使用管道。 - usr
其实我并不明白为什么你需要多个 ActionBlock。只需将所有工作项发布到其中,并使用异步工作者委托即可。您可以以这种方式设置并行度。 - usr
你说的也许没错,但是请原谅我如果我漏掉了什么,不过这不是可以用于任何流水线吗?如果是这样,那它们的意义在哪里呢? - bornfromanegg
1
我对TPL数据流有点陌生,但将块链接在一起的价值似乎在于组合具有不同行为的不同类型的块。如果您只需要一个单步管道,那就这样吧。 - usr
2个回答

4
首先,正如@usr所建议的那样,您的情况适用于单个ActionBlock。链接多个块的重点是组合具有不同配置的不同类型的块。例如,如果您有一步骤的MaxDegreeOfParallelism为1,另一个为10。
其次,MaxDegreeOfParallelism设置最大值,这意味着TPL可以根据资源的可用性在该范围内选择任何数字。因此,我不会担心为所有这些块设置最大值,如果TPL决定使用较少的线程,则会使用较少的线程。
来自如何:指定数据流块中的并行度 由于MaxDegreeOfParallelism属性表示最大并行度,因此数据流块可能会以比您指定的更低的并行度执行。数据流块可以使用较低的并行度来满足其功能要求或考虑到缺乏可用系统资源。数据流块从不选择比您指定的更高的并行度。

嗨。我已经考虑减少块的数量,但不确定是否有好的理由。我喜欢它的“工作单位”方面。然而,我认为在这种情况下,这可能不是最好的选择,所以我会简化它。话虽如此,我为了提问的目的已经简化了我的场景——也许我简化得太多了:-)。 我当然需要一些块处理一个块,这就是它们目前正在做的事情。感谢您的帮助。 - bornfromanegg
@user1158174 当然,随时欢迎。 - i3arnon

0
我认为合理的做法是将这两个CPU密集型块合并成一个。这样,您可以分别调整具有不同特性的块。
如果这不可能(例如,如果CPU密集型块不相邻),则最有可能仍然可以将每个CPU密集型块的MaxDegreeOfParallelism设置为ProcessorCount。线程池很聪明,除非它认为有利,否则不会使用太多线程。虽然我认为在其他块(或程序的其他部分)中使用阻塞IO代码可能会使其混淆,因此建议使用异步IO。
无论如何,使用略多于必要的线程很可能不是一个大问题。如果您确实需要修复此问题,可以使用限制线程数量的自定义TaskScheduler,并将其设置为CPU密集型块的DataflowBlockOptions.TaskScheduler

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接