[英]Why shouldn't I use F# asynchronous workflows for parallelism?
我最近一直在学习F#,特别感兴趣的是它易于利用数据并行性。 data |> Array.map |> Async.Parallel |> Async.RunSynchronously
惯用法似乎非常容易理解,并且易于使用并从中获得真正的价值。
那么为什么async
并不是真正意图呢? Donald Syme本人表示,PLINQ和期货可能是更好的选择。 我在这里读到的其他答案同意这一点以及推荐TPL。 (只要您使用F# PSeq
来获取PSeq
功能,PLINQ似乎与上述内置函数没有太大区别。)
F#和函数式语言对此非常有意义,并且一些应用程序在async
并行性方面取得了巨大成功。
那么为什么我不应该使用async
来执行并行数据流程呢? 通过编写并行async
代码而不是使用PLINQ或TPL,我将失去什么?
那么为什么我不应该使用异步来执行并行数据流程呢?
如果您有少量完全独立的非async
任务和大量内核,那么使用async实现并行性没有任何问题。 但是,如果您的任务以任何方式依赖,或者您拥有的任务多于核心,或者您将async
的使用推到了代码中,那么您将在桌面上留下很多性能并且可以通过选择更适合并行编程的基础。
请注意,使用F#中的TPL可以更优雅地编写示例:
Array.Parallel.map f xs
通过编写并行异步代码而不是使用PLINQ或TPL,我将失去什么?
您将失去编写缓存遗忘代码的能力,因此会遭受大量缓存未命中,因此,所有内核停止等待共享内存,这意味着多核上的可扩展性较差。
TPL建立在这样的思想之上:子任务应该以高概率在与父级相同的核心上执行,因此,重用相同的数据将会受益,因为它在本地CPU缓存中会很热。 异步没有这样的保证。
我写了一篇文章,使用Task
和Async
重新实现了一个C#TPL示例,它也对两者之间的差异有一些评论。 你可以在这里找到它 ,还有一个更高级的基于异步的版本 。
以下是第一篇文章的引用,它比较了两个选项:
两种可能的实现之间的选择取决于许多因素。 异步工作流是专为F#设计的,因此它们更适合语言。 它们为I / O绑定任务提供了更好的性能,并提供了更方便的异常处理。 而且,顺序语法非常方便。 另一方面,任务针对CPU绑定计算进行了优化,并且可以更轻松地从应用程序的其他位置访问计算结果,而无需显式缓存。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.