Is there some substitute of map
which evaluates the list in parallel? I don't need it to be lazy.
Something like: pmap :: (a -> b) -> [a] -> [b]
letting me pmap expensive_function big_list
and have all my cores at 100%.
Yes, see the parallel package:
ls `using` parList rdeepseq
will evaluate each element of the list in parallel via the rdeepseq
strategy. Note the use of parListChunk
with a good chunk value might give better performance if your elements are too cheap to get a benefit evaluating each one in parallel (because it saves on sparking for each element).
EDIT: Based on your question I feel I should explain why this is an answer. It's because Haskell is lazy! Consider the statement
let bs = map expensiveFunction as
Nothing has been evaluated. You've just created a thunk that maps expensiveFunction
. So how do we evaluate it in parallel?
let bs = map expensiveFunction as
cs = bs `using` parList rdeepseq
Now don't use the bs
list in your future computations, instead use the cs
list. IOW, you don't need a parallel map, you can use the regular (lazy) maps and a parallel evaulation strategy.
EDIT: And if you look around enough you'll see the parMap function that does what I showed here but wrapped into one helper function.
In response to your comment, does the below code not work for you? it works for me.
import Control.Parallel.Strategies
func as =
let bs = map (+1) as
cs = bs `using` parList rdeepseq
in cs
Besides using explicit strategies yourself as Tom has described, the parallel package also exports parMap
:
parMap :: Strategy b -> (a -> b) -> [a] -> [b]
where the strategy argument is something like rdeepseq
.
And there's also parMap
in the par-monad package (you step out of pure Haskell, and into a parallel monad):
parMap :: NFData b => (a -> b) -> [a] -> Par [b]
The par-monad package is documented here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With