正確な中間結果で評価したい haskell 関数があります。
f 0 x = 0
f n x = let tmp = f (n-1) x in
tmp + (x-tmp^2)/2
(^2) のため、複雑さは n で指数関数的に増加します。プロットを実行したいのですが、2 つの異なる x の計算は完全に独立しているため、並列評価からほぼ最適なスピードアップが期待できます。これのための私のコード:
import Data.Ratio
import Control.Parallel.Strategies
f 0 x = 0
f n x = let tmp = f (n-1) x in
tmp + (x-tmp^2)/2
main = do
it <- readLn
let fn = fromRational . f it
values = map fn [0,1%2..10] :: [Double]
computed = values `using` parBuffer 16 rseq
mapM_ (putStrLn . show) computed
しかし、驚いたことに、これは実際にはスケーリングしません (HT を使用したデュアルコア i3 では):
$ ghc -threaded -O f.hs
[1 of 1] Compiling Main ( f.hs, f.o )
Linking f ...
$ time echo 20 | (./f +RTS -N1 > /dev/null)
real 0m4.760s
user 0m4.736s
sys 0m0.016s
$ time echo 20 | (./f +RTS -N2 > /dev/null)
real 0m4.041s
user 0m5.416s
sys 0m2.548s
$ time echo 20 | (./f +RTS -N3 > /dev/null)
real 0m4.884s
user 0m10.936s
sys 0m3.464s
$ time echo 20 | (./f +RTS -N4 > /dev/null)
real 0m5.536s
user 0m17.028s
sys 0m3.888s
ここで何が間違っていますか?有用な作業を行う代わりに、かなりの時間をロック (sys?) に費やしているようです。