Newsgroups: comp.lang.lisp
Path: cantaloupe.srv.cs.cmu.edu!das-news.harvard.edu!news2.near.net!noc.near.net!MathWorks.Com!europa.eng.gtefsd.com!howland.reston.ans.net!swrinde!pipex!lyra.csx.cam.ac.uk!warwick!uknet!festival!edcogsci!jeff
From: jeff@aiai.ed.ac.uk (Jeff Dalton)
Subject: Re: AKCL: declare makes it worse??
Message-ID: <Cw4s0M.32C@cogsci.ed.ac.uk>
Sender: usenet@cogsci.ed.ac.uk (C News Software)
Nntp-Posting-Host: bute.aiai.ed.ac.uk
Organization: AIAI, University of Edinburgh, Scotland
References: <353d7k$h7n@coils.cims.nyu.edu>
Date: Wed, 14 Sep 1994 17:45:58 GMT
Lines: 82

In article <353d7k$h7n@coils.cims.nyu.edu> mconnell@coils.cims.nyu.edu (Mark McConnell) writes:
>
>I just ran some experiments to see how the Austin Kyoto Common Lisp
>(AKCL) compiler would handle declarations.  I used programs which do a
>lot of addition of fixnums modulo a small integer p.  Surprisingly,
>declaring the numbers to be fixnums make the compiled code run 17%
>slower.
>==========
>Even if you tell the compiler that A and B are fixnums, it can't be
>sure that A+B will be a fixnum.  

You should say (the fixnum (+ ...)).

>       Therefore, I redid the experiment by
>replacing the variable p with 2 throughout the code (removing it from
>argument lists where necessary), and declaring the numbers to be (mod
>2).  Version 2 of the program became version 2', as follows:
>
>(proclaim '(optimize (speed 3)))
>(proclaim '(inline pascal-aux2)) ; doesn't matter much if either
>                                 ; auxiliary is inline?
>
>(defun pascal (n)
>  (pascal-aux n '(1)))
>
>(defun pascal-aux (n ans)
>  (declare (type fixnum n))
>  (if (zerop n)
>      ans
>    (pascal-aux (1- n) (pascal-aux2 ans '(1)))))
>
>(defun pascal-aux2 (in out)
>  (if (null (cdr in))
>      (cons 1 out)
>    (pascal-aux2 (cdr in)
>		 (cons (mod (+ (the (mod 2) (car in))
>			       (the (mod 2) (cadr in)))
>			    2)
>		       out))))
>
>Version 1' is the same as version 2', but with no declarations or
>proclamations.  Version 1' ran almost exactly as fast as version 1:
>359.8 secs.  Version 2' was only a hair faster than version 2, at
>414.8 secs (versus 420.4).  Version 1' still beats version 2'.
>
>==========
>
>Does anyone know what is going on?  Is there are better way to do
>these declarations?  Or does this simply reflect an idiosyncracy in
>the compiler?  Do other compilers, such as CMU CL, have the same
>property?

When you declare a variable to be of type fixnum in KCL, it will
prbably be stored in a C int as an actual int.  Normally, fixnums
are allocated on the heap inside some stuff that says they're
fixnums.  This is sometimes called being "boxed", perhaps from
the way list are sometimes diagrammed using boxes and arrows.

Declaring the var to be a fixnum changes the way it's
stored so that you don't have to repeatedly extract it from
the heap structure.  On the other hand, if you need the heap
version it has to be constructed.  So that's happening when
you call pascal-aux2 from pascal-aux.

Within pascal-aux2, you're doing + and mod without any declarations
to say fixnums are involved.  So you don't get any compensating
speedup for the slowdowns introduced as described above.

I'm not sure that's all there is to it, but it's pretty easy for
you to see what KCL's doing by calling disassemble on a fn that's
not compiled.

In some Common Lisps, you could do better by making the aux
functions local functions defined by LABELS and declaring their
type or by having a top-level PROCLAIM that gave their type
(w/o making them local functions).  Either of these might
eliminate the need to convert fixnums stored as ints to their
"boxed" heap forms when calling one of the functions so defined.

I'm not sure how much AKCL does with that kind of thing these days.

-- jeff
