Google Groups Home
Help | Sign in
Message from discussion a potential lisp convert, and interpreting the shootout
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
Rahul Jain  
View profile
 More options Oct 3 2006, 1:47 pm
Newsgroups: comp.lang.lisp
From: Rahul Jain <rj...@nyct.net>
Date: Tue, 03 Oct 2006 13:47:17 -0400
Local: Tues, Oct 3 2006 1:47 pm
Subject: Re: a potential lisp convert, and interpreting the shootout

"Henry Bigelow" <hrbige...@gmail.com> writes:
> hi jon,

>> You may be interested in my ray tracer benchmarks:

>>   http://www.ffconsultancy.com/free/ray_tracer/languages.html

> thank you!  very enlightening.  i read the analysis.  i have a few
> questions about this excerpt

> "However, the designers of the ML family of languages (including OCaml
> and SML) deliberately avoided some of the functionality provided by
> Lisp in order to facilitate static type checking and improve
> performance."

> i guess i misunderstood something.  does lisp not have any type
> inference?  or does it have partial type inference if you explicitly
> declare the types for some variables and not others?

What do you mean by "Lisp"? The standard does not require type
inference, as it's merely a way to optimize code by eliding type
dispatches at run time and allowing the inlining of the implementation
of the operator for that specific type.

Lisp has a much richer type system than any of the MLs. CMUCL, for
example, can do type inference to determine whether the arcsin of a
value rounded off to the nearest integer will fit in a machine word or
whether it might need to have a bignum (MLs don't have bignums as part
of the language).

For example, if we compile the following:
(defun test (x y)
  (declare (type (integer 5 100) x)
           (type (integer 1 5) y))
  (expt x y))

CMUCL tells us (among other things):
Function: #<Function TEST {582F61C9}>
Function arguments:
  (x y)
Its defined argument types are:
  ((INTEGER 5 100) (INTEGER 1 5))
Its result type is:
  (INTEGER 5 10000000000)

Therefore, it has figured out that an integer from 5 to 100 raised to
the power of an integer from 1 to 5 gives us an integer from 5 to
10000000000. It can then use this information to determine whether to
return a boxed (with type information if the result can overflow a
register) or unboxed (raw value in a register) value.

As an exmaple of this, we can compile the following:
(defun test (x y)
  (declare (optimize speed (safety 0))
           (type (integer 5 1000000) x)
           (type (integer 1 5000000) y))
  (* x y))

and the compiler tells us:
; Note: Forced to do GENERIC-* (cost 30).
;     Unable to do inline fixnum arithmetic (cost 4) because:
;     The result is a (INTEGER 5 5000000000000), not a FIXNUM.
;     Unable to do inline (signed-byte 32) arithmetic (cost 5) because:
;     The result is a (INTEGER 5 5000000000000), not a (SIGNED-BYTE 32).
;     etc.

Delete a few zeroes from each of the upper bounds and the note goes
away, as the * can be inlined (in the dissasembly, we see:
      C9:       IMUL    EDX, EDI
instead of:
      7E:       CALL    #x100002D0           ; #x100002D0: GENERIC-*

This topic is VERY, VERY important to optimizing Lisp numeric code, so
be SURE to study it carefully.

--
Rahul Jain
rj...@nyct.net
Professional Software Developer, Amateur Quantum Mechanicist


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google