
WAM-CL: Common Lisp in Prolog - lispm
https://groups.google.com/forum/#!msg/comp.lang.prolog/85jyECdWTxc/l-yQ19kPAAAJ
======
fasquoika
The link to the main github page, for the curious:
[https://github.com/TeamSPoon/wam_common_lisp](https://github.com/TeamSPoon/wam_common_lisp)

Is SWI-Prolog really faster than CLisp? I had no idea. Prolog seems like a
language that would be pretty slow by default, but maybe you can do some
pretty novel optimizations

~~~
tom_mellior
> Is SWI-Prolog really faster than CLisp?

Naive Fibonacci isn't exactly representative. Especially not if you mess up
the implementation: As given, the Lisp version

    
    
        (defun fib (n) (if (<= (1- n) 0) n (the fixnum (+ (fib (- n 1)) (fib (- n 2))))))
    

computes 39088169 for (fib 38) (on my machine, in 64 seconds in CLisp),
whereas the hand-written Prolog version computes 63245986. Oops. Changing the
Lisp version to a version equivalent to the Prolog version:

    
    
        (defun fib (n) (if (<= n 1) 1 (the fixnum (+ (fib (- n 1)) (fib (- n 2))))))
    

computes the correct result. With this I get:

    
    
        [3]> (time (fib 38))
        Real time: 59.298958 sec.
        Run time: 59.3 sec.
        Space: 1011935760 Bytes
        GC: 1157, GC time: 1.168 sec.
        63245986
    

And on SWI-Prolog:

    
    
        ?- time(fibp2(38, O)).
        % 379,475,913 inferences, 20.021 CPU in 20.022 seconds (100% CPU, 18953864 Lips)
        O = 63245986.
    
        ?- statistics.
        % [...]
        % 33,858 garbage collections gained 2,529,839,696 bytes in 0.851 seconds.
    

Both allocate a whole lot of memory but (if the numbers are to be trusted) GC
is not the reason CLisp is so much slower. All the numbers involved here fit
well into SWI's range for tagged integers, so arithmetic on them should be
pretty efficient.

EDIT: You can further improve the CLisp version by removing the THE which was
presumably meant to aid optimization, but apparently didn't:

    
    
        [1]> (defun fib (n) (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
        FIB
        [2]> (time (fib 38))
        Real time: 42.21966 sec.
        Run time: 42.216 sec.
        Space: 0 Bytes
        63245986
    

That's more like it... (With the author's DECLAIM flags for maximum speed, I
get a further improvement of about 2 seconds, to 40 seconds. Launching SWI-
Prolog with -O, though, improves it in turn to 10 seconds, with only 1 GB
allocated instead of 2.5. Benchmarking is fun!)

~~~
kazinator
CLISP doesn't compile functions input at the REPL or loaded from source files
with LOAD. If you don't do (compile 'fib), you're testing AST interpretation,
not byte code.

~~~
tom_mellior
Ha, excellent point. Thanks.

~~~
tom_mellior
OK, so now we are ready to answer the great-great-grandparent's question:

> Is SWI-Prolog really faster than CLisp?

No. At least not on naive Fibonacci.

    
    
        [1]> (defun fib (n) (if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
        FIB
        [2]> (compile 'fib)
        FIB ;
        NIL ;
        NIL
        [3]> (time (fib 38))
        Real time: 6.730412 sec.
        Run time: 6.732 sec.
        Space: 0 Bytes
        63245986
    

The project's GitHub page makes pretty much all the mistakes you can make when
benchmarking: Comparing programs that are not equivalent and with wildly
uncomparable optimization settings.

There is an almost incomprehensible blurb at the end of
[https://github.com/TeamSPoon/wam_common_lisp](https://github.com/TeamSPoon/wam_common_lisp)
that (I think) tries to argue that you should _not_ turn on optimization in
Lisp because it costs more than you gain. I disagree.

~~~
zmonx
Thank you for these benchmarks!

For a fair comparison, one should however also take into account that SWI-
Prolog is among the slower Prolog systems. I therefore recommend to also use a
faster Prolog system.

For example, I used the following Prolog translation of your code and ran it
in GNU Prolog:

    
    
        n_fib(N0, F) :-
                (   N0 =< 1 -> F = 1
                ;   N1 is N0 - 1,
                    N2 is N0 - 2,
                    n_fib(N1, F1),
                    n_fib(N2, F2),
                    F is F1 + F2
                ).
    

On my machine configuration, GNU Prolog is more than _thrice as fast_ as SWI-
Prolog (even with -O) for:

    
    
        | ?- n_fib(38, F).
        
        F = 63245986
    

GNU Prolog in fact compiles to _native_ code. You can test this by putting the
code into a file, say fib.pl, and compiling it with the GNU Prolog compiler
using:

    
    
        $ gplc fib.pl
    

You can then run it with ./fib and invoke the above query.

------
flavio81
> _The main purpose is this impl is it to run prolog-in-lisp 1000x faster than
> the fastest lisps (like SBCL)_

This is very interesting. I thought that the prolog implementations done in
Common Lisp were fast!

So now you can have not only Prolog in Lisp, but _also_ Lisp in Prolog.
Wonderful.

~~~
fusiongyro
Here's a much older demo of a similar idea:

[https://www.metalevel.at/lisprolog/](https://www.metalevel.at/lisprolog/)

At 160 lines, it's short enough and readable enough to give a hint of the
kinds of things Prolog is good at.

