Opened 8 years ago

Closed 8 years ago

#5535 closed bug (wontfix)

Performance regression vs. 7.2.1

Reported by: simonmar Owned by: igloo
Priority: highest Milestone: 7.4.1
Component: Compiler Version: 7.2.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:

Description

nofib/spectral/mandel is showing a regression since 7.2.1.

Create a larger test input:

$ cat >mandel.in
-2.0
-2.0
2.0
2.0
512
512
256

With today's 7.3:

$ ./mandel <mandel.in +RTS -s >/dev/null
Enter min x  = Enter min y  = Enter max x  = Enter max y  = Screen width = Screen height= Screen depth =    3,517,780,112 bytes allocated in the heap
      21,178,480 bytes copied during GC
          98,960 bytes maximum residency (19 sample(s))
          42,640 bytes maximum slop
               2 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0      6736 colls,     0 par    0.11s    0.11s     0.0000s    0.0002s
  Gen  1        19 colls,     0 par    0.00s    0.00s     0.0001s    0.0003s

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    2.92s  (  2.92s elapsed)
  GC      time    0.11s  (  0.11s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time    3.03s  (  3.03s elapsed)

With 7.2.1:

$ ./mandel <mandel.in +RTS -s >/dev/null
Enter min x  = Enter min y  = Enter max x  = Enter max y  = Screen width = Screen height= Screen depth =    2,554,096,496 bytes allocated in the heap
      16,583,464 bytes copied during GC
          98,928 bytes maximum residency (16 sample(s))
          44,216 bytes maximum slop
               2 MB total memory in use (0 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0      4919 colls,     0 par    0.08s    0.08s     0.0000s    0.0002s
  Gen  1        16 colls,     0 par    0.00s    0.00s     0.0001s    0.0003s

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    2.29s  (  2.29s elapsed)
  GC      time    0.08s  (  0.08s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time    2.37s  (  2.37s elapsed)

Both were standard builds (GhcLibOpts contains -O2), and the programs themselves were compiled with -O2.

Change History (6)

comment:1 Changed 8 years ago by igloo

Owner: set to igloo

comment:2 Changed 8 years ago by igloo

difficulty: Unknown

OK, I think the essence of the problem is here:

{-# LANGUAGE MagicHash, UnboxedTuples #-}

module Q (whenDiverge) where

import GHC.Base
import GHC.Integer

whenDiverge :: Int -> Int -> Double -> Bool
whenDiverge limit radius d
  = walkIt (replicate limit d)
  where
     walkIt []              = True
     walkIt (x : _)
        | diverge x radius  = True
        | otherwise         = False

diverge :: Double -> Int -> Bool
diverge d radius = exponentDouble d > radius

exponentDouble :: Double -> Int
exponentDouble x = case decodeDouble x of
                   (m,n) -> if m == (0 :: Integer)
                            then (0 :: Int)
                            else n + floatDigits x

decodeDouble :: Double -> (Integer, Int)
decodeDouble (D# x#) = case decodeDoubleInteger x# of
                       (# i, j #) -> (i, I# j)

When compiled with 7.2.1 -O2, the two top-level functions (whenDiverge and its wrapper) have Caf=NoCafRefs. When compiled with HEAD, they don't. It looks like the problem is the (0 :: Integer) literal, which under the hood uses GHC.Integer.Type.mkInteger, which calls negateInteger, which has a CAF for the (minBound :: Int) case.

So I changed it not to use a CAF:

-negateInteger (S# INT_MINBOUND) = NEG_INT_MINBOUND
+negateInteger i@(S# INT_MINBOUND) = negateInteger (toBig i)

and now negateInteger and mkInteger have HasNoCafRefs in the GHC.Integer.Type interface file, but whenDiverge still doesn't have it.

Simon, any idea what's going wrong please?

comment:3 Changed 8 years ago by igloo

Oh, I was missing the obvious: The integer constant itself is now being turned into a CAF.

comment:4 Changed 8 years ago by simonpj

So why does that matter (for execution time)?

comment:5 Changed 8 years ago by igloo

Hmm, looks like it was a red herring.

comment:6 Changed 8 years ago by igloo

Resolution: wontfix
Status: newclosed

OK, in the end I don't think there's anything bad actually going wrong here. ticky shows that we now call a number of integer-gmp functions a lot, but that's to be expected as we no longer inline them (and we can't inline them, because that can cause code size explosion).

Note: See TracTickets for help on using tickets.