ParTraversable without creating sparks

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 parListtoparTraversable

x  = product (xs `using` parTraversable rseq)

no sparks are created:

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

If I change rseqto 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 overflow, 0 dud, 0 GC'd, 0 fizzled)

I use parallel-3.2.1.1 and in the source code parListis defined using parTraversable!

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

What am I missing?

+4
source share
1 answer

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

Strategies.hs RULES , parList rseq. , , parTraversable ( , , ). parallel: https://github.com/haskell/parallel/issues

, , 505 :

-- 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
 #-}
+5

Source: https://habr.com/ru/post/1687051/


All Articles