F# 并行化树递归过程

F# 并行化树递归过程,f#,parallel-processing,F#,Parallel Processing,我用以下方式在F#中编写了来自sicp的变更计数问题 let count_change amount = let first_denomination kinds_of_coins = match kinds_of_coins with |1->1 |2->5 |3->10 |4->25 |5->50 let rec cc amount kinds

我用以下方式在F#中编写了来自sicp的变更计数问题

let count_change amount = 

    let first_denomination kinds_of_coins = 
        match kinds_of_coins with
        |1->1
        |2->5
        |3->10
        |4->25
        |5->50

    let rec cc amount kinds_of_coins = 
        match (amount,kinds_of_coins) with
        |(0,_) -> 1
        |(i,j) when i<0 || j=0 -> 0
        |(_,_) -> 
            [cc amount (kinds_of_coins-1) + 
             cc (amount - (first_denomination kinds_of_coins)) kinds_of_coins] 
              |> List.fold (+) 0

    cc amount 5
let count\u change amount=
让第一种面额的硬币种类=
将硬币的种类与
|1->1
|2->5
|3->10
|4->25
|5->50
让rec cc金额种类硬币=
将(数量、硬币种类)与
|(0,_) -> 1
|(i,j)当i 0
|(_,_) -> 
[抄送金额(硬币种类-1)+
cc(金额-(第一种面额硬币种类))硬币种类]
|>List.fold(+)0
抄送金额5
我想并行化长时间运行的任务,这就是我所做的

let rec cc amount kinds_of_coins = 
    match (amount,kinds_of_coins) with
    |(0,_) -> 1
    |(i,j) when i<0 || j=0 -> 0
    |(_,_) -> 
      [async {return cc amount (kinds_of_coins-1)
       + cc (amount - (first_denomination kinds_of_coins)) kinds_of_coins}] 
       |> Async.Parallel |> Async.RunSynchronously |> Array.fold (+) 0
让rec抄送硬币的数量种类=
将(数量、硬币种类)与
|(0,_) -> 1
|(i,j)当i 0
|(_,_) -> 
[async{返回cc金额(硬币种类-1)
+cc(金额-(第一种面额硬币的种类))硬币的种类}]
|>Async.Parallel |>Async.RunSynchronously |>Array.fold(+)0

这比第一次实现要慢几个数量级。您能告诉我如何更有效地并行化它吗。

我可能错了,但我认为您需要进行广度优先遍历,而不是深度优先遍历,以便并行化显示任何好处。

我可能错了,但我认为,为了实现并行化,您需要进行广度优先而不是深度优先的遍历,以显示任何好处。

这根本不是并行的。您只需以并行方式启动单个任务,这比直接执行任务更糟糕。 另外,请注意,您的函数不是尾部递归的,因此它可能并不总是安全的。 无论如何,我能想到的引入并行性的最快方法是:

let rec cc (amount,kinds_of_coins) = 
    match (amount,kinds_of_coins) with
    |(0,_) -> 1
    |(i,j) when i<0 || j=0 -> 0
    |(_,_) -> 
        [| (amount,(kinds_of_coins-1)); 
           ((amount - (first_denomination kinds_of_coins)), kinds_of_coins)
        |] |> Array.Parallel.map(cc) |> Array.fold (+) 0
let rec cc(硬币的数量、种类)=
将(数量、硬币种类)与
|(0,_) -> 1
|(i,j)当i 0
|(_,_) -> 
[|(金额,(硬币种类-1));
((金额-(第一种面额硬币的种类)),硬币的种类)
|]|>Array.Parallel.map(cc)|>Array.fold(+)0

但我不能保证这会比原来的快很多。

这根本不是平行的。您只需以并行方式启动单个任务,这比直接执行任务更糟糕。 另外,请注意,您的函数不是尾部递归的,因此它可能并不总是安全的。 无论如何,我能想到的引入并行性的最快方法是:

let rec cc (amount,kinds_of_coins) = 
    match (amount,kinds_of_coins) with
    |(0,_) -> 1
    |(i,j) when i<0 || j=0 -> 0
    |(_,_) -> 
        [| (amount,(kinds_of_coins-1)); 
           ((amount - (first_denomination kinds_of_coins)), kinds_of_coins)
        |] |> Array.Parallel.map(cc) |> Array.fold (+) 0
let rec cc(硬币的数量、种类)=
将(数量、硬币种类)与
|(0,_) -> 1
|(i,j)当i 0
|(_,_) -> 
[|(金额,(硬币种类-1));
((金额-(第一种面额硬币的种类)),硬币的种类)
|]|>Array.Parallel.map(cc)|>Array.fold(+)0

但我不能向您保证这将比原来的快得多。

实际上,深度优先遍历在并行性方面将提供更大的效率优势。实际上,深度优先遍历在并行性方面将提供更大的效率优势。