parTraversable not creating any sparks

Viewed 92

When I run this program with -s:

module Main where

import Control.Parallel.Strategies

main :: IO ()
main = do let xs = take 1000 $ product . take 1000 . repeat <$> [1..]
              x  = product (xs `using` parList rseq)
          putStrLn (show x)

Sparks are created:

SPARKS: 1000 (993 converted, 0 overflowed, 0 dud, 6 GC'd, 1 fizzled)

If I change parList to parTraversable

x  = product (xs `using` parTraversable rseq)

no sparks are created:

SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

If I change rseq to rdeepseq:

main = do let xs = (take 1000 $ product . take 1000 . repeat <$> [1..]) :: [Integer]
              x  = product (xs `using` parList rdeepseq)
          putStrLn (show x)

No sparks are created

SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

I am using parallel-3.2.1.1 and in the source code, parList is defined using parTraversable !

parList :: Strategy a -> Strategy [a]
parList = parTraversable

What am I missing?

1 Answers

I can reproduce your behaviour (ghc-8.2.1, parallel-3.2.1.1).

Later on down the Strategies.hs is a RULES pragma that special-cases parList rseq. I guess it is a bug that it has different behaviour to parTraversable (I don't know enough about the internals to be sure where the bug lies). I'd suggest filing a ticket at the parallel issue tracker: https://github.com/haskell/parallel/issues

Here is the code in question, starting at line 505 of the file:

-- Non-compositional version of 'parList', evaluating list elements
-- to weak head normal form.
-- Not to be exported; used for optimisation.

-- | DEPRECATED: use @'parList' 'rseq'@ instead
parListWHNF :: Strategy [a]
parListWHNF xs = go xs `pseq` return xs
  where -- go :: [a] -> [a]
           go []     = []
           go (y:ys) = y `par` go ys

-- The non-compositional 'parListWHNF' might be more efficient than its
-- more compositional counterpart; use RULES to do the specialisation.

{-# NOINLINE [1] parList #-}
{-# NOINLINE [1] rseq #-}
{-# RULES
 "parList/rseq" parList rseq = parListWHNF
 #-}
Related