Safe Haskell | None |
---|
Standard combinators for distributed types.
- data Gang
- gangSize :: Gang -> Int
- seqGang :: Gang -> Gang
- forkGang :: Int -> IO Gang
- theGang :: Gang
- class DT a where
- data Dist a
- data MDist a :: * -> *
- indexD :: String -> Dist a -> Int -> a
- newMD :: Gang -> ST s (MDist a s)
- readMD :: MDist a s -> Int -> ST s a
- writeMD :: MDist a s -> Int -> a -> ST s ()
- unsafeFreezeMD :: MDist a s -> ST s (Dist a)
- deepSeqD :: a -> b -> b
- sizeD :: Dist a -> Int
- sizeMD :: MDist a s -> Int
- measureD :: a -> String
- newD :: DT a => Gang -> (forall s. MDist a s -> ST s ()) -> Dist a
- debugD :: DT a => Dist a -> String
- checkGangD :: DT a => String -> Gang -> Dist a -> b -> b
- generateD :: DT a => What -> Gang -> (Int -> a) -> Dist a
- generateD_cheap :: DT a => What -> Gang -> (Int -> a) -> Dist a
- imapD' :: (DT a, DT b) => What -> Gang -> (Int -> a -> b) -> Dist a -> Dist b
- foldD :: DT a => What -> Gang -> (a -> a -> a) -> Dist a -> a
- scanD :: forall a. DT a => What -> Gang -> (a -> a -> a) -> a -> Dist a -> (Dist a, a)
The Gang
DPH programs use this single, shared gang of threads. The gang exists at top level, and is initialised at program start.
The vectoriser guarantees that the gang is only used by a single computation at a time. This is true because the program produced by the vector only uses flat parallelism, so parallel computations don't invoke further parallel computations. If the vectorised program tries to use nested parallelism then there is a bug in the vectoriser, and the code will run sequentially.
Distributed Types
Class of distributable types. Instances of DT
can be
distributed across all workers of a Gang
.
All such types must be hyperstrict as we do not want to pass thunks
into distributed computations.
indexD :: String -> Dist a -> Int -> aSource
Extract a single element of an immutable distributed value.
newMD :: Gang -> ST s (MDist a s)Source
Create an unitialised distributed value for the given Gang
.
The gang is used (only) to know how many elements are needed
in the distributed value.
readMD :: MDist a s -> Int -> ST s aSource
Extract an element from a mutable distributed value.
writeMD :: MDist a s -> Int -> a -> ST s ()Source
Write an element of a mutable distributed value.
unsafeFreezeMD :: MDist a s -> ST s (Dist a)Source
Unsafely freeze a mutable distributed value.
Ensure a distributed value is fully evaluated.
Number of elements in the distributed value.
- For debugging only, as code shouldn't be sensitive to the return value.
sizeMD :: MDist a s -> IntSource
Number of elements in the mutable distributed value.
- For debugging only, as code shouldn't be sensitive to the return value.
Show a distributed value.
- For debugging only.
newD :: DT a => Gang -> (forall s. MDist a s -> ST s ()) -> Dist aSource
Given a computation that can write its result to a mutable distributed value, run the computation to generate an immutable distributed value.
checkGangD :: DT a => String -> Gang -> Dist a -> b -> bSource
Check that the sizes of the Gang
and of the distributed value match.
Primitive Distributed Operators.
Create a distributed value, given a function to create the instance for each thread.
Create a distributed value, but do it sequentially.
This function is used when we want to operate on a distributed value, but there isn't much data involved. For example, if we want to distribute a single integer to each thread, then there's no need to fire up the gang for this.
imapD' :: (DT a, DT b) => What -> Gang -> (Int -> a -> b) -> Dist a -> Dist bSource
Map a function across all elements of a distributed value. The worker function also gets the current thread index.