并行化树递归过程

时间:2009-05-27 10:17:43

标签: 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_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 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

这比几个订单的第一次执行慢。你能告诉我如何更有效地并行化它。

2 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:2)

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

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

但我不保证你会比原版快得多。