%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % Eden Porting Project, Philipps-Universität Marburg % % % % Exercise version, workpool incomplete % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{code} {-# OPTIONS -cpp #-} module EdenSkel (parMap, farm, dm, eagerInstList, shuffle, unshuffleN ) where import Eden import List \end{code} \section{Eden Skeletons} This module contains essential Eden Skeletons described in research papers: ParMap, Farm, Direct Mapping. \begin{code} -- The skeletons ---------------- -- basic: parMap parMap :: (Trans a, Trans b) => Process a b -> [a] -> [b] parMap p xs = eagerInstList (repeat p) xs -- process farm farm :: (Trans a, Trans b) => Int -> (Int -> [a] -> [[a]]) -- n, distribute -> ([[b]] -> [b]) -- combine -> Process [a] [b] -- worker process -> [a] -> [b] -- what to do farm np distr combine p inputs = combine (parMap p (distr np inputs)) -- direct mapping dm :: (Trans a, Trans b) => Int -> (Int -> [a] -> [[a]]) -> ([[b]] -> [b]) -> ([a] -> Process () [b]) -> [a] -> [b] dm np split combine proc inputs = combine results where results = eagerInstList proclist (repeat void) proclist = [ proc (extract i np inputs)| i <- [0..(np-1)] ] extract i n inputs = (split n inputs)!!i \end{code} \section{Eager Process Instantiation} These are the functions to create eagerly instantiated processes in programs (a very common task in Eden programs). Lists are eagerly instantiated by evaluating each element to WHNF. This function uses the internals createProcess and Lift to avoid waiting for a result after process creation (core transformation not implemented). %------------------------------ \begin{code} cpTL :: (Trans a, Trans b) => Process a b -> a -> Lift b cpTL = createProcess -- Front End Function: ---------------------- {- eagerInstList zips a list of processes and their input. All processes are instantiated on the way.-} eagerInstList :: (Trans a, Trans b) => [Process a b ] -> [a] -> [b] eagerInstList ps xs = let insts = zipWith (cpTL) ps xs in tlList insts -- Helpers: ----------- -- tlList: force the instantiation of the element processes and return the list of results tlList :: [Lift a] -> [a] -- tlList insts = foldr1 (seq) insts tlList insts = forceWHNFSpine insts `seq` (map deLift insts) -- forceWHNFSpine: evaluate all elements of the list to WHNF forceWHNFSpine :: [a] -> () forceWHNFSpine [] = () forceWHNFSpine (x:xs) = x `seq` forceWHNFSpine xs -- tlLList: the same for an list of lists tlLList :: [[Lift a]] -> [[a]] -- tlLList insts = foldr1 (seq) (foldr1 (seq) insts) tlLList insts = forceWHNFSpine (map forceWHNFSpine insts) `seq` (map (map deLift) insts) \end{code} \section{Helpers} Some functions to distribute and combine a list. \begin{code} {- unshuffleN splits a list into n lists [takeEach n (drop i xs) | i <- [0..(n-1)]] -} unshuffleN :: Int -> [a] -> [[a]] unshuffleN n xs = unshuffle xs where unshuffle xs = map (f xs) [0..n-1] where f xs i = g (drop i xs) g [] = [] g xs = head xs : (g (drop n xs)) -- simple shuffling (not incremental!) shuffle :: [[a]] -> [a] shuffle = concat . transpose void = () \end{code}