为什么我不应该使用F#异步工作流来实现并行化?

时间:2011-03-16 15:28:32

标签: asynchronous f# parallel-processing task-parallel-library

我最近一直在学习F#,特别感兴趣的是它易于利用数据并行性。 data |> Array.map |> Async.Parallel |> Async.RunSynchronously成语似乎很容易理解,并且直接使用并从中获得真正的价值。

那么为什么async并非真正意图呢? Donald Syme himself说PLINQ和期货可能是更好的选择。我在这里读到的其他答案同意这一点以及推荐TPL。 (PLINQ与上述内置函数似乎没有太大区别,只要您使用F#Powerpack来获取PSeq函数。)

F#和函数式语言对此非常有意义,some applicationsasync并行性方面取得了巨大成功。

那么为什么不应该我使用async执行并行数据流程?通过编写并行async代码而不是使用PLINQ或TPL,我将失去什么?

3 个答案:

答案 0 :(得分:15)

  

那么为什么我不应该使用异步来执行并行数据流程呢?

如果您拥有少量完全独立的非async任务和大量内核,那么使用async实现并行性没有任何问题。但是,如果您的任务以任何方式依赖,或者您拥有的任务多于核心,或者您将async的使用推到了代码中太远,那么您将在桌面上留下很多性能并且可以做很多事情更好的选择更合适的并行编程基础。

请注意,使用F#中的TPL可以更优雅地编写您的示例:

Array.Parallel.map f xs
  

通过编写并行异步代码而不是使用PLINQ或TPL,我将失去什么?

你失去了编写缓存不经意代码的能力,因此会遭受大量缓存未命中,因此,所有内核停止等待共享内存,这意味着多核上的可扩展性很差。

TPL建立在以下思想的基础上:子任务应该以高概率在与父级相同的核心上执行,因此,重用相同的数据将会受益,因为它在本地CPU缓存中会很热。 async没有这样的保证。

答案 1 :(得分:12)

我写了一篇文章,使用TaskAsync重新实现了一个C#TPL示例,它也对两者之间的差异有一些评论。您可以find it here并且还有advanced async-based version

以下是第一篇文章的引用,它比较了两个选项:

  

两种可能的实现之间的选择取决于许多因素。异步工作流是专为F#设计的,因此它们更适合语言。它们为I / O绑定任务提供了更好的性能,并提供了更方便的异常处理。而且,顺序语法非常方便。另一方面,任务针对CPU绑定计算进行了优化,并且可以更轻松地从应用程序的其他位置访问计算结果,而无需显式缓存。

答案 2 :(得分:0)

我总是认为这是TPL,PLinq等...给你超越Async的作用。 (取消机制是我想到的。)This question有更好的答案。

这篇文章提到了slight performance advantage到TPL,但可能还不够重要。