Applies the given function to each element of a data structure
in parallel (fully evaluating the results), and returns a new data
structure containing the results.
parMap f xs = mapM (spawnP . f) xs >>= mapM get
parMap is commonly used for lists, where it has this specialised type:
Computes a binary map/reduce over a finite range. The range is
recursively split into two, the result for each half is computed in
parallel, and then the two results are combined. When the range
reaches the threshold size, the remaining elements of the range are
computed sequentially.
For example, the following is a parallel implementation of
Parallel for-loop over an inclusive range. Semantically equivalent
to
parFor (InclusiveRange n m) f = forM_ [n..m] f
except that the implementation will split the work into an
unspecified number of subtasks in an attempt to gain parallelism.
The exact number of subtasks is chosen at runtime, and is probably
a small multiple of the available number of processors.
Strictly speaking the semantics of parFor depends on the
number of processors, and its behaviour is therefore not
deterministic. However, a good rule of thumb is to not have any
interdependencies between the elements; if this rule is followed
then parFor has deterministic semantics. One easy way to follow
this rule is to only use put or put_ in f, never get.