"Janos G. Hajagos" <[EMAIL PROTECTED]> writes:
> Harvey,
>
> Check out this post from Bill Clementson on optimizing lisp code for
> the Coyote Gulch problem:
>
> http://home.comcast.net/~bc19191/blog/040308.html
>
> Richard Fateman has an excellent paper on numeric programming in
> lisp:
>
> http://http.cs.berkeley.edu/~fateman/papers/lispfloat.ps
>
> Your friend for optimizing numeric code is the disassemble
> function. This will give you a clue of what the compiler is doing.
I've read Fateman's paper before, but I missed the Coyote Gulch
discussion. I just finished reading it, but was a little surprised at
the approach taken.
For example, why were macros used to convert things like:
(* a b)
to
(the 'double-float (* (the 'double-float a) (the 'double-float b)))?
Shouldn't it have been sufficient to specify the types of all the
variables? Potentially ranges would have to be used, to constrain
inputs to the math functions so that the outputs are known to be
double-floats (instead of complex), but I would have thought that this
would suffice, and I think Fateman's paper supports this view.
So I did a little test. Consider:
(eval-when (compile)
(proclaim '(optimize (speed 3) (safety 1) (space 0) (debug 0))))
(defun sumn (n)
(declare (type (integer 0 10000) n))
(let ((s 0))
(dotimes (i n)
(incf s i))
s))
in test1.lisp
Compiling yields the following 4 notes:
In: DEFUN SUMN
(INCF S I)
--> LET*
==>
(+ S I)
Note: Unable to optimize due to type uncertainty:
The first argument is a NUMBER, not a FLOAT.
Note: Unable to optimize due to type uncertainty:
The first argument is a NUMBER, not a (COMPLEX SINGLE-FLOAT).
Note: Unable to optimize due to type uncertainty:
The first argument is a NUMBER, not a (COMPLEX DOUBLE-FLOAT).
Note: Forced to do GENERIC-+ (cost 10).
Unable to do inline fixnum arithmetic (cost 2) because:
The first argument is a NUMBER, not a FIXNUM.
The result is a NUMBER, not a FIXNUM.
Unable to do inline (signed-byte 32) arithmetic (cost 5) because:
The first argument is a NUMBER, not a (SIGNED-BYTE 32).
The result is a NUMBER, not a (SIGNED-BYTE 32).
etc.
Byte Compiling Top-Level Form:
Compilation unit finished.
4 notes
I was surprised that the compiler doesn't figure out that s is a fixnum
as well, given that I start off by assigning it to zero, and only add
fixnums to it, but in retrospect, to do be completely correct, the
compiler would have to sum the series to be able to safely deduce
this, so of course it won't.
Added a declaration after the definition of s helps. The following
doesn't generate any notes:
(defun sumn (n)
(declare (type (integer 0 10000) n))
(let ((s 0))
(declare (type (integer 0 200000000) s))
(dotimes (i n)
(incf s i))
s))
So far, so good. However, before running to try this in my code, I
wanted to see what would happen if I tried to make a double-float
version of sumn:
(defun sumn (n)
(declare (type (integer 0 10000) n)
(values double-float))
(let ((s 0d0))
(declare (type double-float s))
(dotimes (i n)
(incf s i))
s))
Surprisingly, now I get a compiler note:
Python version 1.0, VM version Intel x86 on 14 DEC 04 03:41:24 pm.
Compiling: /home/hjstein/test/test1.lisp 14 DEC 04 03:41:21 pm
Converted SUMN.
Compiling DEFUN SUMN:
File: /home/hjstein/test/test1.lisp
In: DEFUN SUMN
(DEFUN SUMN (N)
(DECLARE (TYPE # N) (VALUES DOUBLE-FLOAT))
(LET (#)
(DECLARE #)
(DOTIMES # #) ..))
Note: Doing float to pointer coercion (cost 13) from S to "<return value>".
Byte Compiling Top-Level Form:
Compilation unit finished.
1 note
Why do I get no notes on the fixnum version, but get a cost 13 float
to pointer coercion in the double-float version?
--
Harvey Stein
Bloomberg LP
[EMAIL PROTECTED]