module Control.Parallel.Eden.DivConq (
DivideConquer, DivideConquerSimple,
dc,
parDC,
disDC, offline_disDC, disDCdepth, disDCn,
flatDC,
divConSeq, divConSeq_c,
divCon, divCon_c, divConD, divConD_c,
dcN, dcN_c, dcN', dcN_c', dcNTickets, dcNTickets_c,
divConFlat, divConFlat_c
) where
#if defined( __PARALLEL_HASKELL__ )
import Control.Parallel.Eden
#else
import Control.Parallel.Eden.EdenConcHs
#endif
import Control.Parallel.Eden.Map
import Control.Parallel.Eden.Auxiliary
type DivideConquer a b
= (a -> Bool)
-> (a -> b)
-> (a -> [a])
-> (a -> [b] -> b)
-> a
-> b
dc :: DivideConquer a b
dc trivial solve split combine = rec_dc
where
rec_dc x = if trivial x then solve x
else combine x (map rec_dc (split x))
parDC :: (Trans a, Trans b)
=> Int
-> DivideConquer a b
parDC lv trivial solve split combine
= pdc lv
where
pdc lv x
| lv == 0 = dc trivial solve split combine x
| lv > 0 = if trivial x then solve x
else combine x (parMap (pdc (lv1)) (split x))
disDC :: (Trans a, Trans b)
=> Int
-> Places
-> DivideConquer a b
disDC k tickets trivial solve split combine x
= if null tickets then seqDC x
else recDC tickets x
where
seqDC = dc trivial solve split combine
recDC tickets x =
if trivial x then solve x
else childRes `pseq`
rdeepseq myRes `pseq`
combine x ( myRes:childRes ++ localRess )
where
childRes = spawnAt childTickets childProcs procIns
childProcs = map (process . recDC) theirTs
(childTickets, restTickets) = splitAt (k1) tickets
(myTs: theirTs) = unshuffle k restTickets
(myIn:theirIn) = split x
(procIns, localIns)
= splitAt (length childTickets) theirIn
myRes = recDC myTs myIn
localRess = map seqDC localIns
offline_disDC :: Trans b
=> Int
-> [Int]
-> DivideConquer a b
offline_disDC k ts triv solve split combine x
= snd (disDC k ts newtriv newsolve newsplit newcombine 0)
where
seqDC = dc triv solve split combine
newsplit = successors k
newtriv n = length ts <= k^(length (path k n))
newsolve n = (flag, seqDC localx)
where (flag, localx) = select triv split x (path k n)
newcombine n bs@((flag,bs1):_)
= if flag then (True, combine localx (map snd bs))
else (lab, bs1)
where (lab, localx) = select triv split x (path k n)
select :: (a -> Bool) -> (a -> [a])
-> a -> [Int] -> (Bool,a)
select trivial split x ys = go x ys
where go x [] = (True, x)
go x (y:ys) = if trivial x then (False, x)
else go (split x !! y) ys
successors :: Int -> Int -> [Int]
successors k n = [nk + i | let nk = n*k, i <- [1..k]]
path :: Int -> Int -> [Int]
path k n | n == 0 = []
| otherwise = reverse (factors k n)
factors :: Int -> Int -> [Int]
factors k n
| n <= 0 = []
| otherwise = (n+k1) `mod` k : factors k ((n1) `div` k)
disDCdepth :: (Trans a, Trans b)
=> Int
-> Int
-> DivideConquer a b
disDCdepth k depth trivial solve split combine x
| depth < 1 = dc trivial solve split combine x
| trivial x = solve x
| otherwise = childRs `seq`
combine x (myR : childRs)
where myself = disDCdepth k (depth 1) trivial solve split combine
(mine:rest) = split x
myR = myself mine
childRs = parMapAt places myself rest
`using` seqList r0
places = map ((+1) . (`mod` noPe) . (+(1))) shifts
shifts = map (selfPe +) [shift,2*shift..]
shift = k ^ (depth 1)
disDCn :: (Trans a, Trans b)
=> Int
-> Int
-> DivideConquer a b
disDCn k n = disDCdepth n depth
where depth = logN k n
logN n 1 = 0
logN n k | k > 0 = 1 + logN n ((k + n1) `div` n)
| otherwise = error "logN"
flatDC :: (Trans a,Trans b) =>
((a->b)->[a]->[b])
-> Int
-> DivideConquer a b
flatDC myMap depth trivial solve split combine x
= combineTopMaster combine levels results
where (tasks,levels) = generateTasks depth trivial split x
results = myMap(divConSeq_c trivial solve split combine) tasks
combineTopMaster :: (NFData b) =>
(a->[b]->b) -> (Tree a) -> [b] -> b
combineTopMaster c t bs = fst (combineTopRnf c t bs)
combineTopRnf :: (NFData b) =>
(a->[b]->b) -> (Tree a) -> [b] -> (b,[b])
combineTopRnf _ (Leaf a) (b:bs) = (b,bs)
combineTopRnf combine (Tree a ts) bs
= (rnf res `pseq` combine a res, bs')
where (bs',res) = foldl f (bs,[]) ts
f (olds,news) t = (remaining,news++[b])
where (b,remaining) = combineTopRnf combine t olds
generateTasks :: Int -> (a->Bool) -> (a->[a]) -> a -> ([a],Tree a)
generateTasks 0 _ _ a = ([a],Leaf a)
generateTasks n trivial split a
| trivial a = ([a],Leaf a)
| otherwise = (concat ass,Tree a ts)
where assts = map (generateTasks (n1) trivial split) (split a)
(ass,ts) = unzip assts
data Tree a = Tree a [Tree a] | Leaf a deriving Show
instance NFData a => NFData (Tree a)
where rnf (Tree a ls) = rnf a `seq` rnf ls
rnf (Leaf a) = rnf a
-----------------------------------DEPRECATED--------------------------------
type DivideConquerSimple a b
= (a -> Bool)
-> (a -> b)
-> (a -> [a])
-> ([b] -> b)
-> a
-> b
divConSeq :: (Trans a, Trans b) => DivideConquerSimple a b
divConSeq trivial solve split combine x
= dc trivial solve split (\_ parts -> combine parts) x
divConSeq_c :: (Trans a, Trans b) => DivideConquer a b
divConSeq_c = dc
divCon :: (Trans a, Trans b) => DivideConquerSimple a b
divCon trivial solve split combine x
= divCon_c trivial solve split (\_ parts -> combine parts) x
divCon_c :: (Trans a, Trans b) => DivideConquer a b
divCon_c trivial solve split combine x
| trivial x = solve x
| otherwise = combine x children
where children = parMap (divCon_c trivial solve split combine) (split x)
divConD :: (Trans a, Trans b)
=> Int
-> DivideConquerSimple a b
divConD depth trivial solve split combine x
= parDC depth trivial solve split (\_ parts -> combine parts) x
divConD_c :: (Trans a, Trans b)
=> Int
-> DivideConquer a b
divConD_c = parDC
dcN :: (Trans a, Trans b)
=> Int
-> Int
-> DivideConquerSimple a b
dcN n depth trivial solve split combine x
= disDCdepth n depth trivial solve split (\_ parts -> combine parts) x
dcN_c :: (Trans a, Trans b)
=> Int
-> Int
-> DivideConquer a b
dcN_c = disDCdepth
dcN' :: (Trans a, Trans b)
=> Int
-> Int
-> DivideConquerSimple a b
dcN' n pes = dcN n depth
where depth = logN n pes
dcN_c' :: (Trans a, Trans b)
=> Int
-> Int
-> DivideConquer a b
dcN_c' = disDCn
dcNTickets :: (Trans a, Trans b) =>
Int
-> Places
-> DivideConquerSimple a b
dcNTickets k ts trivial solve split combine x
= dcNTickets_c k ts trivial solve split (\_ parts -> combine parts) x
dcNTickets_c :: (Trans a, Trans b)
=> Int
-> Places
-> DivideConquer a b
dcNTickets_c k [] trivial solve split combine x
= divConSeq_c trivial solve split combine x
dcNTickets_c k tickets trivial solve split combine x
= if trivial x then solve x
else childRes `pseq`
rnf myRes `pseq` rnf localRess `pseq`
combine x (myRes:childRes ++ localRess )
where
(childTickets,restTickets) = splitAt (k1) tickets
(myTs:theirTs)= unshuffle k restTickets
ticketF ts = dcNTickets_c k ts trivial solve split combine
insts = length childTickets
(procIns, localIns) = splitAt insts theirIn
childProcs = map (process . ticketF) theirTs
childRes = spawnAt childTickets childProcs procIns
myRes = ticketF myTs myIn
(myIn:theirIn) = split x
localRess = map (divConSeq_c trivial solve split combine) localIns
divConFlat :: (Trans a,Trans b) =>
((a->b)->[a]->[b])
-> Int
-> DivideConquerSimple a b
divConFlat myMap depth trivial solve split combine x
= divConFlat_c myMap depth trivial solve split (\_ parts -> combine parts) x
divConFlat_c :: (Trans a,Trans b)
=> ((a->b)->[a]->[b])
-> Int
-> DivideConquer a b
divConFlat_c = flatDC