[Prev][Next][Index][Thread]

Dylan performance



Hi,

I'm a Dylan newby and try to test Dylan's performance. I'm running FO
Dylan on a 450 MHz Pentium II with 520 MB RAM.
The small test program is listed below. The Dylan version takes about 50
seconds on my machine. A c++ version of that program takes only 0.2
seconds (cygwin g++), a Python version 25 seconds and ACL6.0 Lisp 9
seconds (with all possible declarations; CMUCL is faster but only
available for UNIX). Is there any means to make the dylan code faster?

Besides this I get compile time errors when trying:
   let t1 = make(<array>, dimensions: #(nx , ny), fill: 0.0);

Any help and/or hint is appreciated.

--Rolf

P.S.: The little program is an implementation of a simple algorithm
for solving the heat conduction equation.

---------------------------------------------------------------------------------------------

Dylan source
-------------
define method temp (nx :: <integer>, ny :: <integer>, nt :: <integer>)

   let t1 = make(<array>, dimensions: #(300 , 300), fill: 0.0);
   let t2 = make(<array>, dimensions: #(300 , 300), fill: 0.0);

   for (k :: <integer> from 0 to nt - 1)
     for (i :: <integer> from 1 to nx - 2)
       for (j :: <integer> from 1 to ny - 2)
           aref(t2, i, j) := aref(t1, i, j) + 1.0 + 0.1 *
                                              (aref(t1, i + 1, j) +
                                               aref(t1, i - 1, j) +
                                               aref(t1, i, j + 1) +
                                               aref(t1, i, j - 1) -
                                         4.0 * aref(t1, i,j));
        end for;
     end for;
     for (i :: <integer> from 1 to nx - 2)
       for (j :: <integer> from 1 to ny - 2)
           aref(t1, i, j) := aref(t2, i, j) + 1.0 + 0.1 *
                                              (aref(t2, i + 1, j) +
                                               aref(t2, i - 1, j) +
                                               aref(t2, i, j + 1) +
                                               aref(t2, i, j - 1) -
                                         4.0 * aref(t2, i,j));
        end for;
     end for;
     format-out("%d \n", aref(t1, 150, 150));
   end for;
end method;

temp(300 , 300 , 10);

----------------------------------------------------------------------------------------------------

c++ source
------------

#include <iostream>
#include <iomanip>

void main()
{
 const int nx = 300;
 const int ny = 300;
 const int nt = 10;

 float ** t1 = new float*[nx];
 float ** t2 = new float*[nx];

 t1[0] = new float[nx*ny];
 t2[0] = new float[nx*ny];

 int i,j,k;

 for(i=1; i < nx; i++)
  t1[i] = t1[i-1] + ny;
 for(i=1; i < nx; i++)
  t2[i] = t2[i-1] + ny;

 for(i=0; i < nx; i++)
 {
  for(j=0; j < ny; j++)
     {
   t1[i][j] = 0.0;
   t2[i][j] = 0.0;
  }
 }


 for(k=0; k < nt; k++)
 {
  for(i=1; i < nx-1; i++)
  {
   for(j=1; j < ny-1; j++)
   {
    t2[i][j] = t1[i][j] + 1.0 + 0.1*(
     t1[i+1][j] +
     t1[i-1][j] +
     t1[i][j+1] +
     t1[i][j-1] -
     t1[i][j] * 4.0);
   }
  }
  for(i=1; i < nx-1; i++)
  {
   for(j=0; j < ny-1; j++)
   {
    t1[i][j] = t2[i][j] + 1.0 + 0.1*(
     t2[i+1][j] +
     t2[i-1][j] +
     t2[i][j+1] +
     t2[i][j-1] -
     t2[i][j] * 4.0);
   }
  }
  cout << t1[0][ny/2] << "  " << t1[10][ny/2] << "  "  <<
t1[nx/2][ny/2]  <<endl;
 }
}

-----------------------------------------------------------------------------------------------------

Python source
--------------

import array

def run(nt):
    list = [0.0]*(300*300)
    mat1 = array.array('f',list)
    mat2 = array.array('f',list)
    for i in range(300*300):
  mat1[i] = 0.0
  mat2[i] = 0.0

    for k in range(nt):
        for i in range(1,299):
            for j in range(1,299):
                ii = i*300
                im = ii - 300
                ip = ii + 300
                mat2[ii+j] = mat1[ii+j] + 1.0 + 0.1*(mat1[im+j]     +
mat1[ip+j]    +
                                                     mat1[ii+j+1]   +
mat1[ii+j-1]  -
                                                     4.0 * mat1[ii+j])
        for i in range(1,299):
            for j in range(1,299):
                ii = i*300
                im = ii - 300
                ip = ii + 300
                mat1[ii+j] = mat2[ii+j] + 1.0 + 0.1*(mat2[im+j]     +
mat2[ip+j]    +
                                                     mat2[ii+j+1]   +
mat2[ii+j-1]  -
                                                     4.0 * mat2[ii+j])
        print mat1[300*150 + 150]

run(10)

The Python version could be optimized by using numpy for example.

-----------------------------------------------------------------------------------------------

Lisp source
------------

(defmacro _f (form) `(the single-float ,form))
(defmacro _i (form) `(the fixnum ,form))

(defun temp-diff (nt)
  (declare (optimize (speed 3) (safety 0) (debug 0)))
  (let ((mat1 (make-array '(300 300) :element-type 'single-float
:initial-element 0.0)))
  (let ((mat2 (make-array '(300 300) :element-type 'single-float
:initial-element 0.0)))
    (declare (type (simple-array single-float (300 300)) mat1))
    (declare (type (simple-array single-float (300 300)) mat2))

    (dotimes (k nt)
      (declare (type fixnum k nt))
      ;(declare (:explain :calls :types))
      ;(declare (:explain :boxing))
      (loop for i fixnum from 1 to 298 do
            (loop for j fixnum from 1 to 298 do
                  (setf (aref mat2 i j)
                     (+ (_f (aref mat1 i j)) 1.0
                            (_f (* (_f 0.1) (_f  (+ (_f (aref mat1 (_i
(+ i -1)) j        ))
                                                    (_f (* (_f -4.0) (_f
(aref mat1 i j) )))
                                                    (_f (aref mat1 (_i
(+ i 1))  j        ))
                                                    (_f (aref mat1 i (_i
(+ j -1))        ))
                                                    (_f (aref mat1 i (_i
(+ j  1)))        )
                                                  ))))))))
      (loop for i fixnum from 1 to 298 do
            (loop for j fixnum from 1 to 298 do
                  (setf (aref mat1 i j)
                     (+ (_f (aref mat2 i j)) 1.0
                            (_f (* (_f 0.1) (_f  (+ (_f (aref mat2 (_i
(+ i -1)) j   )     )
                                                    (_f (* (_f -4.0) (_f
(aref mat2 i j) )))
                                                    (_f (aref mat2 (_i
(+ i 1))  j   )     )
                                                    (_f (aref mat2 i (_i
(+ j -1))   )     )
                                                    (_f (aref mat2 i (_i
(+ j  1)))        )
                                                  ))))))))

      ;(print (aref mat1 0 150))
      ;(print (aref mat1 1 150))
      (print (aref mat1 150 150)) )))
    )

I find this almost unreadable






Follow-Ups: