Safe Haskell | None |
---|
- Types
- Constructors
- Projections
- Update
- Permutation
- Zipping and Unzipping
- Map and ZipWith
- Scans and Folds
- Pack and Filter
- Combine and Interleave
- Selectors
- Selector Representations
- Segment Descriptors
- Scattered Segment Descriptors
- Virtual Segment Descriptors
- Irregular two dimensional arrays
- Random arrays
- Array IO
Parallel implementation of the segmented array API defined in dph-prim-interface
.
Some of them don't yet have parallel implementations, so we fall back
to the sequential ones from dph-prim-seq
.
WARNING: Although this library is intended to be used as a target
for the DPH vectoriser, it is also fine to use it directly from non
DPH programs. However, this library does not support nested parallelism
by itself. If you try to run further parallel computations in the workers
passed to map
, zipWith
, fold
etc, then they will just run
sequentially.
- class (Unbox a, DT a) => Elt a
- type Array = Vector
- empty :: Elt a => Array a
- generate :: Elt a => Int -> (Int -> a) -> Array a
- replicate :: Elt a => Int -> a -> Array a
- replicate_s :: Elt a => Segd -> Array a -> Array a
- replicate_rs :: Elt a => Int -> Array a -> Array a
- repeat :: Elt a => Int -> Int -> Array a -> Array a
- indexed :: Elt a => Array a -> Array (Int, a)
- (+:+) :: Elt a => Array a -> Array a -> Array a
- append_s :: Elt a => Segd -> Segd -> Array a -> Segd -> Array a -> Array a
- append_vs :: (Elt a, Elts a) => Segd -> VSegd -> Arrays a -> VSegd -> Arrays a -> Array a
- indices_s :: Segd -> Array Int
- enumFromTo :: Int -> Int -> Array Int
- enumFromThenTo :: Int -> Int -> Int -> Array Int
- enumFromStepLen :: Int -> Int -> Int -> Array Int
- enumFromStepLenEach :: Int -> Array Int -> Array Int -> Array Int -> Array Int
- length :: Elt a => Array a -> Int
- index :: Elt a => String -> Array a -> Int -> a
- indexs :: Elt a => Array a -> Array Int -> Array a
- indexs_avs :: (Elt a, Elts a) => Arrays a -> VSegd -> Array (Int, Int) -> Array a
- extract :: Elt a => Array a -> Int -> Int -> Array a
- extracts_nss :: Elt a => SSegd -> Vector (Array a) -> Array a
- extracts_ass :: (Elt a, Elts a) => SSegd -> Arrays a -> Array a
- extracts_avs :: (Elt a, Elts a) => VSegd -> Arrays a -> Array a
- drop :: Elt a => Int -> Array a -> Array a
- update :: Elt a => Array a -> Array (Int, a) -> Array a
- permute :: Elt a => Array a -> Array Int -> Array a
- bpermute :: Elt a => Array a -> Array Int -> Array a
- mbpermute :: (Elt a, Elt b) => (a -> b) -> Array a -> Array Int -> Array b
- bpermuteDft :: Elt e => Int -> (Int -> e) -> Array (Int, e) -> Array e
- zip :: (Elt a, Elt b) => Array a -> Array b -> Array (a, b)
- zip3 :: (Elt a, Elt b, Elt c) => Array a -> Array b -> Array c -> Array (a, b, c)
- unzip :: (Elt a, Elt b) => Array (a, b) -> (Array a, Array b)
- unzip3 :: (Elt a, Elt b, Elt c) => Array (a, b, c) -> (Array a, Array b, Array c)
- fsts :: (Elt a, Elt b) => Array (a, b) -> Array a
- snds :: (Elt a, Elt b) => Array (a, b) -> Array b
- map :: (Elt a, Elt b) => (a -> b) -> Array a -> Array b
- zipWith :: (Elt a, Elt b, Elt c) => (a -> b -> c) -> Array a -> Array b -> Array c
- zipWith3 :: (Elt a, Elt b, Elt c, Elt d) => (a -> b -> c -> d) -> Array a -> Array b -> Array c -> Array d
- zipWith4 :: (Elt a, Elt b, Elt c, Elt d, Elt e) => (a -> b -> c -> d -> e) -> Array a -> Array b -> Array c -> Array d -> Array e
- zipWith5 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => (a -> b -> c -> d -> e -> f) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array f
- zipWith6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g) => (a -> b -> c -> d -> e -> f -> g) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array f -> Array g
- zipWith7 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h) => (a -> b -> c -> d -> e -> f -> g -> h) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array f -> Array g -> Array h
- zipWith8 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i) => (a -> b -> c -> d -> e -> f -> g -> h -> i) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array f -> Array g -> Array h -> Array i
- scan :: Elt a => (a -> a -> a) -> a -> Array a -> Array a
- fold :: Elt a => (a -> a -> a) -> a -> Array a -> a
- fold_s :: Elt a => (a -> a -> a) -> a -> Segd -> Array a -> Array a
- fold_ss :: (Elts a, Elt a) => (a -> a -> a) -> a -> SSegd -> Arrays a -> Array a
- fold_vs :: (Elts a, Elt a) => (a -> a -> a) -> a -> VSegd -> Arrays a -> Array a
- fold_r :: Elt a => (a -> a -> a) -> a -> Int -> Array a -> Array a
- fold1 :: Elt a => (a -> a -> a) -> Array a -> a
- fold1_s :: Elt a => (a -> a -> a) -> Segd -> Array a -> Array a
- fold1_ss :: (Elts a, Elt a) => (a -> a -> a) -> SSegd -> Arrays a -> Array a
- fold1_vs :: (Elts a, Elt a) => (a -> a -> a) -> VSegd -> Arrays a -> Array a
- sum :: (Num a, Elt a) => Array a -> a
- sum_s :: (Num a, Elt a) => Segd -> Array a -> Array a
- sum_ss :: (Num a, Elts a, Elt a) => SSegd -> Arrays a -> Array a
- sum_r :: (Num a, Elt a) => Int -> Array a -> Array a
- count :: (Elt a, Eq a) => Array a -> a -> Int
- count_s :: (Elt a, Eq a) => Segd -> Array a -> a -> Array Int
- count_ss :: (Elt a, Eq a) => SSegd -> Vector (Array a) -> a -> Array Int
- and :: Array Bool -> Bool
- pack :: Elt a => Array a -> Array Bool -> Array a
- packByTag :: Elt a => Array a -> Array Tag -> Tag -> Array a
- filter :: Elt a => (a -> Bool) -> Array a -> Array a
- pick :: (Elt a, Eq a) => Array a -> a -> Array Bool
- combine :: Elt a => Array Bool -> Array a -> Array a -> Array a
- combine2 :: Elt a => Array Tag -> SelRep2 -> Array a -> Array a -> Array a
- interleave :: Elt a => Array a -> Array a -> Array a
- type Sel2 = UPSel2
- mkSel2 :: Array Tag -> Array Int -> Int -> Int -> SelRep2 -> Sel2
- tagsSel2 :: Sel2 -> Array Tag
- indicesSel2 :: Sel2 -> Array Int
- elementsSel2_0 :: Sel2 -> Int
- elementsSel2_1 :: Sel2 -> Int
- repSel2 :: Sel2 -> SelRep2
- tagsToSel2 :: Array Tag -> Sel2
- type SelRep2 = UPSelRep2
- mkSelRep2 :: Array Tag -> SelRep2
- indicesSelRep2 :: Array Tag -> SelRep2 -> Array Int
- elementsSelRep2_0 :: Array Tag -> SelRep2 -> Int
- elementsSelRep2_1 :: Array Tag -> SelRep2 -> Int
- type Segd = UPSegd
- mkSegd :: Array Int -> Array Int -> Int -> Segd
- validSegd :: Segd -> Bool
- emptySegd :: Segd
- singletonSegd :: Int -> Segd
- lengthsToSegd :: Array Int -> Segd
- lengthSegd :: Segd -> Int
- lengthsSegd :: Segd -> Array Int
- indicesSegd :: Segd -> Array Int
- elementsSegd :: Segd -> Int
- plusSegd :: Segd -> Segd -> Segd
- type SSegd = UPSSegd
- mkSSegd :: Array Int -> Array Int -> Segd -> SSegd
- validSSegd :: SSegd -> Bool
- emptySSegd :: SSegd
- singletonSSegd :: Int -> SSegd
- promoteSegdToSSegd :: Segd -> SSegd
- isContiguousSSegd :: SSegd -> Bool
- lengthOfSSegd :: SSegd -> Int
- lengthsOfSSegd :: SSegd -> Array Int
- indicesOfSSegd :: SSegd -> Array Int
- startsOfSSegd :: SSegd -> Array Int
- sourcesOfSSegd :: SSegd -> Array Int
- getSegOfSSegd :: SSegd -> Int -> (Int, Int, Int, Int)
- appendSSegd :: SSegd -> Int -> SSegd -> Int -> SSegd
- type VSegd = UPVSegd
- mkVSegd :: Array Int -> SSegd -> VSegd
- validVSegd :: VSegd -> Bool
- emptyVSegd :: VSegd
- singletonVSegd :: Int -> VSegd
- replicatedVSegd :: Int -> Int -> VSegd
- promoteSegdToVSegd :: Segd -> VSegd
- promoteSSegdToVSegd :: SSegd -> VSegd
- isManifestVSegd :: VSegd -> Bool
- isContiguousVSegd :: VSegd -> Bool
- lengthOfVSegd :: VSegd -> Int
- takeVSegidsOfVSegd :: VSegd -> Array Int
- takeVSegidsRedundantOfVSegd :: VSegd -> Array Int
- takeSSegdOfVSegd :: VSegd -> SSegd
- takeSSegdRedundantOfVSegd :: VSegd -> SSegd
- takeLengthsOfVSegd :: VSegd -> Array Int
- getSegOfVSegd :: VSegd -> Int -> (Int, Int, Int)
- unsafeDemoteToSSegdOfVSegd :: VSegd -> SSegd
- unsafeDemoteToSegdOfVSegd :: VSegd -> Segd
- updateVSegsOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegd
- updateVSegsReachableOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegd
- appendVSegd :: VSegd -> Int -> VSegd -> Int -> VSegd
- combine2VSegd :: Sel2 -> VSegd -> Int -> VSegd -> Int -> VSegd
- class (Unboxes a, DT a) => Elts a
- type Arrays = Vectors
- emptys :: Arrays a
- singletons :: (Elt a, Elts a) => Array a -> Arrays a
- lengths :: Elts a => Arrays a -> Int
- unsafeIndexs :: (Elt a, Elts a) => Arrays a -> Int -> Array a
- unsafeIndex2s :: (Elt a, Elts a) => Arrays a -> Int -> Int -> a
- appends :: (Elt a, Elts a) => Arrays a -> Arrays a -> Arrays a
- fromVectors :: (Elt a, Elts a) => Vector (Array a) -> Arrays a
- toVectors :: (Elt a, Elts a) => Arrays a -> Vector (Array a)
- randoms :: (Elt a, Random a, RandomGen g) => Int -> g -> Array a
- randomRs :: (Elt a, Random a, RandomGen g) => Int -> (a, a) -> g -> Array a
- class UIO a => IOElt a
- hGet :: IOElt a => Handle -> IO (Array a)
- hPut :: IOElt a => Handle -> Array a -> IO ()
- toList :: Elt a => Array a -> [a]
- fromList :: Elt a => [a] -> Array a
Types
Arrays are stored as unboxed vectors. They have bulk-strict semantics, so demanding one element demands them all.
Constructors
generate :: Elt a => Int -> (Int -> a) -> Array aSource
Generate a new array given its length and a function to compute each element.
replicate :: Elt a => Int -> a -> Array aSource
O(length result). Construct a new array by replicating a single element the given number of times.
replicate_s :: Elt a => Segd -> Array a -> Array aSource
O(length result). Segmented replicate.
Elements of the array are replicated according to the lengths of the
segments defined by the Segd
.
replicate_rs :: Elt a => Int -> Array a -> Array aSource
O(length result). Regular segmented replicate.
Like replicate_s
, but all segments are assumed to have the given length.
:: Elt a | |
=> Int | Number of times to repeat the source. |
-> Int | Length of source (can be less than the provided array). |
-> Array a | Array elements to repeat. |
-> Array a |
O(length result). Construct an array by copying a portion of another array.
indexed :: Elt a => Array a -> Array (Int, a)Source
O(length result). Tag each element of an array with its index.
indexed [42, 93, 13] = [(0, 42), (1, 93), (2, 13)]
:: Elt a | |
=> Segd | Segment descriptor of result aarray. |
-> Segd | Segment descriptor of first array. |
-> Array a | Data of first array. |
-> Segd | Segment descriptor of second array. |
-> Array a | Data of second array. |
-> Array a |
O(length result). Segmented append.
indices_s :: Segd -> Array IntSource
O(length result). Segmented indices.
Construct an array containing containing the segments defined by the
given Segd
.
Each segment will contain the elements [0..len-1]
where len
is the
length of that segment.
Projections
index :: Elt a => String -> Array a -> Int -> aSource
O(1). Retrieve a numbered element from an array.
The first argument gives a source-code location for out-of-bounds errors.
:: Elt a | |
=> Array a | Source array. |
-> Int | Starting index in source array. |
-> Int | Length of result array. |
-> Array a |
O(length result). Extract a subrange of elements from an array.
extract [23, 42, 93, 50, 27] 1 3 = [42, 93, 50]
extracts_nss :: Elt a => SSegd -> Vector (Array a) -> Array aSource
O(length result). Extract segments defined by a SSegd
from a vector of arrays.
NOTE: This is a transitory interface, and will be removed in future versions.
Use extracts_ass
instead.
drop :: Elt a => Int -> Array a -> Array aSource
O(length result). Drop elements from the front of an array, returning the latter portion.
Update
O(length result). Copy the source array while replacing some elements by new ones in the result.
Permutation
:: Elt a | |
=> Array a | Source array. |
-> Array Int | Indices in the destination to copy elements to. |
-> Array a |
O(length result). Forwards permutation of array elements.
:: Elt a | |
=> Array a | Source array. |
-> Array Int | Indices in the source to copy elements from. |
-> Array a |
O(length result). Backwards permutation of array elements.
bpermute [50, 60, 20, 30] [0, 3, 2] = [50, 30, 20]
mbpermute :: (Elt a, Elt b) => (a -> b) -> Array a -> Array Int -> Array bSource
Combination of map and bpermute.
The advantage of using this combined version is that we don't need to apply the parameter function to source elements that don't appear in the result.
bpermuteDft :: Elt e => Int -> (Int -> e) -> Array (Int, e) -> Array eSource
Default backwards permutation.
The values of the index-value pairs are written into the position in the result array that is indicated by the corresponding index.
All positions not covered by the index-value pairs will have the value determined by the initialiser function for that index position.
Zipping and Unzipping
zip :: (Elt a, Elt b) => Array a -> Array b -> Array (a, b)Source
O(1). Zip two arrays into an array of pairs. If one array is short, excess elements of the longer array are discarded.
zip3 :: (Elt a, Elt b, Elt c) => Array a -> Array b -> Array c -> Array (a, b, c)Source
O(1). Zip three arrays into an array of triples. If one array is short, excess elements of the longer arrays are discarded.
unzip :: (Elt a, Elt b) => Array (a, b) -> (Array a, Array b)Source
O(1). Unzip an array of pairs into a pair of arrays.
unzip3 :: (Elt a, Elt b, Elt c) => Array (a, b, c) -> (Array a, Array b, Array c)Source
O(1). Unzip an array of triples into a triple of arrays.
fsts :: (Elt a, Elt b) => Array (a, b) -> Array aSource
O(1). Take the first elements of an array of pairs.
snds :: (Elt a, Elt b) => Array (a, b) -> Array bSource
O(1). Take the second elements of an array of pairs.
Map and ZipWith
map :: (Elt a, Elt b) => (a -> b) -> Array a -> Array bSource
Apply a worker function to each element of an array, yielding a new array.
zipWith :: (Elt a, Elt b, Elt c) => (a -> b -> c) -> Array a -> Array b -> Array cSource
Apply a worker function to correponding elements of two arrays.
zipWith3 :: (Elt a, Elt b, Elt c, Elt d) => (a -> b -> c -> d) -> Array a -> Array b -> Array c -> Array dSource
Apply a worker function to corresponding elements of three arrays.
zipWith4 :: (Elt a, Elt b, Elt c, Elt d, Elt e) => (a -> b -> c -> d -> e) -> Array a -> Array b -> Array c -> Array d -> Array eSource
Apply a worker function to corresponding elements of four arrays.
zipWith5 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f) => (a -> b -> c -> d -> e -> f) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array fSource
Apply a worker function to corresponding elements of five arrays.
zipWith6 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g) => (a -> b -> c -> d -> e -> f -> g) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array f -> Array gSource
Apply a worker function to corresponding elements of six arrays.
zipWith7 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h) => (a -> b -> c -> d -> e -> f -> g -> h) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array f -> Array g -> Array hSource
Apply a worker function to corresponding elements of seven arrays.
zipWith8 :: (Elt a, Elt b, Elt c, Elt d, Elt e, Elt f, Elt g, Elt h, Elt i) => (a -> b -> c -> d -> e -> f -> g -> h -> i) -> Array a -> Array b -> Array c -> Array d -> Array e -> Array f -> Array g -> Array h -> Array iSource
Apply a worker function to corresponding elements of six arrays.
Scans and Folds
scan :: Elt a => (a -> a -> a) -> a -> Array a -> Array aSource
Similar to foldl
but return an array of the intermediate states, including
the final state that is computed by foldl
.
fold :: Elt a => (a -> a -> a) -> a -> Array a -> aSource
Undirected fold over an array.
- The worker function must be associative.
- The provided starting element must be neutral with respect to the worker. For example 0 is neutral wrt (+) and 1 is neutral wrt (*).
fold_s :: Elt a => (a -> a -> a) -> a -> Segd -> Array a -> Array aSource
Undirected segmented fold.
All segments are folded individually, and the result contains one element for each segment.
Same preconditions as fold
.
fold1 :: Elt a => (a -> a -> a) -> Array a -> aSource
Undirected fold, using the first element to initialise the state.
- The worker function must be associative.
- The provided starting element must be neutral with respect to the worker. For example 0 is neutral wrt (+) and 1 is neutral wrt (*).
- If the array contains no elements then you'll get a bounds check
error
.
count :: (Elt a, Eq a) => Array a -> a -> IntSource
Count the number of elements in array that are equal to the given value.
count_ss :: (Elt a, Eq a) => SSegd -> Vector (Array a) -> a -> Array IntSource
Scattered segmented count.
NOTE: This is a transitory interface, and will be removed in future versions.
and :: Array Bool -> BoolSource
O(length source). Compute the conjunction of all elements in a boolean array.
Pack and Filter
pack :: Elt a => Array a -> Array Bool -> Array aSource
O(length result). Extract elements of an array where the associated flag is true.
:: Elt a | |
=> Array a | data values |
-> Array Tag | tag values |
-> Tag | the tag of values to select |
-> Array a | data values that had that tag |
O(length result). Select the elements of an array that have a corresponding tag.
packByTag [12, 24, 42, 93] [1, 0, 0, 1] 0 = [24, 42]
filter :: Elt a => (a -> Bool) -> Array a -> Array aSource
Extract the elements from an array that match the given predicate.
pick :: (Elt a, Eq a) => Array a -> a -> Array BoolSource
Compute an array of flags indicating which elements match a given value.
pick [4, 5, 3, 6, 5, 2, 5] 5 = [F, T, F, F, T, F, T]
Combine and Interleave
combine :: Elt a => Array Bool -> Array a -> Array a -> Array aSource
Combine two arrays, using a flags array to tell us where to get each element from.
combine [T, F, F, T, T, F] [1, 2, 3] [4, 5, 6] = [1, 4, 5, 2, 3, 6]
interleave :: Elt a => Array a -> Array a -> Array aSource
Interleave the elements of two arrays.
interleave [1, 2, 3] [4, 5, 6] = [1, 4, 2, 5, 3, 6]
Selectors
:: Array Tag | Tags array. |
-> Array Int | Indices array. |
-> Int | Number of elements taken from first source array. |
-> Int | Number of elements taken from second source array. |
-> SelRep2 | Parallel selector representation. |
-> Sel2 |
O(1). Construct a selector.
A selector is a description of how to perform a combine
operation.
Suppose we are evaluating the following expression:
combine [F,F,T,F,T,T] [1,2,3] [4,5,6] = [4,5,1,6,2,3]
This is difficult to parallelise. For each element in the result, the source array we get this element from depends on the tag values associated with all previous elements.
However, if we going to apply combine
several times with the same flags array,
we can precompute a selector that tells us where to get each element.
The selector contains the original flags, as well as the source index telling
us where to get each element for the result array.
For example:
tagsToIndices2 [F,F,T,F,T,T] -- tags = [0,1,0,2,1,2] -- indices
This says get the first element from index 0 in the second array, then from index 1 in the second array, then index 0 in the first array ...
The selector then consists of both the tag
and indices
arrays.
indicesSel2 :: Sel2 -> Array IntSource
O(1). Yield the indices array of a selector.
elementsSel2_0 :: Sel2 -> IntSource
O(1). Yield the number of elements that will be taken from the first array.
elementsSel2_1 :: Sel2 -> IntSource
O(1). Yield the number of elements that will be taken from the second array.
tagsToSel2 :: Array Tag -> Sel2Source
O(n). Compute a selector from a tags array.
Selector Representations
mkSelRep2 :: Array Tag -> SelRep2Source
O(n). Construct a parallel selector representation.
A SelRep2
describes how to distribute the two data vectors
corresponding to a Sel2
across several PEs.
Suppose we want to perform the following combine
operation:
combine [F,F,T,T,F,T,F,F,T] [A0,A1,A2,A3,A4] [B0,B1,B2,B3] = [A0,A1,B0,B1,A2,B2,A3,A4,B3]
The first array is the flags array, that says which of the data arrays to
get each successive element from. As combine
is difficult to compute
in parallel, if we are going to perform several combines with the same
flags array, we can precompute a selector that tells us where to get each
element. The selector contains the original flags, as well as the source
index telling us where to get each element for the result array.
flags: [F,F,T,T,F,T,F,F,T] indices: [0,1,0,1,2,2,3,4,3]
Suppose we want to distribute the combine operation across 3 PEs. It's easy to split the selector like so:
PE0 PE1 PE2 flags: [F,F,T] [T,F,T] [F,F,T] indices: [0,1,0] [1,2,2] [3,4,3]
We now need to split the two data arrays. Each PE needs slices of the data arrays that correspond to the parts of the selector that were given to it. For the current example we get:
PE0 PE1 PE2 data_A: [A0,A1] [A2] [A3,A4] data_B: [B0] [B1,B2] [B3]
The SelRep2
contains the starting index and length of each of of these
slices:
PE0 PE1 PE2 ((0, 0), (2, 1)) ((2, 1), (1, 2)) ((3, 3), (2, 1)) indices lens indices lens indices lens
indicesSelRep2 :: Array Tag -> SelRep2 -> Array IntSource
O(1). Take the indices
field from a SelRep2
.
elementsSelRep2_0 :: Array Tag -> SelRep2 -> IntSource
O(1). Yield the number of elements to take from the first array.
elementsSelRep2_1 :: Array Tag -> SelRep2 -> IntSource
O(1). Yield the number of elements to take from the second array.
Segment Descriptors
:: Array Int | (lengths) Segment lengths. |
-> Array Int | (indices) Segment indices. |
-> Int | Total number of elements. |
-> Segd |
O(max(segs, threads) . log segs). Construct a segment descriptor.
A segment desciptor defines an irregular 2D array based on a flat, 1D array of elements. The defined array is a nested array of segments, where every segment covers some of the elements from the flat array.
- The starting indices must be equal to
init (scanl (+) 0 lengths)
- If you don't want to cover all the elements from the flat arrary then
use a
SSegd
instead.
Example:
flat array data: [1 2 3 4 5 6 7 8] (segmentation) --- ----- - --- segd lengths: [2, 3, 1, 2] indices: [0, 2, 5, 6] elements: 8
singletonSegd :: Int -> SegdSource
O(1). Construct a Segd
containing a single segment of the given length.
lengthsToSegd :: Array Int -> SegdSource
O(max(segs, threads) . log segs).
Construct a Segd
from an array of segment lengths.
lengthSegd :: Segd -> IntSource
O(1). Yield the length of a Segd
.
elementsSegd :: Segd -> IntSource
O(1). Yield the total number of elements defined by a Segd
.
plusSegd :: Segd -> Segd -> SegdSource
O(max(segs, threads) . log segs). Add the lengths of corresponding segments in two descriptors.
plusSegd [lens: 2 3 1] [lens: 3 1 1] = [lens: 5 4 2]
Scattered Segment Descriptors
:: Array Int | (starts) Starting index of each segment within its flat array. |
-> Array Int | (sources) Source id of flat array to get each segment from. |
-> Segd | Plain segment descriptor giving the lengths of the segments. |
-> SSegd |
Construct a Scattered Segment Descriptor.
A SSegd
is an extension of a Segd
that that allows the segments to be
scattered through multiple flat arrays.
Each segment is associated with a source id that indicates what flat array it is in, along with the starting index in that flat array.
- The segments need not cover the entire flat array.
- Different segments may point to the same elements.
validSSegd :: SSegd -> BoolSource
Check whether a Segd
is well formed.
O(1). Construct an empty SSegd
.
singletonSSegd :: Int -> SSegdSource
O(1). Construct a Segd
containing a single segment of the given length.
isContiguousSSegd :: SSegd -> BoolSource
lengthOfSSegd :: SSegd -> IntSource
O(1). Yield the length of a SSegd
.
getSegOfSSegd :: SSegd -> Int -> (Int, Int, Int, Int)Source
O(1). Get the length, segment index, starting index, and source id of a segment.
appendSSegd :: SSegd -> Int -> SSegd -> Int -> SSegdSource
Produce a segment descriptor that describes the result of appending two segmented arrays.
Virtual Segment Descriptors
:: Array Int | (vsegids) Mapping from virtual to physical segments. |
-> SSegd | Scattered Segment descriptor defining the physical segments. |
-> VSegd |
Construct a Virtual Segment Descriptor.
A VSegd
is an extension of a SSegd
that allows data from the underlying
flat array to be shared between segments. For example, you can define an array
of 10 virtual segments that all have the same length and elements as a
single physical segment.
- Internally we maintain the invariant that all physical segments must be
reachable by some virtual segment. This is needed to ensure that operations
such as
fold_ss
segmented fold have the right complexity. - If you don't need the invariant then you can sidestep the code that maintains it by using the redundant versions of the following operators, and sometimes get faster code.
validVSegd :: VSegd -> BoolSource
Check whether a Segd
is well formed.
O(1). Construct an empty SSegd
.
singletonVSegd :: Int -> VSegdSource
O(1). Construct a VSegd
containing a single segment of the given length.
O(len). Construct a VSegd
that describes an array where all virtual
segments point to the same physical segment.
isManifestVSegd :: VSegd -> BoolSource
O(1). If true then the segments are all unshared, and the vsegids
field
be just [0..len-1]
.
Consumers can check this field to avoid demanding the vsegids
field.
This can avoid the need for it to be constructed in the first place,
due to lazy evaluation.
isContiguousVSegd :: VSegd -> BoolSource
O(1). If true then the starts
field is identical to the indices
field
and the sourceids are all 0s.
In this case all the data elements are in one contiguous flat array, and consumers can avoid looking at the real starts and sources fields.
lengthOfVSegd :: VSegd -> IntSource
O(1). Yield the length of a VSegd
.
takeVSegidsRedundantOfVSegd :: VSegd -> Array IntSource
O(1). Yield the vsegids of a VSegd
, but don't require that every physical
segment is referenced by some virtual segment.
If you're just performing indexing and don't need the invariant that all physical segments are reachable from some virtual segment, then use this version as it's faster. This sidesteps the code that maintains the invariant.
The stated O(1) complexity assumes that the array has already been fully
evalauted. If this is not the case then we can avoid demanding the result
of a prior computation on the vsegids
, thus reducing the cost attributed
to that prior computation.
takeSSegdRedundantOfVSegd :: VSegd -> SSegdSource
O(1). Yield the SSegd
of a VSegd
, but don't require that every physical
segment is referenced by some virtual segment.
See the note in takeVSegidsRedundantOfVSegd
.
getSegOfVSegd :: VSegd -> Int -> (Int, Int, Int)Source
O(1). Get the length, starting index, and source id of a segment.
unsafeDemoteToSSegdOfVSegd :: VSegd -> SSegdSource
O(segs).
Yield a SSegd
that describes each segment of a VSegd
individually.
By doing this we lose information about which virtual segments correspond to the same physical segments.
WARNING: Trying to take the SSegd
of a nested array that has been
constructed with replication can cause index space overflow. This is
because the virtual size of the corresponding flat data can be larger
than physical memory. If this happens then indices fields and
element count in the result will be invalid.
unsafeDemoteToSegdOfVSegd :: VSegd -> SegdSource
O(segs). Yield a Segd
that describes each segment of a VSegd
individually.
By doing this we lose information about which virtual segments correspond to the same physical segments.
See the warning in unsafeDemoteToSSegdOfVSegd
.
updateVSegsOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegdSource
Update the vsegids
of a VSegd
, and then cull the physical
segment descriptor so that all physical segments are reachable from
some virtual segment.
updateVSegsReachableOfVSegd :: (Array Int -> Array Int) -> VSegd -> VSegdSource
Update the vsegids
of VSegd
, where the result is guaranteed to
cover all physical segments.
Using this version avoids performing the cull
operation which
discards unreachable physical segments.
- The resulting vsegids must cover all physical segments.
If they do not then there will be physical segments that are not
reachable from some virtual segment, and subsequent operations
like
fold_ss
will have the wrong work complexity.
:: VSegd | Descriptor of first array. |
-> Int | Number of flat physical arrays for first descriptor. |
-> VSegd | Descriptor of second array. |
-> Int | Number of flat physical arrays for second descriptor. |
-> VSegd |
Produce a virtual segment descriptor that describes the result of appending two segmented arrays.
:: Sel2 | Selector for the combine operation. |
-> VSegd | Descriptor of first array. |
-> Int | Number of flat physical arrays for first descriptor. |
-> VSegd | Descriptor of second array. |
-> Int | Number of flat physical arrays for second descriptor. |
-> VSegd |
Combine two virtual segment descriptors.
Irregular two dimensional arrays
unsafeIndex2s :: (Elt a, Elts a) => Arrays a -> Int -> Int -> aSource
O(1). Retrieve a single element from an Arrays
,
given the outer and inner indices.
appends :: (Elt a, Elts a) => Arrays a -> Arrays a -> Arrays aSource
O(n). Append two Arrays
, using work proportional to the length
of the outer array.
Random arrays
randoms :: (Elt a, Random a, RandomGen g) => Int -> g -> Array aSource
Generate an array of the given length full of random data. Good for testing.
randomRs :: (Elt a, Random a, RandomGen g) => Int -> (a, a) -> g -> Array aSource
Generate an array of the given length full of random data. Good for testing.