Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 25 additions & 60 deletions Control/Parallel/Strategies.hs
Original file line number Diff line number Diff line change
Expand Up @@ -628,68 +628,33 @@ parFmap strat f = (`using` parTraversable strat) . fmap f
-- --------------------------------------------------------------------------
-- Strategies for lazy lists

-- List-based non-compositional rolling buffer strategy, evaluating list
-- elements to weak head normal form.
-- Not to be exported; used in evalBuffer and for optimisation.
evalBufferWHNF :: Int -> Strategy [a]
evalBufferWHNF n0 xs0 = return (ret xs0 (start n0 xs0))
where -- ret :: [a] -> [a] -> [a]
ret (x:xs) (y:ys) = y `pseq` (x : ret xs ys)
ret xs _ = xs

-- start :: Int -> [a] -> [a]
start 0 ys = ys
start !_n [] = []
start !n (y:ys) = y `pseq` start (n-1) ys

-- | 'evalBuffer' is a rolling buffer strategy combinator for (lazy) lists.
-- Evaluation of the ith element induces evaluation of the (i+n)th element,
-- with the first n elements being evaluated immediately.
--
-- 'evalBuffer' is not as compositional as the type suggests. In fact,
-- it evaluates list elements at least to weak head normal form,
-- disregarding a strategy argument 'r0'.
--
-- > evalBuffer n r0 == evalBuffer n rseq
--
-- | 'evalBuffer' is a rolling buffer strategy combinator for lazy lists.
-- Pattern matching on the result of @evalBuffer n strat xs@ will evaluate the
-- first @n+1@ elements of @xs@ using @strat@. Pattern matching on each
-- additional list cons will evaluate an additional element using @strat@.
evalBuffer :: Int -> Strategy a -> Strategy [a]
evalBuffer n strat = evalBufferWHNF n . map (withStrategy strat)

-- Like evalBufferWHNF, but sparks the list elements when pushing them
-- into the buffer.
-- Not to be exported; used in parBuffer and for optimisation.
parBufferWHNF :: Int -> Strategy [a]
parBufferWHNF n0 xs0 = return (ret xs0 (start n0 xs0))
where -- ret :: [a] -> [a] -> [a]
ret (x:xs) (y:ys) = y `par` (x : ret xs ys)
ret xs _ = xs

-- start :: Int -> [a] -> [a]
start 0 ys = ys
start !_n [] = []
start !n (y:ys) = y `par` start (n-1) ys


-- | Like 'evalBuffer', but evaluates the list elements in parallel when
-- pushing them into the buffer.
-- Evaluation of the ith element induces parallel evaluation of the (i+n)th element,
-- with the first n elements being evaluated in parallel immediately.
--
-- > parBuffer n strat = evalBuffer n (rparWith strat)
evalBuffer n0 strat xs0 = return (ret tied (drop n0 tied))
where
-- This is the heart of the strategy. The idea is to tie the evaluation
-- of each cons (to WHNF) to the evaluation of its contents (according
-- to strat). Walking the spine of the result will thus perform
-- the requested Eval actions.
tied = foldr go [] xs0
where
go x r = runEval ((: r) <$> strat x)

ret (x : xs) (_y : ys) = x : ret xs ys
ret xs _ = xs

-- | 'parBuffer' is a rolling buffer strategy combinator for lazy lists.
-- Pattern matching on the result of @parBuffer n s xs@ sparks
-- computations to evaluate the first @n+1@ elements of @xs@ using the
-- strategy @s@. Pattern matching on each additional list cons will
-- spark an additional computation.
--
-- @parBuffer n strat = 'evalBuffer' n ('rparWith' strat)@
parBuffer :: Int -> Strategy a -> Strategy [a]
parBuffer n strat = parBufferWHNF n . map (withStrategy strat)
-- Alternative definition via evalBuffer (may compromise firing of RULES):
-- parBuffer n strat = evalBuffer n (rparWith strat)

-- Deforest the intermediate list in parBuffer/evalBuffer when it is
-- unnecessary:

{-# NOINLINE [1] evalBuffer #-}
{-# NOINLINE [1] parBuffer #-}
{-# RULES
"evalBuffer/rseq" forall n . evalBuffer n rseq = evalBufferWHNF n
"parBuffer/rseq" forall n . parBuffer n rseq = parBufferWHNF n
#-}
parBuffer n strat = evalBuffer n (rparWith strat)

-- --------------------------------------------------------------------------
-- Strategies for tuples
Expand Down