From: Richard Fateman
Subject: Fortran vs. Lisp timings
Date: 
Message-ID: <1ks3ng$esm@agate.berkeley.edu>
One of the issues that has come up in discussions of Lisp vs.
mainstream languages, is the quality of the compiler.  I've
done some testing on various problems, and here is my
conclusion about the current state of a few compilers, with
respect to something that one other language's compiler does
OK on. Floating point.

The fortran (f77) compiler, with default settings on SPARC1+
computers produces code that runs about as fast as the
Allegro CL 4.1 compiler, with "optimize speed (safety 0)" and careful
declarations.

The fortran compiler with full optimization (-fast -O3 options)
produces code that runs about 10 times faster than either of the previously
indicated situations.


I would be delighted to hear other peoples' results.
(Though if all you are comparing is the same 2 pieces of software on the
same hardware, I guess I would be bored :)).

  For reference, here are the 2 benchmarks.

Here is a fortran program that on a SPARC1+
runs a 100x100 by 100x100  matrix mult in 4.9 seconds; 0.48 seconds with
high optimization.


c     main program/ driver
      dimension u(100,100),v(100,100),w(100,100),tarr(2)
c     set up test matrices
      do 10 i=1,100
         do 10 j=1,100
            v(i,j)=1.0
 10         u(i,j)=1.0
c    initialize timer
      start=dtime(tarr)
      call matmul(u,v,w,100,100,100)
      elapsed=dtime(tarr)
c     print user and system time in seconds
      print 1, tarr(1),tarr(2)
 1    format(f12.3)
      end

c     this is what we are comparing -- time for matmul
      subroutine matmul(a,b,c,n,m,k)
      dimension a(n,m),b(m,k),c(n,k)
      do 30 i=1,n
         do 30 j=1,k
            sum=0.0
            do 20 l=1,m
 20            sum=sum+a(i,l)*b(l,j)
 30      c(i,j)=sum
         end

.............................

Here is the Lisp program I am comparing it with. It takes 5.1 seconds
to run, compiled in Allegro CL 4.1.  (Note, I am told that Allegro 4.2 
will do better on this.)
......................
;; -*- mode: common lisp; -*-

#| Experiments with matrix multiply in Lisp.
      
          Compute C=A.B, matrix product

|#

(defun matmul(a b c n m k)  
  ;; in Allegro 4.1 this allocates no new
  ;; floating point space, and therefore does no GC.
  
  (declare   (optimize speed (safety 0))
	     (type (simple-array single-float (* *)) a b c)
	     (fixnum n m k))

  (let ((sum 0.0))
    (declare (single-float sum))
    (dotimes (i n c)		;run through columns; return c
      (declare (fixnum i))
      (dotimes (j k)
	(declare (fixnum j))
	(setf sum 0.0)
	(dotimes (l m)
	  (declare (fixnum l))

	  (setf sum (+ sum (* (aref a i l)(aref b l j)))))
	(setf (aref c i j) sum)))))



;;Some test data
(defparameter n0 100)
(defparameter m0 100)
(defparameter k0 100)

(defparameter a0
    (make-array (list n0 m0) :element-type 'single-float :initial-element 1.0))
;;a0 is n columns, m rows

(defparameter b0 
    (make-array (list m0 k0) :element-type 'single-float :initial-element 2.0))
;;b0 is m columns k rows

(defparameter  c0 
    (make-array (list n0 k0) :element-type 'single-float))
;; c0 is n columns k rows

#| to time this, compile the matmul, and

(time (matmul? a0 b0 c0 n0 m0 k0))
|#
.............

I will be glad to summarize info mailed to me.



-- 
Richard J. Fateman
·······@cs.berkeley.edu   510 642-1879

From: Bob Krovetz
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <60170@dime.cs.umass.edu>
A while back there were some comments about Lisp being inefficient
in terms of I/O.  Has anyone done any benchmarks to test this?
Perhaps reading and writing a million characters via read-char/
write-char vs. read-line/write-line, and comparing that to similar
functions in C and Fortran.

Bob

·······@cs.umass.edu
From: Ted Dunning
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <TED.93Feb22224409@lole.nmsu.edu>
In article <·····@dime.cs.umass.edu> ·······@canberra.cs.umass.edu (Bob Krovetz) writes:

   A while back there were some comments about Lisp being inefficient
   in terms of I/O.  Has anyone done any benchmarks to test this?

sure.

i just wrote a c program to read million characters using getchar.  it
takes 1.7 seconds to do it.

my lisp version (compiled using cmu common lisp, default settings) of
the same thing took 0.4 seconds to read 10,000 characters, and i hope
it will be done reading the full million by the time i finish this
paragraph.  ahhh... yes.  38.4 seconds.  this was for the following
code:

(defvar buffer (make-array 10000 :element-type 'standard-char))

(defun test(s)
    (dotimes (i 10000)
	     (setf (elt buffer i) (read-char s)))
    buffer)


   Perhaps reading and writing a million characters via read-char/
   write-char vs. read-line/write-line, and comparing that to similar
   functions in C and Fortran.

i am not interested in read-line since i usually am trying to read
binary files when reading very large files.  no optimizations were
done.  as a mild matter of interest, i converted the c code to use
fread instead of getchar.  the time required dropped to 0.8 seconds.

i am happy to take a factor of 2-4 in return for what lisp gives me,
but a factor of 20-40 is a bit much.  last time i tried doing this
sort of thing, i had to crib some of the system sources which had a
special macro-ized version of read-char since the portable version was
*so* slow.

this could probably be fixed by a few routines to 

a) read a buffer full of somethings (like fread)

b) a *fast* (not read) and reliable way to shrinkwrap/unwrap data
elements from a chunk read as in a).  this has no equivalent in
standard c, but is similar in intent to sun's xdr.
From: Scott McKay
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <19930223163702.0.SWM@SUMMER.SCRC.Symbolics.COM>
    Date: Tue, 23 Feb 1993 01:44 EST
    From: Ted Dunning <···@nmsu.edu>

    In article <·····@dime.cs.umass.edu> ·······@canberra.cs.umass.edu (Bob Krovetz) writes:

       A while back there were some comments about Lisp being inefficient
       in terms of I/O.  Has anyone done any benchmarks to test this?

    sure.

    i just wrote a c program to read million characters using getchar.  it
    takes 1.7 seconds to do it.

    my lisp version (compiled using cmu common lisp, default settings) of
    the same thing took 0.4 seconds to read 10,000 characters, and i hope
    it will be done reading the full million by the time i finish this
    paragraph.  ahhh... yes.  38.4 seconds.  this was for the following
    code:

    (defvar buffer (make-array 10000 :element-type 'standard-char))

    (defun test(s)
	(dotimes (i 10000)
		 (setf (elt buffer i) (read-char s)))
	buffer)


       Perhaps reading and writing a million characters via read-char/
       write-char vs. read-line/write-line, and comparing that to similar
       functions in C and Fortran.

    i am not interested in read-line since i usually am trying to read
    binary files when reading very large files.  no optimizations were
    done.  as a mild matter of interest, i converted the c code to use
    fread instead of getchar.  the time required dropped to 0.8 seconds.

    i am happy to take a factor of 2-4 in return for what lisp gives me,
    but a factor of 20-40 is a bit much.  last time i tried doing this
    sort of thing, i had to crib some of the system sources which had a
    special macro-ized version of read-char since the portable version was
    *so* slow.

    this could probably be fixed by a few routines to 

    a) read a buffer full of somethings (like fread)

    b) a *fast* (not read) and reliable way to shrinkwrap/unwrap data
    elements from a chunk read as in a).  this has no equivalent in
    standard c, but is similar in intent to sun's xdr.

The following form on a Symbolics XL1200 reading a file using TCP/FTP
from another Symbolics XL1200 (which are generally considered slow file
servers compared to Unix servers) took 0.55 seconds to read 100,000
bytes, which would be about 5.5 seconds to read 1,000,000 bytes.  That's
about 3.5 times slower than the Unix version, which you said is
acceptable performance.

 (defvar *bolix-buffer* (make-array 100000 :element-type 'standard-char))
 (defun bolix-test (s)
   (scl:send s :string-in nil *bolix-buffer* 0 100000)
   *bolix-buffer*)

Much to my surprise, doing the same test using TCP/FTP to OSF/1 running
on a DEC Alpha, it took about 0.65 seconds.  Using NFS to the same
machine took about 1.1 seconds, almost all of it actually waiting for
the data to get back to me from over the network.  I guess this means
that the Alpha just can't crank the bytes to us very fast, despite the
fact that it's 10 times faster than an XL1200.

Doing the same test to a local file system took 0.11 seconds, meaning
that I could read 1,000,000 bytes in 1.1 seconds.  That's about 1.5
times faster than your C program.  (Of course, I have no idea what sort
of a machine you are using.)

What this means is, a little diligence implementing a file stream system
can yield excellent performance in Lisp.  It's really too bad that X3J13
didn't address the issue of standardized stream interfaces.  Most of the
Lisp vendors implement most of David Gray's stream proposal, so perhaps
it's time to agree on a good buffered I/O interface as well.
From: Joshua M Yelon
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <C2wx39.65n@news.cso.uiuc.edu>
···@stony-brook.scrc.symbolics.com (Scott McKay) writes:

>The following form on a Symbolics XL1200 reading a file using TCP/FTP
>from another Symbolics XL1200 (which are generally considered slow file
>servers compared to Unix servers) took 0.55 seconds 

> (defvar *bolix-buffer* (make-array 100000 :element-type 'standard-char))
> (defun bolix-test (s)
>   (scl:send s :string-in nil *bolix-buffer* 0 100000)
>   *bolix-buffer*)

>What this means is, a little diligence implementing a file stream system
>can yield excellent performance in Lisp.

This is silly.  You are comparing a non-portable block-at-a-time operation
(SCL:SEND) to a portable, character-at-a-time operation (getchar).
Of _course_ the lisp is going to win.

Try comparing getchar to your lisp's portable character-at-a-time
operation (ie, READ-CHAR).
From: Scott McKay
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <19930223182518.3.SWM@SUMMER.SCRC.Symbolics.COM>
    Date: Tue, 23 Feb 1993 12:40 EST
    From: Joshua M Yelon <·······@ehsn11.cen.uiuc.edu>

    ···@stony-brook.scrc.symbolics.com (Scott McKay) writes:

    >The following form on a Symbolics XL1200 reading a file using TCP/FTP
    >from another Symbolics XL1200 (which are generally considered slow file
    >servers compared to Unix servers) took 0.55 seconds 

    > (defvar *bolix-buffer* (make-array 100000 :element-type 'standard-char))
    > (defun bolix-test (s)
    >   (scl:send s :string-in nil *bolix-buffer* 0 100000)
    >   *bolix-buffer*)

    >What this means is, a little diligence implementing a file stream system
    >can yield excellent performance in Lisp.

    This is silly.  You are comparing a non-portable block-at-a-time operation
    (SCL:SEND) to a portable, character-at-a-time operation (getchar).
    Of _course_ the lisp is going to win.

    Try comparing getchar to your lisp's portable character-at-a-time
    operation (ie, READ-CHAR).

Please re-read the last paragraph of my message, which I include here:

 What this means is, a little diligence implementing a file stream system
 can yield excellent performance in Lisp.  It's really too bad that X3J13
 didn't address the issue of standardized stream interfaces.  Most of the
 Lisp vendors implement most of David Gray's stream proposal, so perhaps
 it's time to agree on a good buffered I/O interface as well.

The only thing that is silly is that there are no portable, buffered I/O
operations in Common Lisp, and the point of my message is that we should
address this deficiency in a principled, portable way.
From: Ted Dunning
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <TED.93Feb23131603@lole.nmsu.edu>
In article <····················@SUMMER.SCRC.Symbolics.COM> ···@stony-brook.scrc.symbolics.com (Scott McKay) writes:

   The only thing that is silly is that there are no portable, buffered I/O
   operations in Common Lisp, and the point of my message is that we should
   address this deficiency in a principled, portable way.


hopefully by buffered i/o operations, i hope you mean the equivalent
of getchar.  if not, then there still isn't any hope.



and btw... i am curious how fast the C equivalent runs on the
symbolics.

that is, if it indeed does run on the symbolics.
From: Thomas Kirk
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <TK.93Feb23175839@mariah.research.att.com>
It's just not that hard to do fast I/O in lisp. The following toy code
implements very simple buffered binary I/O (actually just input) with
performance equivalent to getchar in C. It's not pure portable Common Lisp, 
but the amount of implementation-dependent code is minimal. I'll agree 
that it would be nice if there were standard inferfaces for this sort 
of thing; until then, I can live with such minor system dependencies.

This code is at the same level as getchar, so it's not surprising that its 
performance is comparable to C code (within a few percent, give or take).
Reading 1 million chars takes about 0.7 sec on a sparc 10/30, about 4 sec 
on a Symbolics UX1200S. 


;;; -*- Mode: LISP; Syntax: Common-lisp; Package: FIO; Base: 10; -*-

(eval-when (compile load eval)
  (defconstant *bufsiz* 4096))

(deftype ib-buf () `(simple-array (unsigned-byte 8) (,*bufsiz*)))

(defstruct ib
  (stream nil)
  (buf (make-array *bufsiz* :element-type '(unsigned-byte 8)
		   :initial-element 0 :adjustable nil)
       :type ib-buf)
  (nbytes 0 :type (integer 0 #.*bufsiz*))
  (offset 0 :type (integer 0 (#.*bufsiz*))))

(defun open-ib (file &key direction)
  (let ((stream (open file :direction direction
		      :element-type '(unsigned-byte 8))))
    (make-ib :stream stream)))

(defun close-ib (ib)
  (close (ib-stream ib)))

(defmacro %ib-read-byte (ib)
  `(locally (declare (optimize (speed 3) (safety 1)))
     (unless (< (ib-offset ,ib) (ib-nbytes ,ib))
       (ib-fill-buffer ,ib))
     (prog1
	 (aref (ib-buf ,ib) (ib-offset ,ib))
       (incf (ib-offset ,ib)))))

(defun ib-fill-buffer (ib)
  (setf (ib-nbytes ib)
    #+:allegro
    (excl::filesys-read-bytes (excl::stream-input-fn (ib-stream ib))
			      (ib-buf ib) 0 *bufsiz*)
    #+:cmu
    (system:read-n-bytes (ib-stream ib) (ib-buf ib) 0 *bufsiz*)
    #+:lucid ; SYS_read => 3 in sunos4.1
    (sys:syscall 3 (lcl:extract-stream-handle (ib-stream ib) :input)
		 (ib-buf ib) *bufsiz*)
    #+:symbolics
    (multiple-value-bind (ibuf first last)
	; don't block when input isn't available...
	(scl:send (ib-stream ib) :read-input-buffer nil nil)
      (when (and first last (> last first))
	(let ((n (min (- last first) *bufsiz*)))
	  (replace (ib-buf ib) ibuf :start1 0 :end1 n :start2 first :end2 last)
	  (scl:send (ib-stream ib) :advance-input-buffer (+ first n))
	  n))))
  (setf (ib-offset ib) 0)
  (values))

;;; read n chars from file
(defun test-ib (file n)
  (let ((ib (open-ib file :direction :input)))
    (unwind-protect
	(dotimes (i n)
	  (%ib-read-byte ib))
      (close-ib ib))))
From: Scott McKay
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <19930223232846.3.SWM@SUMMER.SCRC.Symbolics.COM>
    Date: Tue, 23 Feb 1993 16:16 EST
    From: Ted Dunning <···@nmsu.edu>

    In article <····················@SUMMER.SCRC.Symbolics.COM> ···@stony-brook.scrc.symbolics.com (Scott McKay) writes:

       The only thing that is silly is that there are no portable, buffered I/O
       operations in Common Lisp, and the point of my message is that we should
       address this deficiency in a principled, portable way.

    hopefully by buffered i/o operations, i hope you mean the equivalent
    of getchar.  if not, then there still isn't any hope.

Yes.

    and btw... i am curious how fast the C equivalent runs on the
    symbolics.

    that is, if it indeed does run on the symbolics.

There is a C compiler for the Symbolics, and I don't have it loaded.
Too much trouble.  So, I dunno how fast it would run.  But C is pretty
slow on a Symbolics Lisp Machine -- I can promise with 100% certainty
that it is not as fast as Lisp.
From: Ted Dunning
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <TED.93Feb23151007@lole.nmsu.edu>
In article <····················@bingen.hrp.no> ······@bingen.hrp.no (Eyvind Ness) writes:

   In article <·····@dime.cs.umass.edu> ·······@canberra.cs.umass.edu (Bob Krovetz) writes:

      A while back there were some comments about Lisp being inefficient
      in terms of I/O.  Has anyone done any benchmarks to test this?
      Perhaps reading and writing a million characters via read-char/
      write-char vs. read-line/write-line, and comparing that to similar
      functions in C and Fortran.

   Often it is a bit inappropriate to use the low-level IO functions
   WRITE-CHAR and READ-CHAR when you might be able to employ the
   higher-level READ and PRINT functions.

sometimes this is true, sometimes it isn't.

   After you have configured your own readtable with COPY-READTABLE,
   SET-SYNTAX-FROM-CHAR, and SET-MACRO-CHARACTER, you can write simple and
   efficient parsers in CL.

readtable hacking is an art that is rather more difficult than most of
the simple jobs we are talking about.

furthermore, readtables don't help a whit with binary files.

   Another option to avoid using the portable (but often inefficient)
   READ-CHAR and WRITE-CHAR, is to use implementation specific versions
   like e.g. Lucid's FAST-READ/WRITE-CHAR/BYTE/STRING.


this isn't really an option any more than groveling around in the
internal structure of _iob is an option in C.  it can be done, but if
it really needs to be done, then something is structurally wrong.
From: Drew Justin Asson
Subject: Re: Fortran vs. Lisp timings
Date: 
Message-ID: <ASSON.93Feb23154644@halcyon.stsci.edu>
On 23 Feb 93 09:26:55, ······@bingen.hrp.no (Eyvind Ness) said:

>The most annoying limitation of this scheme is that some characters like
>":" belongs to a fixed character class. ":" is interpreted as a package
>marker, no matter what readtable you are using. I know that you can get
>around this in some CL implementations (e.g. Symbolics CL), but there is
>no portable way of doing it as far as I know, anyway.

I just wanted to say that you can do this in Allegro CL on Suns, because
I am doing it right now.  We're reading in a large file which consists of
keyword/value pairs of the form:

	<keyword>: <value>

The way that I do it is:

	(set-syntax-from-char #\: #\;)

This way I just treat the : as a comment, and grab what I need.  Simple,
but perhaps not elegant.  But, it does work.  It seems that, based on 
CLtL2, that set-syntax-from-char was designed to do just this.

============================================================
Drew J. Asson                                ·····@stsci.edu
Advance Planning Systems Group               (410) 338-4474

Space Telescope Science Institute
3700 San Martin Drive
Baltimore, MD 21218
--
============================================================
Drew J. Asson                                ·····@stsci.edu
Advance Planning Systems Group               (410) 338-4474

Space Telescope Science Institute
3700 San Martin Drive
Baltimore, MD 21218