web-dev-qa-db-ja.com

haskellの並列マップ

リストを並行して評価するmapの代替品はありますか?怠惰である必要はありません。

次のようなもの:pmap :: (a -> b) -> [a] -> [b] let me pmap expensive_function big_listそして私のすべてのコアを100%にします。

34
Clark Gaebel

はい、 並列パッケージ を参照してください:

ls `using` parList rdeepseq

rdeepseq戦略を介して、リストの各要素を並行して評価します。 parListChunkを適切なチャンク値とともに使用すると、要素が安すぎて各要素を並行して評価するメリットが得られない場合に、パフォーマンスが向上する可能性があることに注意してください(各要素のスパークを節約できるため)。

編集:あなたの質問に基づいて、私は説明する必要があると思いますなぜこれは答えです。 Haskellが怠け者だからです!ステートメントを検討してください

let bs = map expensiveFunction as

何も評価されていません。 expensiveFunctionをマップするサンクを作成しました。では、どのように並行して評価するのでしょうか。

let bs = map expensiveFunction as
    cs = bs `using` parList rdeepseq

今後の計算ではbsリストを使用せず、代わりにcsリストを使用してください。 IOW、並列マップは必要ありません。通常の(遅延)マップと並列評価戦略を使用できます。

編集:そして、十分に見回すと、ここで示したものを実行するが、1つのヘルパー関数にラップされた parMap 関数が表示されます。

あなたのコメントに応えて、以下のコードはあなたのために機能しませんか?わたしにはできる。

import Control.Parallel.Strategies

func as =
        let bs = map (+1) as
            cs = bs `using` parList rdeepseq
        in cs
40

トムが説明したように明示的な戦略を自分で使用することに加えて、 並列 パッケージ parMap もエクスポートします:

 parMap :: Strategy b -> (a -> b) -> [a] -> [b]

ここで、戦略引数はrdeepseqのようなものです。

また、par-monadパッケージにはparMapもあります(純粋なHaskellから出て、並列モナドに入る):

 parMap :: NFData b => (a -> b) -> [a] -> Par [b]

Par-monadパッケージは ここに記載されています です。

18
Don Stewart