[Prev][Next][Index][Thread]
Dylan performance
-
To: info-dylan@ai.mit.edu
-
Subject: Dylan performance
-
From: Rolf Wester <wester@ilt.fhg.de>
-
Date: Wed, 10 Jan 2001 11:45:01 -0500 (EST)
-
Organization: Aachen University of Technology (RWTH)
-
Xref: traf.lcs.mit.edu comp.lang.dylan:12965
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: