如何在f#中一次执行两个函数?

时间:2018-12-04 02:25:47

标签: parallel-processing f#

我试图通过使两个任务并行执行来使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

但是我得到有关类型的语法错误。我在这里想念什么?

2 个答案:

答案 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更适合在较大的数组上进行并行处理。