【问题标题】:Haskell: sequential Fibonacci faster than parallelHaskell:顺序斐波那契比并行更快
【发布时间】:2017-02-16 03:28:56
【问题描述】:

所以,我正在 Haskell 中试验并行性。我举了一个经典的例子,以顺序和并行的方式实现斐波那契数列方法。这是我的 Main.hs 文件:

module Main where
import Control.Parallel
main = print (fib 47)
fib :: Int -> Int
fib n
| n <=1 = n
| otherwise = fib (n-1) + fib (n-2)

我用ghc -O2 --make Main.hs -threaded -rtsopts 编译 并使用time ./Main +RTS -N4 执行,这给了我:

2971215073
63.23user 13.03system 0:20.30elapsed 375%CPU (0avgtext+0avgdata 3824maxresident)k
0inputs+0outputs (0major+276minor)pagefaults 0swaps

所以使用正常的斐波那契大约需要 20 秒。

现在如果我将我的 fib 方法更改为

pfib :: Int -> Int
pfib n
    | n <= 1 = n
    | otherwise = n1 `par` (n2 `par` n1 + n2)
        where
            n1 = pfib (n - 1)
            n2 = pfib (n - 2)

如上编译和运行,time 需要更长的时间并以输出结束:

2971215073
179.50user 9.04system 0:53.08elapsed 355%CPU (0avgtext+0avgdata 6980maxresident)k
0inputs+0outputs (0major+1066minor)pagefaults 0swaps

进一步修改我的 pfib 以使用 pseq 而不是第二个 partime 给出:

2971215073
113.34user 3.42system 0:30.91elapsed 377%CPU (0avgtext+0avgdata 7312maxresident)k
0inputs+0outputs (0major+1119minor)pagefaults 0swaps

我的代码有问题吗?为什么我在各种实现之间会有这种不合逻辑的时间差?

【问题讨论】:

    标签: haskell parallel-processing fibonacci


    【解决方案1】:

    来自par 的文档:

    此外,确保 a 不是简单的计算也是一个好主意,否则并行生成它的成本会掩盖并行运行它所获得的好处。

    一个加法和几个减法是一个微不足道的计算。如果您只并行运行几个深度级别,您会看到好处:

    module Main where
    import Control.Parallel
    
    main = print (pfib 16 47)
    
    fib :: Int -> Int
    fib n
        | n <= 1 = n
        | otherwise = fib (n-1) + fib (n-2)
    
    pfib :: Int -> Int -> Int
    pfib 1 n = fib n
    pfib p n
        | n <= 1 = n
        | otherwise = n1 `par` (n2 `par` n1 + n2)
            where
                n1 = pfib (p - 1) (n - 1)
                n2 = pfib (p - 1) (n - 2)
    

    【讨论】:

    • 确实,我看到使用您的代码有了很大的改进,但是当我使用 mymapmyparmap 函数时:mymap :: (a -&gt; b) -&gt; [a] -&gt; [b] mymap f [] = [] mymap f (x:xs) = f x : mymap f xs myparmap :: (a -&gt; b) -&gt; [a] -&gt; [b] myparmap f [] = [] myparmap f (x:xs) = n2 par` (n1 par n2 : n1) where n1 = myparmap f xs n2 = f x` 并行版本的代码确实更快。这是否意味着在这种情况下,与pfib 相比,在myparmap 中使用并行版本更有意义?
    • @jrsall92:如果您的任务足够繁重,可以跨列表元素并行运行它是有益的(显然您的测试就是这种情况)并且您希望使用更多内核来加速它起来,然后是的。
    猜你喜欢
    • 1970-01-01
    • 2017-12-06
    • 2015-01-06
    • 2018-11-09
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 2011-02-17
    相关资源
    最近更新 更多