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.


Reply via email to