[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