7

正確な中間結果で評価したい 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?) に費やしているようです。

4

1 に答える 1

6

全体的なランタイムが比較的小さいため、ガベージ コレクション中のヒープの初期サイズ変更に多くの苦労をしていると思います。を渡すことで、初期割り当て領域を大きくしてみることができます+RTS -A100M

于 2013-06-11T09:35:13.003 に答える