Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit be2398b

Browse files
treeowlkonsumlamm
andauthored
Chunk better (#45)
`parListChunk` previously split a list up into chunks, applied the given strategy to each chunk, and then put them all together again. This led to two extra copies of the list. We get very little benefit from actually splitting the list, because the parallel computations need to traverse their part anyway; we can instead just hand off the whole list and let them count out their chunk. We count each chunk twice, but that shouldn't cost enough to matter. Now that `Eval` has a `MonadFix` instance, we can avoid actually having to put together lists at the end; instead, we pass each parallel computation the (as-yet-uncomputed) result of calculating the rest of the list. --------- Co-authored-by: konsumlamm <[email protected]>
1 parent 350e513 commit be2398b

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

Control/Parallel/Strategies.hs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{-# LANGUAGE BangPatterns, CPP, MagicHash, UnboxedTuples #-}
22
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
3+
{-# LANGUAGE RecursiveDo #-}
34
-----------------------------------------------------------------------------
45
-- |
56
-- Module : Control.Parallel.Strategies
@@ -592,20 +593,35 @@ parListNth n strat = evalListNth n (rparWith strat)
592593
-- | Divides a list into chunks, and applies the strategy
593594
-- @'evalList' strat@ to each chunk in parallel.
594595
--
595-
-- It is expected that this function will be replaced by a more
596-
-- generic clustering infrastructure in the future.
597-
--
598596
-- If the chunk size is 1 or less, 'parListChunk' is equivalent to
599597
-- 'parList'
600598
--
599+
-- This function may be replaced by a more
600+
-- generic clustering infrastructure in the future.
601601
parListChunk :: Int -> Strategy a -> Strategy [a]
602-
parListChunk n strat xs
603-
| n <= 1 = parList strat xs
604-
| otherwise = concat `fmap` parList (evalList strat) (chunk n xs)
605-
606-
chunk :: Int -> [a] -> [[a]]
607-
chunk _ [] = []
608-
chunk n xs = as : chunk n bs where (as,bs) = splitAt n xs
602+
parListChunk n strat
603+
| n <= 1 = parList strat
604+
| otherwise = go
605+
where
606+
go [] = pure []
607+
go as = mdo
608+
-- Calculate the first chunk in parallel, passing it the result
609+
-- of calculating the rest
610+
bs <- rpar $ runEval $ evalChunk strat more n as
611+
612+
-- Calculate the rest
613+
more <- go (drop n as)
614+
return bs
615+
616+
-- | @evalChunk strat end n as@ uses @strat@ to evaluate the first @n@
617+
-- elements of @as@ (ignoring the rest) and appends @end@ to the result.
618+
evalChunk :: Strategy a -> [a] -> Int -> Strategy [a]
619+
evalChunk strat = \end ->
620+
let
621+
go !_n [] = pure end
622+
go 0 _ = pure end
623+
go n (a:as) = (:) <$> strat a <*> go (n - 1) as
624+
in go
609625

610626
-- --------------------------------------------------------------------------
611627
-- Convenience

0 commit comments

Comments
 (0)