async {}工作流程易于使用,并在IO等异步操作上提供了良好的结果。对于纯粹的数据绑定操作,这是一个很好的选择吗? .NET ThreadPool和BackgroundWorker也是数据绑定计算的更好选择吗?
我的例子是一个大型列表,大约10,000个字符串都是唯一的。对于每个项目,我需要比较字符串以及列表中后面的所有字符串。返回类型将是list<string * list<string>>
,其中包含每个原始项以及可能的解决方案列表(可能的字符串匹配,基于某些特定于应用程序的算法)。
我最初的想法是使用ansyc {}工作流程,但我不确定这个问题是否更适合其他并行技术,或者即使它应该被平行化。
答案 0 :(得分:3)
有几个选项,但第一个问题是您是否要使用基于任务或数据并行的解决方案。我最近写了一篇few articles about parallel programming in F#,所以你可能会发现这个系列中的一些文章很有用。
数据并行即可。如果你有一个纯粹的CPU绑定操作 data-parallel ,那么最好的选项是
PSeq
模块。您可以在我的文章Using PLINQ and Tasks from F#中找到介绍。Array.Parallel.map
功能。 基于任务的CPU绑定。如果数据并行不能很好地解决您的问题,那么您可以使用.NET 4.0 Tasks或F#异步工作流和StartAsChild
成员。任务不支持取消,并且在F#中看起来有点难看,但它们可能更加优化(如果你想创建非常多的它们)。另一方面,F#异步工作流在F#中看起来更优雅。我写了两篇比较选项的文章。 first one解释了基本功能和the second one关于取消的说明。
还有使用F#代理的消息传递,如果您需要复杂的协调(并且使用大量同步原语和可变状态编写),这可能会很好地工作> p>
答案 1 :(得分:1)
您的问题是CPU密集型的,因为您的所有数据都在内存中,主CPU成本是您自定义的字符串匹配算法。
您可以使用Parallel.For,这比CPU绑定并行任务的Async快一点。
答案 2 :(得分:0)
async {}工作流程易于使用,并在IO等异步操作上提供了良好的结果。对纯粹的数据绑定操作来说,这是一个不错的选择吗?
没有。异步用于并发IO,这与并行CPU绑定计算的问题完全不同。
.NET ThreadPool和BackgroundWorker也是数据绑定计算的更好选择吗?
略好一点,但它们仍然没有为此而建。
list<(string * list)
这不是有效的类型。
我最初的想法是使用ansyc {}工作流程
糟糕的主意。
但我不确定这个问题是否更适合其他并行技术,或者它是否应该被平行化。
首先编写正确的串行版本,如果速度太慢,请对其进行优化并将其并行化。例如,当您仍在使用链接列表时,您不太可能从并行性中看到显着的收益。
您描述的算法可以在F#中实现如下:
let rec f p a = function
| [] -> List.rev a
| x::xs -> f p ((x, List.filter (p x) xs)::a) xs
其中p
是任意谓词函数,您的算法是通用的。例如,以下内容查找所有后续字符串等于每个头字符串:
> f (=) [] ["a"; "b"; "c"; "a"; "c"];;
val it : (string * string list) list =
[("a", ["a"]); ("b", []); ("c", ["c"]); ("a", []); ("c", [])]
在我的上网本上运行10,000个字符串需要不到6秒。这够快吗?
答案 3 :(得分:0)
Async适用于并行CPU绑定操作和异步IO操作,适用于两者。 Don Syme对此有一个blog post。操作仍将在线程池上运行,因此您不会通过使用异步来放弃它。