F#:Asynch和Tasks以及PLINQ,哦,我的!

时间:2010-02-01 17:15:01

标签: multithreading f#

当F#出现时,我将会对异步/并行编程领域的财富感到尴尬。 answer to this question可以很好地描述Tasks,Parallel LINQ和Reactive Framework之间的差异,但我想知道异步工作流如何适应图片。

如果我错了,请纠正我,但据我所知,asynch工作流将是使用IO绑定操作的最简单方法,特别是那些定义了AsynchXxx方法的操作,或遵循BeginXxx / EndXxx模式。另一个优点是,asynch工作流程是可组合的,并且可以构建在其他异步工作流程之外 - 这可以为程序的构建方式提供很大的灵活性。

我想我需要帮助的是理解在什么情况下我会在F#代码中选择任务或PLINQ而不是异步工作流。我相信我读到任务并行库有更复杂的方法来平衡核心之间的负载。如果这是真的,那么对于需要并行操作的纯CPU绑定操作,Tasks可能是更好的选择。另一方面,PLINQ似乎主要是一种方便的方法来并行化与序列一起使用的现有代码。

最后,假设我对每种方法的优势的理解是正确的,将它们组合起来是否可行或可取?例如,也许可以从异步工作流中组合一系列操作,然后在执行之前将它们转换为Tasks。如果这是可能的 - 甚至是个好主意。

2 个答案:

答案 0 :(得分:12)

请参阅Task Parallel Library vs Async Workflows

我总结了以下基础知识:

任务并行库:允许多个工作单元在多个核心上高效运行,包括相对简单的场景,例如产生多个线程以并行执行类似的计算以及更复杂的计算操作他们自己也最终产生了额外的任务。使用改进的.NET 4.0线程池并工作窃取队列以确保所有核心保持忙碌。

异步工作流程:允许异步计算在不占用不需要的线程的情况下运行,在结果可用时启动回调。

PLINQ :使用PLINQ编写的代码最终通过TPL运行,但这是一个更好的代码接口,可以使用LINQ查询轻松表达(例如对数组中的每个项目执行单个操作数据并行)。

请注意,可以使用StartAsTask方法将异步工作流转换为任务,并且可以使用Async方法将任务转换为Async.AwaitTask,因此可以桥接技术,虽然他们确实针对的是略有不同的目标场景。

对我来说,经验法则是如果你在不同的线程上积极进行大量计算,你将需要使用TPL(可能通过PLINQ或F#等价物,如PSeq模块),而如果你想要做很多IO(无论是否并行),你应该使用asynch工作流程。 因此,光线跟踪器将使用TPL启动任务以并行渲染每个像素(或扫描线),从而最大限度地提高计算机上的可用计算能力。 但是下载一堆网页将使用异步工作流完成,因为在核心之间传播的计算量不大;你只需要在结果出来时通知操作系统。

答案 1 :(得分:1)

异步工作流程通过F#monadic语法实现。这意味着您可以编写自己的基于并行任务库的“异步”版本,而不是将工作流转换为任务。我这样说了几个警告:

  • 这很难做到。
  • 在.NET中使用BeginXxx / EndXxx模式的异步操作注册了线程池中的回调。我不确定你是否可以改变它,改为重定向他们使用任务。

有关如何在F#中实现monad的更多详细信息,请参阅“专家F#”一书或google“F#monads”。

我知道这不是一个完整的答案,但希望它有所帮助。