リストを並行して評価するmap
の代替品はありますか?怠惰である必要はありません。
次のようなもの:pmap :: (a -> b) -> [a] -> [b]
let me pmap expensive_function big_list
そして私のすべてのコアを100%にします。
はい、 並列パッケージ を参照してください:
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
トムが説明したように明示的な戦略を自分で使用することに加えて、 並列 パッケージ parMap
もエクスポートします:
parMap :: Strategy b -> (a -> b) -> [a] -> [b]
ここで、戦略引数はrdeepseq
のようなものです。
また、par-monadパッケージにはparMap
もあります(純粋なHaskellから出て、並列モナドに入る):
parMap :: NFData b => (a -> b) -> [a] -> Par [b]
Par-monadパッケージは ここに記載されています です。