Why is GHC so much worse than JHC when computing the Ackermann function?

Christopher Done chrisdone at gmail.com
Sat Apr 20 12:08:01 CEST 2013


JHC compiles to C and last time I tried this it looked very much like the
original C version:
http://www.reddit.com/r/haskell/comments/1bcru7/damn_lies_and_haskell_performance/c9689a3

This is the same thing. Compile with --tdir=/tmp/ajhc and then cat
/tmp/ajhc/main_code.c. Output should be like this:

static uint32_t A_STD
fW$__fMain_1__ack(gc_t gc,uint32_t v105553376,uint32_t v61835120)
{
        if (0 == v105553376) {
            return 1 + v61835120;
        } else {
            uint32_t v16;
            uint32_t v22;
            struct tup1 x2;
            if (0 == v61835120) {
                uint32_t v228308038 = (v105553376 - 1);
                x2.t0 = v228308038;
                x2.t1 = 1;
            } else {
                uint32_t v110947990;
                uint32_t v215884490 = (v61835120 - 1);
                uint32_t v62470112 = (v105553376 - 1);
                v110947990 = fW$__fMain_1__ack(gc,v105553376,v215884490);
                x2.t0 = v62470112;
                x2.t1 = v110947990;
            }
            v22 = x2.t0;
            v16 = x2.t1;
            return fW$__fMain_1__ack(gc,v22,v16);
        }
}

And it's as fast as C on my machine:

chris at midnight:~/Projects/me/ajhc$ time ./ack
65533

real 0m2.134s
user 0m2.124s
sys 0m0.000s
chris at midnight:~/Projects/me/ajhc$ gcc -O3 ack.c -o ack-c
ack.c: In function ‘main’:
ack.c:8:3: warning: incompatible implicit declaration of built-in function
‘printf’ [enabled by default]
chris at midnight:~/Projects/me/ajhc$ time ./ack-c
65533

real 0m2.255s
user 0m2.248s
sys 0m0.000s
chris at midnight:~/Projects/me/ajhc$




On 20 April 2013 10:55, Mikhail Glushenkov <the.dead.shall.rise at gmail.com>wrote:

> Hi all,
>
> This came up on StackOverflow [1]. When compiled with GHC (7.4.2 &
> 7.6.2), this simple program:
>
> main = print $ ack 4 1
>   where ack :: Int -> Int -> Int
>         ack 0 n = n+1
>         ack m 0 = ack (m-1) 1
>         ack m n = ack (m-1) (ack m (n-1))
>
> consumes all available memory on my machine and slows down to a crawl.
> However, when compiled with JHC it runs in constant space and is about
> as fast as the straightforward Ocaml version (see the SO question for
> benchmark numbers).
>
> I was able to fix the space leak by using CPS-conversion, but the
> CPS-converted version is still about 10 times slower than the naive
> version compiled with JHC.
>
> I looked both at the Core and Cmm, but couldn't find anything
> obviously wrong with the generated code - 'ack' is compiled to a
> simple loop of type 'Int# -> Int# -> Int#'. What's more frustrating is
> that running the program with +RTS -hc makes the space leak
> mysteriously vanish.
>
> Can someone please explain where the space leak comes from and if it's
> possible to further improve the runtime of this program with GHC?
> Apparently it's somehow connected to the stack management strategy,
> since running the program with a larger stack chunk size (+RTS -kc1M)
> makes the space leak go away. Interestingly, choosing smaller stack
> chunk sizes (256K, 512K) causes it to die with an OOM exception:
>
> $ time ./Test +RTS -kc256K
> Test: out of memory (requested 2097152 bytes)
>
>
> [1]
> http://stackoverflow.com/questions/16115815/ackermann-very-inefficient-with-haskell-ghc/16116074#16116074
>
> --
> ()  ascii ribbon campaign - against html e-mail
> /\  www.asciiribbon.org   - against proprietary attachments
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/glasgow-haskell-users/attachments/20130420/6e49b595/attachment.htm>


More information about the Glasgow-haskell-users mailing list