我试图通过使两个任务并行执行来使F#中的快速排序程序并行工作。我尝试查看Microsoft的在线文档,但这并没有真正帮助我!这是我的没有并行性的代码:
let rec quicksort (list: int list) =
match list with
| [] -> [] // if empty list, yield nothing
// otherwise, split the list into a head and tial, and the head is the pivot value
| pivot :: tail ->
// Using List.partition to partition the list into lower and upper
let lower, upper = List.partition (fun x -> x < pivot) tail
// Recursive calls, final product will be low list + pivot + high list
quicksort lower @ [pivot] @ quicksort upper
我尝试实现类似
Async.Parallel [quicksort lower; @ [pivot] @ quicksort upper;] |> Async.RunSynchronously
但是我得到有关类型的语法错误。我在这里想念什么?
答案 0 :(得分:2)
应该使用Array.Parallel.map
而不是Async.Parallel
来并行化诸如排序之类的计算绑定代码,这是为了提高IO绑定代码的吞吐量。
您可以使用Array.Parallel.map
来并行化函数。
let rec quicksort (list: int list) =
match list with
| [] -> [] /
| pivot :: tail ->
let lower, upper = List.partition (fun x -> x < pivot) tail
let sortedArrays = Array.Parallel.map quicksort [| lower; upper |]
sortedArrays.[0] @ [pivot] @ sortedArrays.[1]
但是,您不应该这样做,因为并行化的开销比并行化的好处要高得多,而并行化的版本实际上要慢得多。
如果要加快快速排序算法的速度,可以避免在算法期间分配对象(列表),从而获得最大的收益。使用数组并将其更改为适当的方式是:)
答案 1 :(得分:2)
正如@hvester所提到的那样,以这种方式将并行化添加到quicksort不会对您有太大帮助。实现速度很慢,因为它使用列表和分配,而不是因为实际的CPU限制。
那就是说,如果这仅仅是说明以不同方式并行化F#代码,那么使用Array.Parallel.map
的一个不错的选择就是使用任务:
open System.Threading.Tasks
let rec quicksort (list: int list) =
match list with
| [] -> []
| pivot :: tail ->
let lower, upper = List.partition (fun x -> x < pivot) tail
let lowerRes = Task.Factory.StartNew(fun _ -> quicksort lower)
let upperRes = quicksort upper
lowerRes.Result @ [pivot] @ upperRes
通过任务,您可以使用StartNew
在后台开始工作,然后通过访问Result
属性等待结果。我认为这在这种情况下会更合适。 Array.Parallel.map
更适合在较大的数组上进行并行处理。