[GHC] #15333: Weird cachegrind results for binary-trees
GHC
ghc-devs at haskell.org
Mon Jul 2 15:13:28 UTC 2018
#15333: Weird cachegrind results for binary-trees
-------------------------------------+-------------------------------------
Reporter: sgraf | Owner: (none)
Type: bug | Status: new
Priority: normal | Milestone: Research needed
Component: NoFib | Version: 8.5
benchmark suite |
Keywords: | Operating System: Unknown/Multiple
Architecture: | Type of failure: None/Unknown
Unknown/Multiple |
Test Case: | Blocked By:
Blocking: | Related Tickets:
Differential Rev(s): | Wiki Page:
-------------------------------------+-------------------------------------
I'm currently investigating an alleged regression in my branch of the late
lambda lift and hit a confusing data point. Note that I'm very much
relying on cachegrinds counted instructions/memory accesses for my
findings.
Check out the most recent version of `nofib` and run the following script:
{{{#!sh
#! /usr/bin/env zsh
sed -i 's/import Debug.Trace//g' Main.hs # Make the following line
idempotent
echo "import Debug.Trace" | cat - Main.hs > Main.tmp && mv Main.tmp
Main.hs # add the import for trace
sed -i 's/trace "" \$ bit/bit/g' Main.hs # strip `trace $ ` prefixes in
the call to `bit`
ghc -O2 -XBangPatterns Main.hs -o bt1
sed -i 's/bit/trace "" $ bit/g' Main.hs # prepend `trace $ ` to the call
to `bit`
ghc -O2 -XBangPatterns Main.hs -o bt2
valgrind --tool=cachegrind ./bt1 12 2>&1 > /dev/null # without trace
valgrind --tool=cachegrind ./bt2 12 2>&1 > /dev/null # with trace
}}}
This will compile two versions of `binary-trees`, one with an extra `trace
"" $` call before the only call to the `bit` function. One would expect
the version with the `trace` call (`bt1`) to allocate more than the
version without (`bt2`). Indeed, the output of `+RTS -s` suggests that:
{{{
$ ./bt1 12 +RTS -s
...
43,107,560 bytes allocated in the heap
...
$ ./bt2 12 +RTS -s
...
43,116,888 bytes allocated in the heap
...
}}}
That's fine. A few benchmark runs by hand also suggested the tracing
version is a little slower (probably due to IO).
Compare that to the output of the above cachegrind calls:
{{{
$ valgrind --tool=cachegrind ./bt1 12 > /dev/null
...
I refs: 118,697,583
...
D refs: 43,475,212
...
$ valgrind --tool=cachegrind ./bt2 12 > /dev/null
...
I refs: 116,340,710
...
D refs: 42,523,369
...
}}}
It's the other way round here! How's that possible?
Even if this isn't strictly a bug in GHC or NoFib, it's relevant
nonetheless, as our benchmark infrastructure currently relies on
instruction counts. I couldn't reproduce this by writing my own no-op
`trace _ a = a; {-# NOINLINE trace #-}`, btw.
I checked this on GHC 8.2.2 and a semi-recent HEAD commit
(bb539cfe335eeec7989332b859b1f3162c5e105a).
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15333>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list