module Data.Vector.Strategies
( parVector
-- * Re-exported for convenience
, NFData, using
) where
import Control.DeepSeq (NFData)
import Control.Parallel.Strategies
import qualified Data.Vector as V
-- |Evaluate the elements of a boxed vector in parallel.
--
-- The vector will be divided up into chunks of length less than or
-- equal to the provided chunk size (first argument) and each chunk
-- of elements will be sparked off for evaluation.
--
-- Use this along with the "parallel" package's 'using' function:
--
-- @
-- vec `using` (parVector chunkSize)
-- @
--
-- This is not useful on unboxed vectors (will not provide any performance increase)
parVector :: NFData a => Int -> Strategy (V.Vector a)
parVector minChunk vector
| minChunk <= 0 = parVector 1 vector
| otherwise = go vector
where
go vec =
let vLen = V.length vec
half = vLen `div` 2
in if vLen > minChunk
then do
go (V.unsafeSlice 0 half vec)
go (V.unsafeSlice half (vLen - half) vec)
return vec
else evalChunk (vLen-1) >> return vec
where
evalChunk (-1) = return vec
evalChunk i = rpar (rdeepseq (vec V.! i)) >> evalChunk (i-1)