[GHC] #3259: A module-local combinator using Control.Parallel.par behaves differently than when it's imported

GHC trac at galois.com
Tue May 26 12:25:02 EDT 2009


#3259: A module-local combinator using Control.Parallel.par behaves differently
than when it's imported
-------------------------+--------------------------------------------------
    Reporter:  blamario  |        Owner:         
        Type:  bug       |       Status:  new    
    Priority:  normal    |    Milestone:         
   Component:  Compiler  |      Version:  6.11   
    Severity:  normal    |   Resolution:         
    Keywords:            |   Difficulty:  Unknown
    Testcase:            |           Os:  Linux  
Architecture:  x86       |  
-------------------------+--------------------------------------------------
Changes (by simonpj):

  * difficulty:  => Unknown

Old description:

> There's a moderately long thread at haskell-cafe discussing the problem at:
>
> http://www.haskell.org/pipermail/haskell-cafe/2009-May/061765.html
>
> I will attach the source files and the outputs of compilation with
>
> ghc-6.11.20090421 --make primes-test.hs -threaded -O2 -ddump-simpl
>
> on a 32-bit Ubuntu 2009.4.
>
> What appears to be happening is that GHC generates the call to function
> `parallelize' as though it was strict, even though the interface declares
> it as lazy, but only when the function is imported.
>
> The only proof of this, apart from the execution time, is this line of
> difference between the two -ddump-simpl outputs:
>
> > $diff main.simpl imported.simpl
> > ...
> > 223c232
> > < a_s1rs [ALWAYS Just L] :: GHC.Integer.Internals.Integer
> > ---
> > > a_s1sV [ALWAYS Just S] :: GHC.Integer.Internals.Integer
> > ...

New description:

 There's a moderately long thread at haskell-cafe discussing the problem at:

 http://www.haskell.org/pipermail/haskell-cafe/2009-May/061765.html

 I will attach the source files and the outputs of compilation with
 {{{
 ghc-6.11.20090421 --make primes-test.hs -threaded -O2 -ddump-simpl
 }}}
 on a 32-bit Ubuntu 2009.4.

 What appears to be happening is that GHC generates the call to function
 `parallelize' as though it was strict, even though the interface declares
 it as lazy, but only when the function is imported.

 The only proof of this, apart from the execution time, is this line of
 difference between the two -ddump-simpl outputs:
 {{{
 > $diff main.simpl imported.simpl
 > ...
 > 223c232
 > < a_s1rs [ALWAYS Just L] :: GHC.Integer.Internals.Integer
 > ---
 > > a_s1sV [ALWAYS Just S] :: GHC.Integer.Internals.Integer
 > ...
 }}}

Comment:

 Well diagnosed!  Your report reveals quite a long-standing and serious
 but, so thank you!  It'll generate nasty, insidious loss of parallelism.

 Here's brain dump of what is going on, just to record it for posterity.
 `par` is defined in `GHC.Conc` thus:
 {{{
 {-# INLINE par  #-}
 par :: a -> b -> b
 par  x y = case (par# x) of { _ -> lazy y }

 -- The reason for the strange "lazy" call is that
 -- it fools the compiler into thinking that pseq  and par are non-strict
 in
 -- their second argument (even if it inlines pseq/par at the call site).
 -- If it thinks par is strict in "y", then it often evaluates
 -- "y" before "x", which is totally wrong.
 }}}

 The function `lazy` is the identity function, but it is inlined only after
 strictness analysis, and (via some magic) pretends to be lazy.  Hence
 `par` pretends to be lazy too.

 The trouble is that both `par` and `lazy` are inlined into your definition
 of `parallelise`, so that the unfolding for `parallelise` (exposed in
 `Parallelise.hi`) does not use `lazy` at all.  Then when compiling `Main`,
 `parallelise` is in turn inlined (before strictness analysis), and so the
 strictness analyser sees too much.

 This was all sloppy thinking on my part. Inlining `lazy` after strictness
 analysis works fine for the ''current'' module, but not for ''importing''
 modules.   My proposed fix is to inline `lazy` only at the very, very end,
 and in particular ''after'' any unfoldings have been exposed in an
 interface file.  That might mean that we lose some optimisations, but I
 don't think it'll make much difference.

 However, I'm going to leave this until Simon M gets back from holiday to
 discuss.

 Simon

-- 
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/3259#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the Glasgow-haskell-bugs mailing list