我正在尝试学习如何使用Control.Parallel
模块,但我认为我没有理解正确。
我正在尝试运行以下代码(fibs.hs).
import Control.Parallel
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = p `par` (q `pseq` (p + q))
where
p = fib (n-1)
q = fib (n-2)
main = print $ fib 30
我用以下方法编译了这个:
ghc -O2 --make -threaded fibs.hs
然后执行该程序得到以下结果(Python 脚本的输出,该脚本运行每个程序 100 次并返回执行时间的平均值和标准差):
./fibs +RTS -N1 -> avg= 0.060203 s, deviation = 0.004112 s
./fibs +RTS -N2 -> avg= 0.052335 s, deviation = 0.006713 s
./fibs +RTS -N3 -> avg= 0.052935 s, deviation = 0.006183 s
./fibs +RTS -N4 -> avg= 0.053976 s, deviation = 0.007106 s
./fibs +RTS -N5 -> avg= 0.055227 s, deviation = 0.008598 s
./fibs +RTS -N6 -> avg= 0.055703 s, deviation = 0.006537 s
./fibs +RTS -N7 -> avg= 0.058327 s, deviation = 0.007526 s
我的问题是:
-
当我评估时到底发生了什么:
a `par` (b `pseq` (a + b)) ?
我明白,一个par
b 应该提示编译器与 b 并行计算 a 并返回 b。好的。但有什么作用pseq
do?
为什么我看到的性能提升如此之小?
我在英特尔上运行这个Core 2 http://en.wikipedia.org/wiki/Intel_Core_2四机.我预计使用 -N5 或 -N6 运行不会对性能产生真正的影响,或者程序实际上会开始表现得非常糟糕。但为什么我没有看到从 -N2 到 -N3 的任何改进,并且为什么最初的改进如此之小?
As Don 解释了 https://stackoverflow.com/questions/1798996/multicore-programming-in-haskell-control-parallel/1799134#1799134,问题是你制造了太多的火花。以下是您可以如何重写它以获得良好的加速效果。
import Control.Parallel
cutoff :: Int
cutoff = 20
parFib :: Int -> Int
parFib n | n < cutoff = fib n
parFib n = p `par` q `pseq` (p + q)
where
p = parFib $ n - 1
q = parFib $ n - 2
fib :: Int -> Int
fib 0 = 0
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
main :: IO ()
main = print $ parFib 40
示范:
[computer ~]$ ghc --make -threaded -O2 Main.hs
[1 of 1] Compiling Main ( Main.hs, Main.o )
Linking Main ...
[computer ~]$ time ./Main +RTS -N1
102334155
real 0m1.509s
user 0m1.450s
sys 0m0.003s
[computer ~]$ time ./Main +RTS -N2
102334155
real 0m0.776s
user 0m1.487s
sys 0m0.023s
[computer ~]$ time ./Main +RTS -N3
102334155
real 0m0.564s
user 0m1.487s
sys 0m0.030s
[computer ~]$ time ./Main +RTS -N4
102334155
real 0m0.510s
user 0m1.587s
sys 0m0.047s
[computer ~]$
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)