Nicolas Neuss <[EMAIL PROTECTED]> writes:
> Hello, CMUCLers.
>
> It would be nice to have important applications for which Lisp is
> faster than C. Here, a possible candidate is the following: generate
> the innermost loop for a filter operating on an image or a structured
> grid of floating point numbers. In C, the code could be for example:
>
> #include <stdio.h>
>
> const int n = 1000;
> const int nn = 1000*1000;
> static double mat[1000*1000];
>
> int main ()
> {
> int i, pos1, pos2;
>
> for (i=0; i<nn; i++)
> mat[i] = 1.0;
>
> for (i=0; i<10; i++)
> for (pos1=1; pos1<n-1; pos1++)
> for (pos2=pos1+n; pos2<pos1+(n-1)*n; pos2+=n)
> mat[pos2] = 0.11111111111111*
> (mat[pos2-1001]+mat[pos2-1]+mat[pos2+999]+
> mat[pos2-1000]+mat[pos2]+mat[pos2+1000]+
> mat[pos2-999]+mat[pos2+1]+mat[pos2+1001]);
> printf("%f", mat[n+1]);
>
> return 0;
> }
>
>
> In CL, I wrote the analogous thing as
>
> [stuff with definitions missing]
Here is the correct version (using n=100 for circumventing the size
limitations of ACL and Lispworks):
(eval-when (:compile-toplevel :load-toplevel :execute)
(deftype uint () '(unsigned-byte 32))
(deftype double-vec () '(simple-array double-float (*)))
(deftype fixnum-vec () '(simple-array fixnum (*))))
(defun fixnum-vec (&rest args)
(map 'fixnum-vec #'identity args))
(defun make-fixnum-vec (dim &optional (init 0))
(make-array dim :element-type 'fixnum :initial-element init))
(defun make-double-vec (dim &optional (init 0.0d0))
(make-array dim :element-type 'double-float :initial-element init))
(defun test ()
(let* ((dim 2) (n 100) ; !! 1000
(dims (make-fixnum-vec dim n))
(offsets (fixnum-vec 1 n))
(entries (make-double-vec (expt n dim) 1.0d0))
(pos0 0))
(declare (optimize (speed 3) (safety 0) (debug 0)))
(declare (type fixnum pos0)
(type fixnum-vec dims offsets)
(type double-vec entries))
(loop with offset of-type uint = (aref offsets 0)
for pos1 of-type uint from (the uint (+ pos0 offset)) by offset
below (the uint (+ pos0 (the uint (* offset (the uint (- (aref dims 0) 1))))))
do
(loop with offset of-type uint = (aref offsets 1)
for pos2 of-type uint from (the uint (+ pos1 offset)) by offset
below (the uint (+ pos1 (the uint (* offset (the uint (- (aref dims 1)
1))))))
do
(setf (aref entries pos2)
(* 0.1111111111
(+ (aref entries (the uint (+ pos2 -101))) ; !! -1001
(aref entries (the uint (+ pos2 -1)))
(aref entries (the uint (+ pos2 99))) ; !! 999
(aref entries (the uint (+ pos2 -100))) ; !! -1000
(aref entries (the uint (+ pos2 0)))
(aref entries (the uint (+ pos2 100))) ; !! 1000
(aref entries (the uint (+ pos2 -99))) ; !! -999
(aref entries (the uint (+ pos2 1)))
(aref entries (the uint (+ pos2 101)))))))))) ; !! 1001
(disassemble 'test)
The resulting disassembly is much longer than the disassembly of the C
code and the code performs a factor 10 worse. In the meantime, I
tried also ACL and Lispworks which yield even worse results. If noone
here has any idea, probably I'll take this over to comp.lang.lisp.
Nicolas.