Safe Haskell | None |
---|---|
Language | Haskell98 |
Control.Monad.Par
Description
The monad-par
package provides a family of Par
monads, for
speeding up pure computations using parallel processors. (for a similar
programming model for use with IO
, see Control.Monad.Par.IO.)
The result of a given Par
computation is always the same - i.e. it
is deterministic, but the computation may be performed more quickly
if there are processors available to share the work.
For example, the following program fragment computes the values of
(f x)
and (g x)
in parallel, and returns a pair of their results:
runPar $ do fx <- spawnP (f x) -- start evaluating (f x) gx <- spawnP (g x) -- start evaluating (g x) a <- get fx -- wait for fx b <- get gx -- wait for gx return (a,b) -- return results
Par
can be used for specifying pure parallel computations in
which the order of the computation is not known beforehand.
The programmer specifies how information flows from one
part of the computation to another, but not the order in which
computations will be evaluated at runtime. Information flow is
described using "variables" called IVar
s, which support put
and
get
operations. For example, suppose you have a problem that
can be expressed as a network with four nodes, where b
and c
require the value of a
, and d
requires the value of b
and c
:
a / \ b c \ / d
Then you could express this in the Par
monad like this:
runPar $ do [a,b,c,d] <- sequence [new,new,new,new] fork $ do x <- get a; put b (x+1) fork $ do x <- get a; put c (x+2) fork $ do x <- get b; y <- get c; put d (x+y) fork $ do put a (3 :: Int) get d
The result of the above computation is always 9. The get
operation
waits until its input is available; multiple put
s to the same
IVar
are not allowed, and result in a runtime error. Values
stored in IVar
s are usually fully evaluated (although there are
ways provided to pass lazy values if necessary).
In the above example, b
and c
will be evaluated in parallel.
In practice the work involved at each node is too small here to see
the benefits of parallelism though: typically each node should
involve much more work. The granularity is completely under your
control - too small and the overhead of the Par
monad will
outweigh any parallelism benefits, whereas if the nodes are too
large then there might not be enough parallelism to use all the
available processors.
Unlike Control.Parallel
, in Control.Monad.Par
parallelism is
not combined with laziness, so sharing and granularity are
completely under the control of the programmer. New units of
parallel work are only created by fork
and a few other
combinators.
The default implementation is based on a work-stealing scheduler that divides the work as evenly as possible between the available processors at runtime. Other schedulers are available that are based on different policies and have different performance characteristics. To use one of these other schedulers, just import its module instead of Control.Monad.Par:
For more information on the programming model, please see these sources:
- The wiki/tutorial (http://www.haskell.org/haskellwiki/Par_Monad:_A_Parallelism_Tutorial)
- The original paper (http://www.cs.indiana.edu/~rrnewton/papers/haskell2011_monad-par.pdf)
- Tutorial slides (http://community.haskell.org/~simonmar/slides/CUFP.pdf)
- Other slides: (http://www.cs.ox.ac.uk/ralf.hinze/WG2.8/28/slides/simon.pdf, http://www.cs.indiana.edu/~rrnewton/talks/2011_HaskellSymposium_ParMonad.pdf)
Synopsis
- data Par a
- runPar :: Par a -> a
- runParIO :: Par a -> IO a
- fork :: Par () -> Par ()
- data IVar a
- new :: Par (IVar a)
- newFull :: NFData a => a -> Par (IVar a)
- newFull_ :: a -> Par (IVar a)
- get :: IVar a -> Par a
- put :: NFData a => IVar a -> a -> Par ()
- put_ :: IVar a -> a -> Par ()
- spawn :: NFData a => Par a -> Par (IVar a)
- spawn_ :: Par a -> Par (IVar a)
- spawnP :: NFData a => a -> Par (IVar a)
- class NFData a
The Par Monad
Run a parallel, deterministic computation and return its result.
Note: you must NOT return an IVar in the output of the parallel
computation. This is unfortunately not enforced, as it is with
runST
or with newer libraries that export a Par monad, such as
lvish
.
runParIO :: Par a -> IO a Source #
A version that avoids an internal unsafePerformIO
for calling
contexts that are already in the IO
monad.
Returning any value containing IVar is still disallowed, as it can compromise type safety.
Forks a computation to happen in parallel. The forked
computation may exchange values with other computations using
IVar
s.
Communication: IVars
get :: IVar a -> Par a Source #
Read the value in an IVar
. The get
operation can only return when the
value has been written by a prior or parallel put
to the same
IVar
.
put :: NFData a => IVar a -> a -> Par () Source #
Put a value into an IVar
. Multiple put
s to the same IVar
are not allowed, and result in a runtime error.
put
fully evaluates its argument, which therefore must be an
instance of NFData
. The idea is that this forces the work to
happen when we expect it, rather than being passed to the consumer
of the IVar
and performed later, which often results in less
parallelism than expected.
Sometimes partial strictness is more appropriate: see put_
.
Operations
Like fork
, but returns an IVar
that can be used to query the
result of the forked computataion. Therefore spawn
provides futures or promises.
spawn p = do r <- new fork (p >>= put r) return r
Like spawn
, but the result is only head-strict, not fully-strict.
Spawn a pure (rather than monadic) computation. Fully-strict.
spawnP = spawn . return
This module also reexports the Combinator library for backwards compatibility with version 0.1.
Instances
NFData Bool | |
Defined in Control.DeepSeq Methods rnf :: Bool -> () | |
NFData Char | |
Defined in Control.DeepSeq Methods rnf :: Char -> () | |
NFData Double | |
Defined in Control.DeepSeq Methods rnf :: Double -> () | |
NFData Float | |
Defined in Control.DeepSeq Methods rnf :: Float -> () | |
NFData Int | |
Defined in Control.DeepSeq Methods rnf :: Int -> () | |
NFData Int8 | |
Defined in Control.DeepSeq Methods rnf :: Int8 -> () | |
NFData Int16 | |
Defined in Control.DeepSeq Methods rnf :: Int16 -> () | |
NFData Int32 | |
Defined in Control.DeepSeq Methods rnf :: Int32 -> () | |
NFData Int64 | |
Defined in Control.DeepSeq Methods rnf :: Int64 -> () | |
NFData Integer | |
Defined in Control.DeepSeq Methods rnf :: Integer -> () | |
NFData Natural | |
Defined in Control.DeepSeq Methods rnf :: Natural -> () | |
NFData Ordering | |
Defined in Control.DeepSeq Methods rnf :: Ordering -> () | |
NFData Word | |
Defined in Control.DeepSeq Methods rnf :: Word -> () | |
NFData Word8 | |
Defined in Control.DeepSeq Methods rnf :: Word8 -> () | |
NFData Word16 | |
Defined in Control.DeepSeq Methods rnf :: Word16 -> () | |
NFData Word32 | |
Defined in Control.DeepSeq Methods rnf :: Word32 -> () | |
NFData Word64 | |
Defined in Control.DeepSeq Methods rnf :: Word64 -> () | |
NFData CallStack | |
Defined in Control.DeepSeq Methods rnf :: CallStack -> () | |
NFData () | |
Defined in Control.DeepSeq Methods rnf :: () -> () | |
NFData TyCon | |
Defined in Control.DeepSeq Methods rnf :: TyCon -> () | |
NFData ThreadId | |
Defined in Control.DeepSeq Methods rnf :: ThreadId -> () | |
NFData MaskingState | |
Defined in Control.DeepSeq Methods rnf :: MaskingState -> () | |
NFData CInt | |
Defined in Control.DeepSeq Methods rnf :: CInt -> () | |
NFData Any | |
Defined in Control.DeepSeq Methods rnf :: Any -> () | |
NFData SrcLoc | |
Defined in Control.DeepSeq Methods rnf :: SrcLoc -> () | |
NFData Version | |
Defined in Control.DeepSeq Methods rnf :: Version -> () | |
NFData All | |
Defined in Control.DeepSeq Methods rnf :: All -> () | |
NFData ExitCode | |
Defined in Control.DeepSeq Methods rnf :: ExitCode -> () | |
NFData Fingerprint | |
Defined in Control.DeepSeq Methods rnf :: Fingerprint -> () | |
NFData CBool | |
Defined in Control.DeepSeq Methods rnf :: CBool -> () | |
NFData CChar | |
Defined in Control.DeepSeq Methods rnf :: CChar -> () | |
NFData CClock | |
Defined in Control.DeepSeq Methods rnf :: CClock -> () | |
NFData CDouble | |
Defined in Control.DeepSeq Methods rnf :: CDouble -> () | |
NFData CFile | |
Defined in Control.DeepSeq Methods rnf :: CFile -> () | |
NFData CFloat | |
Defined in Control.DeepSeq Methods rnf :: CFloat -> () | |
NFData CFpos | |
Defined in Control.DeepSeq Methods rnf :: CFpos -> () | |
NFData CIntMax | |
Defined in Control.DeepSeq Methods rnf :: CIntMax -> () | |
NFData CIntPtr | |
Defined in Control.DeepSeq Methods rnf :: CIntPtr -> () | |
NFData CJmpBuf | |
Defined in Control.DeepSeq Methods rnf :: CJmpBuf -> () | |
NFData CLLong | |
Defined in Control.DeepSeq Methods rnf :: CLLong -> () | |
NFData CLong | |
Defined in Control.DeepSeq Methods rnf :: CLong -> () | |
NFData CPtrdiff | |
Defined in Control.DeepSeq Methods rnf :: CPtrdiff -> () | |
NFData CSChar | |
Defined in Control.DeepSeq Methods rnf :: CSChar -> () | |
NFData CSUSeconds | |
Defined in Control.DeepSeq Methods rnf :: CSUSeconds -> () | |
NFData CShort | |
Defined in Control.DeepSeq Methods rnf :: CShort -> () | |
NFData CSigAtomic | |
Defined in Control.DeepSeq Methods rnf :: CSigAtomic -> () | |
NFData CSize | |
Defined in Control.DeepSeq Methods rnf :: CSize -> () | |
NFData CTime | |
Defined in Control.DeepSeq Methods rnf :: CTime -> () | |
NFData CUChar | |
Defined in Control.DeepSeq Methods rnf :: CUChar -> () | |
NFData CUInt | |
Defined in Control.DeepSeq Methods rnf :: CUInt -> () | |
NFData CUIntMax | |
Defined in Control.DeepSeq Methods rnf :: CUIntMax -> () | |
NFData CUIntPtr | |
Defined in Control.DeepSeq Methods rnf :: CUIntPtr -> () | |
NFData CULLong | |
Defined in Control.DeepSeq Methods rnf :: CULLong -> () | |
NFData CULong | |
Defined in Control.DeepSeq Methods rnf :: CULong -> () | |
NFData CUSeconds | |
Defined in Control.DeepSeq Methods rnf :: CUSeconds -> () | |
NFData CUShort | |
Defined in Control.DeepSeq Methods rnf :: CUShort -> () | |
NFData CWchar | |
Defined in Control.DeepSeq Methods rnf :: CWchar -> () | |
NFData TypeRep | |
Defined in Control.DeepSeq Methods rnf :: TypeRep -> () | |
NFData Unique | |
Defined in Control.DeepSeq Methods rnf :: Unique -> () | |
NFData Void | |
Defined in Control.DeepSeq Methods rnf :: Void -> () | |
NFData a => NFData [a] | |
Defined in Control.DeepSeq Methods rnf :: [a] -> () | |
NFData a => NFData (Maybe a) | |
Defined in Control.DeepSeq Methods rnf :: Maybe a -> () | |
NFData a => NFData (Ratio a) | |
Defined in Control.DeepSeq Methods rnf :: Ratio a -> () | |
NFData (Ptr a) | |
Defined in Control.DeepSeq Methods rnf :: Ptr a -> () | |
NFData (FunPtr a) | |
Defined in Control.DeepSeq Methods rnf :: FunPtr a -> () | |
NFData a => NFData (ZipList a) | |
Defined in Control.DeepSeq Methods rnf :: ZipList a -> () | |
NFData (Vector a) | |
Defined in Data.Vector.Unboxed.Base Methods rnf :: Vector a -> () | |
NFData (IORef a) | |
Defined in Control.DeepSeq Methods rnf :: IORef a -> () | |
NFData (Vector a) | |
Defined in Data.Vector.Primitive Methods rnf :: Vector a -> () | |
NFData (MVar a) | |
Defined in Control.DeepSeq Methods rnf :: MVar a -> () | |
NFData a => NFData (Set a) | |
Defined in Data.Set.Internal Methods rnf :: Set a -> () | |
NFData a => NFData (Down a) | |
Defined in Control.DeepSeq Methods rnf :: Down a -> () | |
NFData a => NFData (Dual a) | |
Defined in Control.DeepSeq Methods rnf :: Dual a -> () | |
NFData a => NFData (First a) | |
Defined in Control.DeepSeq Methods rnf :: First a -> () | |
NFData a => NFData (Last a) | |
Defined in Control.DeepSeq Methods rnf :: Last a -> () | |
NFData a => NFData (NonEmpty a) | |
Defined in Control.DeepSeq Methods rnf :: NonEmpty a -> () | |
NFData a => NFData (Product a) | |
Defined in Control.DeepSeq Methods rnf :: Product a -> () | |
NFData a => NFData (Sum a) | |
Defined in Control.DeepSeq Methods rnf :: Sum a -> () | |
NFData a => NFData (Identity a) | |
Defined in Control.DeepSeq Methods rnf :: Identity a -> () | |
NFData a => NFData (Complex a) | |
Defined in Control.DeepSeq Methods rnf :: Complex a -> () | |
NFData a => NFData (First a) | |
Defined in Control.DeepSeq Methods rnf :: First a -> () | |
NFData a => NFData (Last a) | |
Defined in Control.DeepSeq Methods rnf :: Last a -> () | |
NFData a => NFData (Max a) | |
Defined in Control.DeepSeq Methods rnf :: Max a -> () | |
NFData a => NFData (Min a) | |
Defined in Control.DeepSeq Methods rnf :: Min a -> () | |
NFData m => NFData (WrappedMonoid m) | |
Defined in Control.DeepSeq Methods rnf :: WrappedMonoid m -> () | |
NFData (StableName a) | |
Defined in Control.DeepSeq Methods rnf :: StableName a -> () | |
NFData (Fixed a) | |
Defined in Control.DeepSeq Methods rnf :: Fixed a -> () | |
NFData a => NFData (Option a) | |
Defined in Control.DeepSeq Methods rnf :: Option a -> () | |
NFData a => NFData (Seq a) | |
Defined in Data.Sequence.Internal Methods rnf :: Seq a -> () | |
NFData a => NFData (Elem a) | |
Defined in Data.Sequence.Internal Methods rnf :: Elem a -> () | |
NFData a => NFData (Digit a) | |
Defined in Data.Sequence.Internal Methods rnf :: Digit a -> () | |
NFData a => NFData (FingerTree a) | |
Defined in Data.Sequence.Internal Methods rnf :: FingerTree a -> () | |
NFData a => NFData (Node a) | |
Defined in Data.Sequence.Internal Methods rnf :: Node a -> () | |
NFData (IVar a) Source # | |
Defined in Control.Monad.Par.Scheds.Direct | |
NFData (IVar a) Source # | |
Defined in Control.Monad.Par.Scheds.TraceInternal | |
NFData (a -> b) | |
Defined in Control.DeepSeq Methods rnf :: (a -> b) -> () | |
(NFData a, NFData b) => NFData (Either a b) | |
Defined in Control.DeepSeq Methods rnf :: Either a b -> () | |
(NFData a, NFData b) => NFData (a, b) | |
Defined in Control.DeepSeq Methods rnf :: (a, b) -> () | |
NFData (MVector s a) | |
Defined in Data.Vector.Unboxed.Base Methods rnf :: MVector s a -> () | |
NFData (MVector s a) | |
Defined in Data.Vector.Primitive.Mutable Methods rnf :: MVector s a -> () | |
(NFData a, NFData b) => NFData (Array a b) | |
Defined in Control.DeepSeq Methods rnf :: Array a b -> () | |
(NFData a, NFData b) => NFData (Arg a b) | |
Defined in Control.DeepSeq Methods rnf :: Arg a b -> () | |
NFData (STRef s a) | |
Defined in Control.DeepSeq Methods rnf :: STRef s a -> () | |
NFData (Proxy a) | |
Defined in Control.DeepSeq Methods rnf :: Proxy a -> () | |
(NFData a1, NFData a2, NFData a3) => NFData (a1, a2, a3) | |
Defined in Control.DeepSeq Methods rnf :: (a1, a2, a3) -> () | |
NFData a => NFData (Const a b) | |
Defined in Control.DeepSeq Methods rnf :: Const a b -> () | |
NFData (a :~: b) | |
Defined in Control.DeepSeq Methods rnf :: (a :~: b) -> () | |
(NFData a1, NFData a2, NFData a3, NFData a4) => NFData (a1, a2, a3, a4) | |
Defined in Control.DeepSeq Methods rnf :: (a1, a2, a3, a4) -> () | |
NFData (a :~~: b) | |
Defined in Control.DeepSeq Methods rnf :: (a :~~: b) -> () | |
(NFData1 f, NFData1 g, NFData a) => NFData (Product f g a) | |
Defined in Control.DeepSeq Methods rnf :: Product f g a -> () | |
(NFData1 f, NFData1 g, NFData a) => NFData (Sum f g a) | |
Defined in Control.DeepSeq Methods rnf :: Sum f g a -> () | |
(NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) => NFData (a1, a2, a3, a4, a5) | |
Defined in Control.DeepSeq Methods rnf :: (a1, a2, a3, a4, a5) -> () | |
(NFData1 f, NFData1 g, NFData a) => NFData (Compose f g a) | |
Defined in Control.DeepSeq Methods rnf :: Compose f g a -> () | |
(NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) => NFData (a1, a2, a3, a4, a5, a6) | |
Defined in Control.DeepSeq Methods rnf :: (a1, a2, a3, a4, a5, a6) -> () | |
(NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) => NFData (a1, a2, a3, a4, a5, a6, a7) | |
Defined in Control.DeepSeq Methods rnf :: (a1, a2, a3, a4, a5, a6, a7) -> () | |
(NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) => NFData (a1, a2, a3, a4, a5, a6, a7, a8) | |
Defined in Control.DeepSeq Methods rnf :: (a1, a2, a3, a4, a5, a6, a7, a8) -> () | |
(NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8, NFData a9) => NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) | |
Defined in Control.DeepSeq Methods rnf :: (a1, a2, a3, a4, a5, a6, a7, a8, a9) -> () |
(0.3) Reexport NFData
for fully-strict operators.