【发布时间】:2010-05-07 16:46:58
【问题描述】:
是否可以为 Array.Parallel 模块设置“MaxDegreeOfParallelism”(即要使用的最大线程数),因为在 it usesParallel.For 的底层?
【问题讨论】:
标签: f# arrays parallel-processing
是否可以为 Array.Parallel 模块设置“MaxDegreeOfParallelism”(即要使用的最大线程数),因为在 it usesParallel.For 的底层?
【问题讨论】:
标签: f# arrays parallel-processing
根据this post的说法,Parallel Extensions的最终版本似乎没有办法全局限制线程数。 brian 建议的替代方法是使用 PLINQ(适用于并行序列)而不是适用于数组的函数。
这可以使用来自F# PowerPack 的PSeq 模块来完成。它提供了诸如PSeq.map、PSeq.filter 和许多其他与并行序列 一起工作的函数(也可以使用流水线很好地组合)。对于并行序列,您可以使用WithDegreeOfParallelism extension method 来指定行为。
你可以为它实现一个包装函数:
[编辑:它已经存在了!]
let withDegreeOfParallelism n (pq:ParallelQuery<_>) =
pq.WithDegreeOfParallelsm(n)
然后写:
let res =
data |> PSeq.map (fun n -> ...)
|> PSeq.withDegreeOfParallelism ParallelOptions.MaxDegreeOfParallelism
|> Array.ofSeq
这可能具有不同的性能,因为它的实现方式与 Array.Parallel 模块中的函数不同,但这当然取决于您的场景。
【讨论】:
PSeq 模块(如PSeq.withDegreeOfParallelism)的一部分。对我来说,ParallelQuery<T> 的唯一问题是延迟执行。
|> 对多个操作进行排序,框架可以一次运行它们(通过一些智能优化),而Array.Parallel 单独运行每个操作(因此它可能会创建更多的任务- 这可能是问题,也可能不是问题......)。
不,我不这么认为。
您始终可以使用array.fs(在CTP release 中)的源代码作为起点,为Array.Parallel 模块中的任何方法创建自己的版本。
【讨论】:
假设我想说我最多替换了 10 个线程:
myArray
|> Array.Parallel.iter (fun item -> doWork item)
与
let maxPara = 10
myArray
|> Array.splitInto maxPara
|> Array.Parallel.iter (fun items -> items |> List.iter (fun item -> doWork item))
【讨论】: