Opened 9 years ago

Closed 8 years ago

Last modified 8 years ago

#5234 closed bug (worksforme)

The parListWHNF optimisation isn't

Reported by: duncan Owned by: simonmar
Priority: high Milestone: 7.4.1
Component: libraries (other) Version: 7.1
Keywords: Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s):
Wiki Page:


In Control.Parallel.Strategies there is:

parListWHNF :: Strategy [a]
parListWHNF xs = go xs `pseq` return xs
  where -- go :: [a] -> [a]
           go []     = []
           go (y:ys) = y `par` go ys

Plus a rule:

{-# RULES 
 "parList/rseq" parList rseq = parListWHNF

However this rule never fires because both parList and rseq get inlined too early (they have no INLINE [n] pragma).

This makes a difference because parListWHNF really is better than parList rseq. Consider this trivial test program:

main =
  let xs = [0..100000] `using` parListWHNF
   in print (sum xs)

This correctly generates 100001 dud sparks. They are all dud because all the elements of [0..100000] are already evaluated.

However if we use the same program with parList rseq then we get 100001 converted (but obviously rather trivial) sparks. This is less good (it runs at half the speed) because it pushes all these sparks through the spark pool, rather than not bothering to put them in the spark pool in the first place.

Change History (5)

comment:1 Changed 9 years ago by duncan

I've not checked, but I'd be very suspicious of the RULE for evalBufferWHNF too. I bet it never fires, again because the things it matches on have nothing to prevent them from being inlined too early.

comment:2 Changed 9 years ago by simonpj

Milestone: 7.2.1
Owner: set to simonmar
Priority: normalhigh

Simon, you know what's going on here. Shouldn't be hard to fix.


comment:3 Changed 8 years ago by igloo


comment:4 Changed 8 years ago by simonmar

Resolution: worksforme
Status: newclosed

Seems to work with 7.0.3, 7.2.1, and with HEAD:

$ ghc-7.2.1 -ddump-rule-firings -O2 parlist.hs -threaded -fforce-recomp -rtsopts      
[1 of 1] Compiling Main             ( parlist.hs, parlist.o )
Rule fired: Class op enumFromTo
Rule fired: parList/rseq
Rule fired: SPEC Data.List.sum
Rule fired: Class op show
Rule fired: enumDeltaToInteger
Rule fired: >=#
Linking parlist ...

I've checked that we get the dud sparks as required, and the parBuffer rule also works.

comment:5 Changed 8 years ago by duncan

Note that it is still not robust to abstraction without the INLINE pragma. I think I've hear Roman say before that GHC should just warn if any name mentioned on the LHS of a rule does not have an INLINE [x] pragma.

Note: See TracTickets for help on using tickets.