[GHC] #15488: GHC takes up huge amount of memory when compiling accelerate 1.2.0

GHC ghc-devs at haskell.org
Wed Sep 26 13:26:00 UTC 2018


#15488: GHC takes up huge amount of memory when compiling accelerate 1.2.0
-------------------------------------+-------------------------------------
        Reporter:  noah              |                Owner:  tdammers
            Type:  bug               |               Status:  new
        Priority:  high              |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.4.3
      Resolution:                    |             Keywords:
                                     |  accelerate,memory,compile
Operating System:  Linux             |         Architecture:  x86_64
                                     |  (amd64)
 Type of failure:  Compile-time      |            Test Case:  accelerate
  performance bug                    |  1.2.0
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 > So AFAICT, this isn't case-of-case being overly eager, it's just GHC
 obediently honoring those `INLINE` pragmas, which legit produces a lot of
 Core

 Yes you are right about that.

 * But why did it not happen in earlier versions of GHC, which should have
 been equally obedient?

 I'm worried that this kind of blow-up can happen even without INLINE
 pragmas:
 {{{
 f1 x = if x>0 then 0 else 1
 f2 x = if x>0 then f1 (x-1) else f1 (x-2)
 f3 x = if x>0 then f2 (x-1) else f2 (x-2)
 f4 x = if x>0 then f3 (x-1) else f3 (x-2)
 h x = f x
 }}}
 Now
 * `f4` looks small, so we could inline it at its call in `h`
 * Now we have two calls to `f3`; but `f3` is small so we can inline them
 both.
 * Now we have four calls to `f2`; but `f2` is small so we can inline them
 all.
 ...and so on.

 This happens if we inline "bottom up".  If instead we did "top-down" we
 might inline `f1` into `f2`, and `f2` into `f3`... but then `f3` would
 look big so we would not inline it into `f4`.  But we are clearly walking
 close to the precipice.

 Who writes such function nests?  Well, `accelerate` perhaps (but see the
 above question).  But they ''also'' arise naturally from the
 join points created from deeply-nested case-of-case transforms, and that's
 the relevance of the case-of-case stuff.

 So we have two threads to pursue
 * Why does `accelerate` have INLINE pragmas on these nested functions?
 Obedience to those pragmas will certainly cause trouble.
 * How can we avoid blow-up when (absent INLINE pragmas) such definition
 nests occur naturally?  This is the thing I've been thinking about.

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


More information about the ghc-tickets mailing list