6

Eval私はmonadとrpar StrategyHaskellで問題に遭遇しました。次のコードを検討してください。

module Main where

import Control.Parallel.Strategies

main :: IO ()
main = print . sum . inParallel2 $ [1..10000]

inParallel :: [Double] -> [Double]
inParallel xss = runEval . go $ xss
    where
      go []  = return []
      go (x:xs) = do
        x'  <- rpar $ x + 1
        xs' <- go xs
        return (x':xs')

inParallel2 :: [Double] -> [Double]
inParallel2 xss = runEval . go $ xss
    where
      go []  = return []
      go [x] = return $ [x + 1]
      go (x:y:xs) = do
        (x',y') <- rpar $ (x + 1, y + 1)
        xs'     <- go xs
        return (x':y':xs'

私はそれを次のようにコンパイルして実行します:

ghc -O2 -Wall -threaded -rtsopts -fforce-recomp -eventlog eval.hs
./eval +RTS -N3 -ls -s

関数を使用inParallelすると、並列処理は期待どおりに機能します。出力ランタイム統計では、次のように表示されます。

SPARKS: 100000 (100000 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

関数に切り替えると、inParallel2すべての並列処理がなくなります。

SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

タプルの評価が並行して機能しないのはなぜですか?タプルをrparに渡す前に、タプルを強制してみました。

rpar $!! (x + 1, y + 1)

しかし、それでも結果はありません。私は何が間違っているのですか?

4

1 に答える 1

11

このrpar戦略は、可能な評価の用語に並行して注釈を付けますが、これは、基本的に最も外側のコンストラクターまでを意味する、弱いヘッドの通常の形式までです。したがって、整数または倍精度浮動小数点数の場合、これは完全な評価を意味しますが、ペアの場合、そのコンポーネントではなく、ペアコンストラクターのみが評価されます。

ペアを渡す前に強制することrparは役に立ちません。これで、並列評価の可能性について、すでに評価されたタプルに注釈を付ける前に、ペアをローカルで評価しています。

おそらく、rparrdeepseq戦略を組み合わせて、可能であれば並行して用語を完全に評価する必要があることを示します。あなたは言うことによってこれを行うことができます

(rpar `dot` rdeepseq) (x + 1, y + 1)

dotオペレーターは戦略を作成するためのものです。

ただし、コードにはさらに別の問題があります。パターンマッチングでは即時評価が強制されるため、rpar通常、注釈付き式にパターンマッチングを使用することはお勧めできません。特に、ライン

(x',y') <- (rpar `dot` rdeepseq) (x + 1, y + 1)

別のスレッドによる評価のためにスパークを取得する前に、ローカルスレッドはパターンに一致させるためにスパークの評価をすでに開始しているため、すべての並列処理が無効になります。怠惰な/反駁できないパターンを使用することでこれを防ぐことができます:

~(x',y') <- (rpar `dot` rdeepseq) (x + 1, y + 1)

または、とを使用fstsndてペアのコンポーネントにアクセスします。

最後に、整数に1を追加するのと同じくらい安価なスパークを作成する場合は、実際のスピードアップを期待しないでください。スパーク自体は比較的安価ですが、コストがかからないわけではないため、並列評価用に注釈を付ける計算にいくらかコストがかかる場合は、スパークの方がうまく機能します。

戦略の使用に関するチュートリアルを読むことをお勧めします。たとえば、Simon Marlowの Haskellを使用した並列および並行プログラミングや、Haskellでの私自身の決定論的並列プログラミングなどです。

于 2012-11-12T09:46:00.783 に答える