Asynchronous 为什么不应该';我是否使用F#异步工作流来实现并行性?

Asynchronous 为什么不应该';我是否使用F#异步工作流来实现并行性?,asynchronous,f#,parallel-processing,task-parallel-library,Asynchronous,F#,Parallel Processing,Task Parallel Library,我最近一直在学习F#,对其利用数据并行性的易用性特别感兴趣。data |>Array.map |>Async.Parallel |>Async.RunSynchronously这个习惯用法似乎非常容易理解,使用起来也非常简单,从中获得了真正的价值 那么为什么async并不是真正用于此目的呢?说PLINQ和Futures可能是更好的选择。我在这里读到的其他答案也同意这一点,并推荐第三方物流。(PLINQ与上述内置功能似乎没有太大区别,只要您使用F#Powerpack获得PSeq功能。) F#和函数

我最近一直在学习F#,对其利用数据并行性的易用性特别感兴趣。
data |>Array.map |>Async.Parallel |>Async.RunSynchronously
这个习惯用法似乎非常容易理解,使用起来也非常简单,从中获得了真正的价值

那么为什么
async
并不是真正用于此目的呢?说PLINQ和Futures可能是更好的选择。我在这里读到的其他答案也同意这一点,并推荐第三方物流。(PLINQ与上述内置功能似乎没有太大区别,只要您使用F#Powerpack获得
PSeq
功能。)

F#和函数式语言在这方面很有意义,并且在
async
并行性方面取得了巨大成功


那么为什么我不应该使用
async
来执行并行数据处理呢?写并行
async
代码而不是使用PLINQ或TPL,我会失去什么?

我一直认为TPL、PLINQ等。。。除了Async所做的之外,它还为您提供了更多的功能。(我想到的是取消机制。)有一些更好的答案


这篇文章暗示了一个到TPL的转换,但可能还不够重要。

我写了一篇文章,使用
任务和
异步
重新实现了一个C#TPL示例,文章还对两者之间的差异进行了一些评论。你可以,还有一个更多

以下是第一篇文章中比较这两种选择的引文:

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

那么为什么我不应该使用async来执行并行数据处理呢

如果您有少量完全独立的非
async
任务和大量内核,那么使用async实现并行并没有什么错。但是,如果您的任务依赖于任何方式,或者您有比内核更多的任务,或者将代码<> asyc使用到代码中太远,那么您将在表中留下很多性能,并且通过选择更合适的并行编程基础,可以做得更好。 请注意,使用F#的TPL可以更优雅地编写您的示例,不过:

如果编写并行异步代码而不是使用PLINQ或TPL,我会损失什么

您将失去编写缓存忽略代码的能力,因此将遭受大量缓存未命中,因此,所有内核都会暂停等待共享内存,这意味着多核上的可扩展性较差


TPL基于这样一个理念,即子任务应该以很高的概率在与父任务相同的核心上执行,因此,将受益于重用相同的数据,因为它在本地CPU缓存中是热的。异步没有这样的保证。

然而,请注意,暗示TPL比异步有一些性能优势的文章已经有三年多的历史了——当时情况可能已经发生了很大的变化。异步与TPL有着相同的取消机制。首选项的总结是I/O->async,CPU->TPL/PLINQ,语法的简化->async/PLINQ。从我从包括上述文章在内的所有来源收集到的信息来看,在CPU受限的任务中使用Async.Parallel并没有什么大的缺点。尤其是TPL的排队和工作分配功能使其成为CPU限制操作的更好选择吗?
Array.Parallel.map f xs