使用任务并行库的更好方法是啥
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<T>
:
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 限制的Task
s,这与这里的情况相去甚远。
因此,我认为最好的选择是将并行度手动限制为一个小数字(您必须测量以找出哪个数字给出了最佳结果):
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 实现并行任务的最佳方法是啥?