使用任务并行库的更好方法是啥

Posted

技术标签:

【中文标题】使用任务并行库的更好方法是啥【英文标题】:What would be a better way of using task parallel library使用任务并行库的更好方法是什么 【发布时间】:2012-07-08 10:14:18 【问题描述】:

我刚开始使用 TPL,我想同时调用多个 Web 服务。据我所知,我看到了两种方法。

Parallel.ForEach:

List<ServiceMemberBase> list = new List<ServiceMemberBase>(); //Take list from somewhere.
        Parallel.ForEach(list, member =>
            
                var result = Proxy.Invoke(member);
                //...
                //Do stuff with the result
                //...
            );

Task&lt;T&gt;:

List<ServiceMemberBase> list = new List<ServiceMemberBase>(); //Take list from somewhere.
        ForEach(var member in list)
        
            Task<MemberResult>.Factory.StartNew(() => proxy.Invoke(member));
        

        //Wait for all tasks to finish.
        //Process the result objects.

不管语法是否正确,这些是否等同?

它们会产生相同的结果吗?如果不是,为什么?哪个更可取?

【问题讨论】:

【参考方案1】:

对于您讨论的代码和用例,这两种方法本质上是等效的。

当您必须将输入范围划分为多个任务(此处不适用)时,Parallel.ForEach 很有用,或者更容易同步合并多个独立并行操作的结果(可能适用于此?)。

无论如何,您已经正确地注意到,在 Parallel.ForEach 案例中,您不必手动同步等待完成,而如果您手动启动任务,则必须自己管理该同步。在这种情况下,您可能会使用 Task.WaitAll(...) 之类的东西。

【讨论】:

感谢您的回复。我最终使用了 Parallel.ForEach,我们看到我们的生产(16 核机器)的响应时间提高了大约 25%。我猜大部分收益是在并行数据处理中,而不是在对 Web 服务本身的并行调用中。【参考方案2】:

在两段代码之间,Parallel.ForEach() 会更高效,因为它在一个 Task 中处理多个项目,一个接一个。

但是他们都将使用ThreadPool 允许的线程数,在这种情况下这不是一个好主意。这是因为ThreadPool 擅长猜测最佳线程数,如果你有非常短的、受 CPU 限制的Tasks,这与这里的情况相去甚远。

因此,我认为最好的选择是将并行度手动限制为一个小数字(您必须测量以找出哪个数字给出了最佳结果):

List<ServiceMemberBase> list = …; //Take list from somewhere.
Parallel.ForEach(list, new ParallelOptions  MaxDegreeOfParallelism = 10 ,
member =>

    var result = Proxy.Invoke(member);
    //...
    //Do stuff with the result
    //...
);

如果您可以异步执行 Web 服务调用,效率会更高。这样做并同时限制并行度并不是很容易,除非您使用的是 C# 5。如果您使用的是 C# 5 并且还更新了 Proxy 以支持基于任务的异步模式 (TAP) ,您可以使用 TPL 数据流更有效地执行您的代码:

var actionBlock = new ActionBlock<ServiceMemberBase>(
    async member =>
    
        var result = await Proxy.InvokeAsync(member);
        //...
        //Do stuff with the result
        //...
    
    new ExecutionDataflowBlockOptions  MaxDegreeOfParallelism = 10 );

【讨论】:

【参考方案3】:

如果不考虑或查看输出,我无法确定两者是否相同;但是我怀疑它们是否有那么大的不同。关于哪个更好的问题是主观的,具体取决于场景。回答哪个更可取也是非常主观的,在您提供的场景中,我会说我更喜欢 Parallel.ForEach 因为我可以阅读它,但是如果您的开发团队不习惯 Parallel 库那么第二个版本就可以了。

【讨论】:

以上是关于使用任务并行库的更好方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

使用 Django 和 Elastic beantalk 实现并行任务的最佳方法是啥?

在java中并行化任务的最简单方法是啥?

使用 APScheduler 在 python 中进行并行编程的最佳方法是啥?

在 API 中使用任务并行库

Storm并行中的“任务”是啥

有没有办法将任务并行库(TPL)与 SQLDataReader 一起使用?