Richard Heathfield said:
In <
[email protected]>, Nicolas
Neuss wrote:
[...]
If one uses a good Common Lisp implementation (especially one which
compiles to native code, as e.g. CMUCL/SBCL, Allegro CL, or
Lispworks), fI would expect that for most code the results for
equivalent code are not worse than C by a factor of 2 or maybe 3.
<cough, splutter> Er, okay, I think I'll put Lisp back on the shelf.
Look, it isn't dirty or anything. Thanks for your time, but I was
looking for something a little sportier. I mean, I knew it would be
slower, but a factor of TWO?
Please note my wording of "equivalent code". This arises when you have
some C program and want to do the same thing with Common Lisp. The
picture changes if you turn to tasks which exploit the dynamicity of
Lisp, and can not easily be done in C.
As an example consider the task of reading function definitions from a
file which are then evaluated many times in a numerical procedure (say
integration). In CL, this can be done by
1. reading the expression from a stream,
2. using the infix package for converting it to list syntax (if it
should be already in Lisp syntax you don't need the infix package,
but can simply use the standard CL read function),
3. compiling the function (the compiler is available also at runtime),
4. and then using that compiled function within the integration routine.
And the following piece of code does precisely that:
(in-package :cl-user)
(require :infix)
(defun integrate (f a b n)
(declare (type double-float a b)
(type fixnum n)
(type (function (double-float) double-float) f))
(let ((h (float (/ (- b a) n) 1.0d0)))
(declare (type double-float h))
(declare (optimize speed))
(* h (loop repeat n
for x of-type double-float from a by h sum
(funcall f x) of-type double-float))))
(defun integrate-input (a b n &key (stream *standard-input*))
(loop for input = (read-line stream nil)
while (and input (string/= input ""))
for source = `(lambda (x)
(declare (type double-float x)
(optimize speed))
,(infix:string->prefix input))
do
(format t "integral(~A,~F,~F)=~F~%" input a b
(integrate (compile nil source) a b n))))
You could interactively use it as follows:
(integrate-input 0.0 1.0 10000000) <-- user input
x^^3 <-- user input
[some compilation output which could be suppressed]
integral(x^^3,0.0,1.0)=0.24999994987310878 <-- output
cos(x)*exp(pi*x) <-- user input
[some compilation output which could be suppressed]
integral(cos(x)*exp(pi*x),0.0,1.0)=5.116088668778863 <-- output
And using a CL implementation which generates native code, e.g. SBCL,
every answer is calculated really fast, because optimized machine code
was used.
Maybe you could do similar things with C in a non-standard way by
dynamical linking with freshly compiled binary code. But in CL, this
whole process of reading and compiling a piece of code is standard and
reasonably fast. Therefore, also calling the above function on a batch
file containing very many function definitions would be reasonably fast.
So, in conclusion, if you could provide an equivalent code in C (please
try!), I think that I could easily choose the number of function
definitions in the batch file and the number of integration points so
that your program would work much slower than the CL version (and not
only by a factor of 2 or 3!).
Nicolas