From: Dr Jon D Harrop
Subject: Eval performance
Date: 
Message-ID: <1130492608.997145.54490@z14g2000cwz.googlegroups.com>
I'm trying to write a benchmark based on the symbolic differentiation
example discussed recently. By using s-exprs, the Lisp implementation
should be short and fast. However, I'm having trouble getting good
performance using "eval". I believe I need to use compile but I'm not
sure how.

So how can this code be optimised:

(declaim (optimize (speed 3) (safety 3) (space 0) (debug 0)))

(define (d e x)
  (typecase e
	    (number 0)
	    (symbol (if (eq e x) 1 0))
	    ((cons (eql log) list)
	     (let ((f (cadr e)))
	       `(* ,(d f x) (/ 1 ,f))))
	    ((cons (eql +) list)
	     (let ((f (cadr e)) (g (caddr e)))
	       `(+ ,(d f x) ,(d g x))))
	    ((cons (eql *) list)
	     (let ((f (cadr e)) (g (caddr e)))
	       `(+ (* ,f ,(d g x)) (* ,g ,(d f x)))))
	    ((cons (eql expt) list)
	     (let ((f (cadr e)) (g (caddr e)))
	       `(* (expt ,f ,g)
		   (+ (/ (* ,g ,(d f x)) ,f)
		      (* (log ,f) ,(d g x))))))))

(define e1 '(+ (* (* a x) x) (* b x) c))

(define (f n g)
  (if (= n 0) g `(expt ,(f (- n 1) g) ,(f (- n 1) g))))

(define n 15)

(print "build")
(define e2 (time (f n e1)))

(print "deriv")
(define e3 (time (d e2 'x)))

(print "eval")
(define a 0.1)
(define b 0.1)
(define c 0.1)
(define x 0.1)
(defun eval2 () (eval e3))
(compile 'eval2)
(print (time (eval2)))
(setf a 0.2)
(setf b 0.2)
(setf c 0.2)
(setf x 0.2)
(print (time (eval2)))
(setf a 0.3)
(setf b 0.3)
(setf c 0.3)
(setf x 0.3)
(print (time (eval2)))

Cheers,
Jon.

From: Pisin Bootvong
Subject: Re: Eval performance
Date: 
Message-ID: <1130497413.946316.272310@g14g2000cwa.googlegroups.com>
Dr Jon D Harrop wrote:
> I'm trying to write a benchmark based on the symbolic differentiation
> example discussed recently. By using s-exprs, the Lisp implementation
> should be short and fast. However, I'm having trouble getting good
> performance using "eval". I believe I need to use compile but I'm not
> sure how.
>
> So how can this code be optimised:
>
> (declaim (optimize (speed 3) (safety 3) (space 0) (debug 0)))
>
> (define (d e x)
>   (typecase e
> 	    (number 0)
> 	    (symbol (if (eq e x) 1 0))
> 	    ((cons (eql log) list)
> 	     (let ((f (cadr e)))
> 	       `(* ,(d f x) (/ 1 ,f))))
> 	    ((cons (eql +) list)
> 	     (let ((f (cadr e)) (g (caddr e)))
> 	       `(+ ,(d f x) ,(d g x))))
> 	    ((cons (eql *) list)
> 	     (let ((f (cadr e)) (g (caddr e)))
> 	       `(+ (* ,f ,(d g x)) (* ,g ,(d f x)))))
> 	    ((cons (eql expt) list)
> 	     (let ((f (cadr e)) (g (caddr e)))
> 	       `(* (expt ,f ,g)
> 		   (+ (/ (* ,g ,(d f x)) ,f)
> 		      (* (log ,f) ,(d g x))))))))
>
> (define e1 '(+ (* (* a x) x) (* b x) c))
>
> (define (f n g)
>   (if (= n 0) g `(expt ,(f (- n 1) g) ,(f (- n 1) g))))
>
> (define n 15)
>
> (print "build")
> (define e2 (time (f n e1)))
>
> (print "deriv")
> (define e3 (time (d e2 'x)))
>
> (print "eval")
> (define a 0.1)
> (define b 0.1)
> (define c 0.1)
> (define x 0.1)
> (defun eval2 () (eval e3))
> (compile 'eval2)
> (print (time (eval2)))
> (setf a 0.2)
> (setf b 0.2)
> (setf c 0.2)
> (setf x 0.2)
> (print (time (eval2)))
> (setf a 0.3)
> (setf b 0.3)
> (setf c 0.3)
> (setf x 0.3)
> (print (time (eval2)))
>
> Cheers,
> Jon.

Is this Common Lisp?

1. Common Lisp doesn't have DEFINE.
2. variable namespace and function namespace of Common Lisp is separate
(eval e3) expression in eval2 will always fail since e3 is undefined
variable.
3. (eval e3) is not a way to use eval. EVAL takes expression tree.
which is list. #'e3 is a function not the expression list. It might
work, but I don't think it's what you want.

I don't think it has anything to do with eval. Perhaps you could first
print out built s-exp then compare time between passing that s-exp to
eval and typing that s-exp as a function and run it.

There is comp.lang.scheme group.
From: Thomas A. Russ
Subject: Re: Eval performance
Date: 
Message-ID: <ymi3bmlskn7.fsf@sevak.isi.edu>
"Dr Jon D Harrop" <···@ffconsultancy.com> writes:

OK, this isn't an optimization per se, but I would find the dispatch
clearer if rewritten to use CASE for the CONSes:

> (define (d e x)
>   (typecase e
> 	    (number 0)
> 	    (symbol (if (eq e x) 1 0))
> 	    ((cons (eql log) list)
> 	     (let ((f (cadr e)))
> 	       `(* ,(d f x) (/ 1 ,f))))
> 	    ((cons (eql +) list)
> 	     (let ((f (cadr e)) (g (caddr e)))
> 	       `(+ ,(d f x) ,(d g x))))
> 	    ((cons (eql *) list)
> 	     (let ((f (cadr e)) (g (caddr e)))
> 	       `(+ (* ,f ,(d g x)) (* ,g ,(d f x)))))
> 	    ((cons (eql expt) list)
> 	     (let ((f (cadr e)) (g (caddr e)))
> 	       `(* (expt ,f ,g)
> 		   (+ (/ (* ,g ,(d f x)) ,f)
> 		      (* (log ,f) ,(d g x))))))))

(define (d e x)
    (typecase e
      (number 0)
      (symbol (if (eq e x) 1 0))
      (cons
       (ecase (first e)
         (* (let ((f (cadr e)))
	      `(* ,(d f x) (/ 1 ,f))))
	 (+ (let ((f (cadr e)) (g (caddr e)))
	      `(+ ,(d f x) ,(d g x))))
	 (* (let ((f (cadr e)) (g (caddr e)))
	      `(+ (* ,f ,(d g x)) (* ,g ,(d f x)))))
	 (expt (let ((f (cadr e)) (g (caddr e)))
		 `(* (expt ,f ,g)
		     (+ (/ (* ,g ,(d f x)) ,f)
			(* (log ,f) ,(d g x))))))))))


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Arthur Lemmens
Subject: Re: Eval performance
Date: 
Message-ID: <opszdctfb2k6vmsw@news.xs4all.nl>
Thomas A. Russ wrote:

 > (ecase (first e)
 >   (* (let ((f (cadr e)))
 >     `(* ,(d f x) (/ 1 ,f))))
 >   (+ (let ((f (cadr e)) (g (caddr e)))
 >     `(+ ,(d f x) ,(d g x))))
 >   (* (let ((f (cadr e)) (g (caddr e)))
 >     `(+ (* ,f ,(d g x)) (* ,g ,(d f x)))))

This sounds like a good case for destructuring-bind:

(destructuring-bind (operator f &optional g)
    e
  (ecase operator
    (log `(* ,(d f x) (/ 1 ,f)))
    (+   `(+ ,(d f x) ,(d g x)))
    (*   `(+ (* ,f ,(d g x)) (* ,g ,(d f x))))))

Untested of course (but I fixed the * instead of LOG typo).
From: Pascal Costanza
Subject: Re: Eval performance
Date: 
Message-ID: <3sfapoFntbdfU1@individual.net>
Arthur Lemmens wrote:
> Thomas A. Russ wrote:
> 
>  > (ecase (first e)
>  >   (* (let ((f (cadr e)))
>  >     `(* ,(d f x) (/ 1 ,f))))
>  >   (+ (let ((f (cadr e)) (g (caddr e)))
>  >     `(+ ,(d f x) ,(d g x))))
>  >   (* (let ((f (cadr e)) (g (caddr e)))
>  >     `(+ (* ,f ,(d g x)) (* ,g ,(d f x)))))
> 
> This sounds like a good case for destructuring-bind:
> 
> (destructuring-bind (operator f &optional g)
>    e
>  (ecase operator
>    (log `(* ,(d f x) (/ 1 ,f)))
>    (+   `(+ ,(d f x) ,(d g x)))
>    (*   `(+ (* ,f ,(d g x)) (* ,g ,(d f x))))))
> 
> Untested of course (but I fixed the * instead of LOG typo).

What about genericizing it?

(defun derive (e x)
   (if (atom e)
       (atom-derive x e)
       (apply #'cons-derive x e)))

(defgeneric atom-derive (x e))

(defmethod atom-derive (x (e number))
   0)
(defmethod atom-derive (x (e symbol))
   (if (eq x e) 1 0))

(defgeneric cons-derive (x op f &optional g))

(defmethod cons-derive (x (op (eql '+)) f &optional g)
   `(+ ,(derive f x) ,(derive g x)))

(defmethod cons-derive (x (op (eql '*)) f &optional g)
   `(+ (* ,f ,(derive g x)) (* ,g ,(derive f x)))))

etc.

In this way you get an extensible derivation protocol. ;)

Also untested of course (and I didn't fix anything).


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Dr Jon D Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <1130533882.176575.12230@g47g2000cwa.googlegroups.com>
Excellent idea! :-)

Cheers,
Jon.
From: Arthur Lemmens
Subject: Re: Eval performance
Date: 
Message-ID: <opszdflulhk6vmsw@news.xs4all.nl>
Pascal Costanza wrote:

> Arthur Lemmens wrote:

>> This sounds like a good case for destructuring-bind:
>>
>> (destructuring-bind (operator f &optional g)
>> e
>> (ecase operator
>> (log `(* ,(d f x) (/ 1 ,f)))
>> (+   `(+ ,(d f x) ,(d g x)))
>> (*   `(+ (* ,f ,(d g x)) (* ,g ,(d f x))))))
>>
>> Untested of course (but I fixed the * instead of LOG typo).
>
> What about genericizing it?

That wouldn't 'look good' on Mr. Harrop's LOC benchmarks,
so I'm afraid we can't allow that...
From: Dr Jon D Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <1130534005.695405.170520@o13g2000cwo.googlegroups.com>
Perhaps using non-whitespace bytes instead of LOC would be better in
this case?
From: Pascal Costanza
Subject: Re: Eval performance
Date: 
Message-ID: <3sflodFo4shuU1@individual.net>
Arthur Lemmens wrote:
> Pascal Costanza wrote:
> 
>> Arthur Lemmens wrote:
> 
>>> This sounds like a good case for destructuring-bind:
>>>
>>> (destructuring-bind (operator f &optional g)
>>> e
>>> (ecase operator
>>> (log `(* ,(d f x) (/ 1 ,f)))
>>> (+   `(+ ,(d f x) ,(d g x)))
>>> (*   `(+ (* ,f ,(d g x)) (* ,g ,(d f x))))))
>>>
>>> Untested of course (but I fixed the * instead of LOG typo).
>>
>> What about genericizing it?
> 
> That wouldn't 'look good' on Mr. Harrop's LOC benchmarks,
> so I'm afraid we can't allow that...

ROTFL!


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Pascal Bourguignon
Subject: Re: Eval performance
Date: 
Message-ID: <87y84duddg.fsf@thalassa.informatimago.com>
"Dr Jon D Harrop" <···@ffconsultancy.com> writes:

> I'm trying to write a benchmark based on the symbolic differentiation
> example discussed recently. By using s-exprs, the Lisp implementation
> should be short and fast. However, I'm having trouble getting good
> performance using "eval". I believe I need to use compile but I'm not
> sure how.
> [...]
> (define ...)

What is define?


> (defun eval2 () (eval e3))
> (compile 'eval2)

What you need to compile is not the call to eval, it's the expression evaluated!

(defparameter e3 '(+ (* 1/2 x x) (* 4 x) 16))
(funcall (eval (compile nil `(lambda (x) ,e3))) 42)

-- 
"I have challenged the entire quality assurance team to a Bat-Leth
contest.  They will not concern us again."
From: Dr Jon D Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <1130498406.976240.241770@g43g2000cwa.googlegroups.com>
Pascal Bourguignon wrote:
> "Dr Jon D Harrop" <···@ffconsultancy.com> writes:
>
> > I'm trying to write a benchmark based on the symbolic differentiation
> > example discussed recently. By using s-exprs, the Lisp implementation
> > should be short and fast. However, I'm having trouble getting good
> > performance using "eval". I believe I need to use compile but I'm not
> > sure how.
> > [...]
> > (define ...)
>
> What is define?

Oops! Sorry, I posted the code I had half ported to Scheme. Still, you
get the idea. :-)

> > (defun eval2 () (eval e3))
> > (compile 'eval2)
>
> What you need to compile is not the call to eval, it's the expression
> evaluated!
>
> (defparameter e3 '(+ (* 1/2 x x) (* 4 x) 16))
> (funcall (eval (compile nil `(lambda (x) ,e3))) 42)

I see. Yes, of course.

Thanks,
Jon.
From: Rainer Joswig
Subject: Re: Eval performance
Date: 
Message-ID: <BF87D077.1C390%joswig@lisp.de>
Am 28.10.2005 11:43 Uhr schrieb "Dr Jon D Harrop" unter
<···@ffconsultancy.com> in
·······················@z14g2000cwz.googlegroups.com:

> I'm trying to write a benchmark based on the symbolic differentiation
> example discussed recently. By using s-exprs, the Lisp implementation
> should be short and fast. However, I'm having trouble getting good
> performance using "eval". I believe I need to use compile but I'm not
> sure how.

I'd say this is a waste of time. You are starting wrong. You
are focused on optimizing micro-benchmarks. This is simply
the wrong approach. Plus having a basic understanding
of Lisp before writing performance oriented code might
help.

First develop some useful architecture based on Lisp.
Then optimize where necessary. It may help to read some code
that exists.

A start would be reading the chapters (and reading the Common Lisp code)
from this book: http://www.norvig.com/paip.html


> 
> So how can this code be optimised:

Throw it away. Learn to write Lisp code first.

> (declaim (optimize (speed 3) (safety 3) (space 0) (debug 0)))
> 
> (define (d e x)
>   (typecase e
>    (number 0)
>    (symbol (if (eq e x) 1 0))
>    ((cons (eql log) list)
>     (let ((f (cadr e)))
>       `(* ,(d f x) (/ 1 ,f))))
>    ((cons (eql +) list)
>     (let ((f (cadr e)) (g (caddr e)))
>       `(+ ,(d f x) ,(d g x))))
>    ((cons (eql *) list)
>     (let ((f (cadr e)) (g (caddr e)))
>       `(+ (* ,f ,(d g x)) (* ,g ,(d f x)))))
>    ((cons (eql expt) list)
>     (let ((f (cadr e)) (g (caddr e)))
>       `(* (expt ,f ,g)
>   (+ (/ (* ,g ,(d f x)) ,f)
>      (* (log ,f) ,(d g x))))))))
> 
> (define e1 '(+ (* (* a x) x) (* b x) c))
> 
> (define (f n g)
>   (if (= n 0) g `(expt ,(f (- n 1) g) ,(f (- n 1) g))))
> 
> (define n 15)
> 
> (print "build")
> (define e2 (time (f n e1)))
> 
> (print "deriv")
> (define e3 (time (d e2 'x)))
> 
> (print "eval")
> (define a 0.1)
> (define b 0.1)
> (define c 0.1)
> (define x 0.1)
> (defun eval2 () (eval e3))
> (compile 'eval2)
> (print (time (eval2)))
> (setf a 0.2)
> (setf b 0.2)
> (setf c 0.2)
> (setf x 0.2)
> (print (time (eval2)))
> (setf a 0.3)
> (setf b 0.3)
> (setf c 0.3)
> (setf x 0.3)
> (print (time (eval2)))
> 
> Cheers,
> Jon.
> 
From: Kaz Kylheku
Subject: Re: Eval performance
Date: 
Message-ID: <1130530111.329590.294670@g14g2000cwa.googlegroups.com>
Dr Jon D Harrop wrote:
> I'm trying to write a benchmark based on the symbolic differentiation
> example discussed recently. By using s-exprs, the Lisp implementation
> should be short and fast. However, I'm having trouble getting good
> performance using "eval". I believe I need to use compile but I'm not
> sure how.

Huh? You mean you want to differentiate a formula symbolically, but
then treat it as a Lisp expression and evaluate it?

Well, you have two choices. You can do the differentiation in a macro,
so that some kind of differentiation notation can be available as
program syntax. The programmer can write:

   (derivative (* 3 x) x)  ;; d/dx 3x

which will hopefully replace itself with:

   3

To turn an expression into a compiled function at runtime, you do
something like:

  (defun compile-expr-into-fun (expr)
    (compile nil `(lambda () ,expr)))

Suppose you just want a single evaluation of the expression. Is it
faster to just EVAL it, or to compile it into a function and funcall
that? The answer is "it depends". Some Lisps compile everything, so the
two are the same.
From: Pascal Costanza
Subject: Re: Eval performance
Date: 
Message-ID: <3set1rFo23ahU1@individual.net>
Dr Jon D Harrop wrote:
> I'm trying to write a benchmark based on the symbolic differentiation
> example discussed recently. By using s-exprs, the Lisp implementation
> should be short and fast. However, I'm having trouble getting good
> performance using "eval". I believe I need to use compile but I'm not
> sure how.
> 
> So how can this code be optimised:
[...]

It's not clear what you are trying to do. Depending on the actual 
purpose of the program, you may neither need eval nor compile. In fact, 
symbolic differentiation is a nice example for macro programming in 
which you can compile a derivative without any loss of runtime 
performance at all.

But I basically agree with Rainer, learn to write Lisp code first.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Peter Seibel
Subject: Re: Eval performance
Date: 
Message-ID: <m2psppsfim.fsf@gigamonkeys.com>
"Dr Jon D Harrop" <···@ffconsultancy.com> writes:

> I'm trying to write a benchmark based on the symbolic differentiation
> example discussed recently. By using s-exprs, the Lisp implementation
> should be short and fast. However, I'm having trouble getting good
> performance using "eval". I believe I need to use compile but I'm not
> sure how.

Uh, why do you need to use EVAL at all to do symbolic differentiation?
Isn't the whole point that it's symbolic?

-Peter

-- 
Peter Seibel           * ·····@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp  * http://www.gigamonkeys.com/book/
From: Dr Jon D Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <1130525670.096254.108090@g49g2000cwa.googlegroups.com>
Peter Seibel wrote:
> Uh, why do you need to use EVAL at all to do symbolic differentiation?
> Isn't the whole point that it's symbolic?

I'm trying to combine different, interesting tasks into a single
program. Ultimately, I'm trying to make a benchmark that will show
Lisp/Scheme in the best possible light.

As other people have already shown, the derivative function in Lisp can
be written fairly clearly and succinctly (especially compared to C/C++,
Java etc.) so I think that is a good demonstration of clarity. With
s-exprs, you don't have the overhead of declaring an expr type in Lisp,
as I do in the other implementations (including OCaml), and there is
continuity in the sytax (as opposed to a+b and Plus(a, b) in the ML).

Currently, I'm using a derivative function to differentiate a big
expression. Then I'm evaluating the derivate at a few points. The Lisp
uses eval for the evaluation because the derivative function generated
an s-expr. My other implementations have to include a custom eval
function, which requires more code and they (typically) cannot compile
to native code so Lisp should be a lot faster.

However, compilation time is clearly going to be overwhelming (now that
I've got it "working" I can't actually execute it because compilation
takes too long and uses too much RAM) because the expression is huge.
So I need to use small expressions and, preferably, ones with recursive
functions in them.

To make Lisp look good (assuming the compiled Lisp s-expr will be
evaluated more quickly than the interpreters written in other
languages), evaluation must be done much more than all other
operations. So, perhaps it would be best to symbolically differentiate
a medium-sized expression and then tabulate it over a large range of
parameter values, or to ditch symbolic differentiation and write a
program to evaluate other programs (I think this is a much bigger task
though, but the results would be much more interesting as well).

Cheers,
Jon.
From: Arthur Lemmens
Subject: Re: Eval performance
Date: 
Message-ID: <opszdem7yzk6vmsw@news.xs4all.nl>
Dr Jon D Harrop wrote:

> Ultimately, I'm trying to make a benchmark that will show
> Lisp/Scheme in the best possible light.

Kenny, can you please get us ilias back?
From: ······@corporate-world.lisp.de
Subject: Re: Eval performance
Date: 
Message-ID: <1130579600.969467.223740@f14g2000cwb.googlegroups.com>
Dr Jon D Harrop wrote:
> Peter Seibel wrote:
> > Uh, why do you need to use EVAL at all to do symbolic differentiation?
> > Isn't the whole point that it's symbolic?
>
> I'm trying to combine different, interesting tasks into a single
> program. Ultimately, I'm trying to make a benchmark that will show
> Lisp/Scheme in the best possible light.

This is approach is highly questionable.

I'm definitely not interested in constructing benchmarks to
make Lisp look good.

> As other people have already shown, the derivative function in Lisp can
> be written fairly clearly and succinctly (especially compared to C/C++,
> Java etc.) so I think that is a good demonstration of clarity. With
> s-exprs, you don't have the overhead of declaring an expr type in Lisp,
> as I do in the other implementations (including OCaml), and there is
> continuity in the sytax (as opposed to a+b and Plus(a, b) in the ML).
>
> Currently, I'm using a derivative function to differentiate a big
> expression. Then I'm evaluating the derivate at a few points. The Lisp
> uses eval for the evaluation because the derivative function generated
> an s-expr. My other implementations have to include a custom eval
> function, which requires more code and they (typically) cannot compile
> to native code so Lisp should be a lot faster.
>
> However, compilation time is clearly going to be overwhelming (now that
> I've got it "working" I can't actually execute it because compilation
> takes too long and uses too much RAM) because the expression is huge.
> So I need to use small expressions and, preferably, ones with recursive
> functions in them.
>
> To make Lisp look good (assuming the compiled Lisp s-expr will be
> evaluated more quickly than the interpreters written in other
> languages), evaluation must be done much more than all other
> operations. So, perhaps it would be best to symbolically differentiate
> a medium-sized expression and then tabulate it over a large range of
> parameter values, or to ditch symbolic differentiation and write a
> program to evaluate other programs (I think this is a much bigger task
> though, but the results would be much more interesting as well).

There is so much wrong in the above paragraph that I wouldn't even
know where to start...
From: Vesa Karvonen
Subject: Re: Eval performance
Date: 
Message-ID: <djvjku$khb$1@oravannahka.helsinki.fi>
······@corporate-world.lisp.de wrote:
> Dr Jon D Harrop wrote:
[...]
> > I'm trying to combine different, interesting tasks into a single
> > program. Ultimately, I'm trying to make a benchmark that will show
> > Lisp/Scheme in the best possible light.

> This is approach is highly questionable.

Indeed. It is extremely difficult to make fair comparisons of any kind
between programming languages. To intentionally design biased benchmarks
is just one step away from being scientific misconduct.

-Vesa Karvonen
From: Dr Jon D Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <1130584570.497438.60630@g44g2000cwa.googlegroups.com>
Not if you state that the test was specifically designed to emphasise
the benefits of efficient run-time code generation. IMHO, many people
believe that such a test cannot exist. I think they would be very
interested to see if it can be created.

Cheers,
Jon.
From: Rainer Joswig
Subject: Re: Eval performance
Date: 
Message-ID: <BF89582F.1C5EC%joswig@lisp.de>
Am 29.10.2005 13:16 Uhr schrieb "Dr Jon D Harrop" unter
<···@ffconsultancy.com> in
·······················@g44g2000cwa.googlegroups.com:

> 
> Not if you state that the test was specifically designed to emphasise
> the benefits of efficient run-time code generation. IMHO, many people
> believe that such a test cannot exist.

Who?

> I think they would be very
> interested to see if it can be created.

Why not enter "run-time code generation" and "benchmark" into
the Google search field and press return?

Or go to comp.benchmark and ask there?

> 
> Cheers,
> Jon.
> 
From: Dr Jon D Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <1130703060.074309.166920@o13g2000cwo.googlegroups.com>
Rainer Joswig wrote:
> Am 29.10.2005 13:16 Uhr schrieb "Dr Jon D Harrop" unter
> <···@ffconsultancy.com> in
> ·······················@g44g2000cwa.googlegroups.com:
> > Not if you state that the test was specifically designed to emphasise
> > the benefits of efficient run-time code generation. IMHO, many people
> > believe that such a test cannot exist.
>
> Who?

Basically everyone that I know of. I am not sure if it can be done.

> > I think they would be very
> > interested to see if it can be created.
>
> Why not enter "run-time code generation" and "benchmark" into
> the Google search field and press return?
>
> Or go to comp.benchmark and ask there?

I've already searched for existing benchmarks. There are many out
there, of course, and I have studied quite a few. However, most Lisp
benchmarks are either out of date, compare only to Java/C# or use poor
implementations written in other languages.

I have studied all of the run-time code generation benchmarks that come
with MetaOCaml. Some of those are probably suitable (I'll look into
this in more detail). However, the ordinary OCaml implementations of
the benchmarks that are used for comparison are typically written in
the style of MetaOCaml, which is much more verbose and less efficient.
When rewritten, I rarely found a significant speed improvement from
MetaOCaml.

Perhaps I should take whichever MetaOCaml benchmark showed the biggest
performance improvement from run-time code generation and port it to
Lisp.

Cheers,
Jon.
From: Pascal Costanza
Subject: Re: Eval performance
Date: 
Message-ID: <3skpq3Fp1rk3U1@individual.net>
Dr Jon D Harrop wrote:
> Rainer Joswig wrote:
> 
>>Am 29.10.2005 13:16 Uhr schrieb "Dr Jon D Harrop" unter
>><···@ffconsultancy.com> in
>>·······················@g44g2000cwa.googlegroups.com:
>>
>>>Not if you state that the test was specifically designed to emphasise
>>>the benefits of efficient run-time code generation. IMHO, many people
>>>believe that such a test cannot exist.
>>
>>Who?
> 
> Basically everyone that I know of. I am not sure if it can be done.

The people you know are apparently not very smart.

Virtual machines rely heavily on runtime code generation, because it is 
clearly better to compile bytecodes to machine code before executing 
them instead of just interpreting them. There exists a whole body of 
literature on benchmarks for virtual machines.

In the case of Common Lisp, for example CLOS relies on runtime code 
generation. Cf. the section on user-defined method combinations in ANSI 
Common Lisp, where you can see that a method combination is basically a 
macro expansion process. Since CLOS allows method redefinition at 
runtime, this macro expansion process has to be performed at runtime. 
Again, there exist a number of papers that discuss performance 
characteristics of CLOS, and there are also benchmarks out there for 
testing performance of CLOS.

There is also the related field of partial evaluation which is of 
interest in this regard. Basically, the implementations of virtual 
machines, CLOS, etc., employ (ad-hoc or principled) partial evaluation 
to distinguish between program fragments that can and cannot change at 
runtime, in order to efficiently compile away the static aspects of such 
code. This is related because one can also make optimistic guesses wrt 
to what is static about a code fragment if one is also able to undo 
optimizations and redo the analysis once the assumptions don't hold 
anymore. This is, by definition, a runtime code generation approach.

The people who have implemented Self have put a lot of work into such 
issues, and again you can find a lot of literature here.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Jon Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <4365b558$0$49811$ed2e19e4@ptn-nntp-reader04.plus.net>
Pascal Costanza wrote:
> Virtual machines rely heavily on runtime code generation, because it is
> clearly better to compile bytecodes to machine code before executing
> them instead of just interpreting them. There exists a whole body of
> literature on benchmarks for virtual machines.
> 
> In the case of Common Lisp, for example CLOS relies on runtime code
> generation. Cf. the section on user-defined method combinations in ANSI
> Common Lisp, where you can see that a method combination is basically a
> macro expansion process. Since CLOS allows method redefinition at
> runtime, this macro expansion process has to be performed at runtime.
> Again, there exist a number of papers that discuss performance
> characteristics of CLOS, and there are also benchmarks out there for
> testing performance of CLOS.
> 
> There is also the related field of partial evaluation which is of
> interest in this regard. Basically, the implementations of virtual
> machines, CLOS, etc., employ (ad-hoc or principled) partial evaluation
> to distinguish between program fragments that can and cannot change at
> runtime, in order to efficiently compile away the static aspects of such
> code. This is related because one can also make optimistic guesses wrt
> to what is static about a code fragment if one is also able to undo
> optimizations and redo the analysis once the assumptions don't hold
> anymore. This is, by definition, a runtime code generation approach.

Those are all sound theoretical reasons why Java should be faster than C++.
That does not provide any evidence that Java implementations are actually
any faster than C++ implementations. Indeed, measurements mostly point to
the contrary.

-- 
Dr Jon D Harrop, Flying Frog Consultancy
http://www.ffconsultancy.com
From: Pascal Costanza
Subject: Re: Eval performance
Date: 
Message-ID: <3slr9uFosi3qU1@individual.net>
Jon Harrop wrote:

> Those are all sound theoretical reasons why Java should be faster than C++.
> That does not provide any evidence that Java implementations are actually
> any faster than C++ implementations. Indeed, measurements mostly point to
> the contrary.

I haven't claimed otherwise, and this was not the topic at hand.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Dr. Thomas Fischbacher
Subject: Re: Eval performance
Date: 
Message-ID: <djv3ng$d5p$1@nwrdmz01.dmz.ncs.ea.ibs-infra.bt.com>
Jon Harrop wrote:

> I'm trying to combine different, interesting tasks into a single
> program. Ultimately, I'm trying to make a benchmark that will show
> Lisp/Scheme in the best possible light.

Gee. Does this actually mean we will see more of your Wikipedia Link 
spam in the articles on Lisp and Scheme in the future as well?

From:

http://en.wikipedia.org/w/index.php?title=Talk:O%27Caml_programming_language&oldid=26697518

===>
On Commercials in this article

Looking at the article in its present state, there are 16 external 
(non-wikipedia) OCaml-related links in it. Seven of them point to 
http://www.ffconsultancy.com, and all of them seem to have been made by 
a user from the IP 80.229.56.224, which resolves to jdh30.plus.com.

Doing a bit of research, this is the machine of the owner of 
ffconsultancy.com, Dr. Jon Harrop. This brings up the question whether 
we actually see here a violation of Wikipedia:What_Wikipedia_is_not 
rules, as this article might be abused for self-promotion and 
advertising issues. Doubly so, as there is quite some consensus of Jon 
Harrop showing quite undue behaviour on the usenet as well as some 
mailing lists, alienating large parts of the functional community.

I therefore strongly suggest deleting all references to 
ffconsultancy.com from the article.

     Motion seconded, carried, and implemented. --MarkSweep (call me 
collect) 22:58, 26 October 2005 (UTC)

I just re-added many of the links before I read this. I am happy to have 
the direct links to commercial products removed (the OCaml book and 
Presenta) if this is against Wikipedia policy (note that Wikipedia 
references many other books though - perhaps we should add a references 
section?). However, I see no sense in removing links to free software 
written in OCaml that happen to be available from the same site, 
particularly the maze generator, ray tracers and example programs from 
scientific computing. I have also added some links to other 
OCaml-related pages. If I can provide any useful information, please 
contact me (the objection was made by 152.78.153.226?). - Jon Harrop 
<···@ffconsultancy.com>.
<===

Jon, maybe you have not noticed yet: there may be some people around who 
think that you do not quite qualify as an expert functional hacker. 
However, you seem to have a 1:10 ratio of producing material - most of 
it of highly questionable quality (and many people did repeatedly tell 
you so) - and advertizing it, sometimes to the borderline of vandalism:

http://en.wikipedia.org/w/index.php?title=Ocaml&limit=20&action=history

# (cur) (last)  20:19, 28 October 2005 MarkSweep (re-added a few links)
# (cur) (last) 20:16, 28 October 2005 MarkSweep m (Reverted edits by 
80.229.56.224 to last version by MarkSweep)
# (cur) (last) 10:23, 28 October 2005 80.229.56.224 (Re-added links to 
freely-available OCaml programs that were removed without adequate reason)
# (cur) (last) 22:57, 26 October 2005 MarkSweep (rm linkspam)
# (cur) (last) 22:54, 26 October 2005 MarkSweep (→External links - rm 
links (FFTW and Unison are not directly relevant here; scientific 
computing link is nothing but an advertisement))

Please also take a look at the ffconsultancy.com links in an older 
version of that article, such as:

http://en.wikipedia.org/w/index.php?title=Ocaml&oldid=26478312

I do not know what your business plan is, but it looks a bit like:

1.: Make a lot of fuss, alienate all the proficient people in the field, 
as well as now the Wikipedians, and see that there is not one left who 
knows about the field but does not know your questionable methods.

2.: ???

3.: Profit.

Huh? I know that internet trolling is a booming business. Could it be 
that you think there is big money to be made in the future by... 
consulting trolls?

-- 
Dr. Thomas Fischbacher
From: Dr Jon D Harrop
Subject: Re: Eval performance
Date: 
Message-ID: <1130583632.074654.101380@g43g2000cwa.googlegroups.com>
Dr. Thomas Fischbacher wrote:
> Jon Harrop wrote:
>
> > I'm trying to combine different, interesting tasks into a single
> > program. Ultimately, I'm trying to make a benchmark that will show
> > Lisp/Scheme in the best possible light.
>
> Gee. Does this actually mean we will see more of your Wikipedia Link
> spam in the articles on Lisp and Scheme in the future as well?

In point of fact, they readded a link to my site (the ray tracer
benchmark). I am more annoyed that they don't want a link to FFTW,
which is probably the most famous software currently written in OCaml.
Anyway, that page is all about OCaml and has nothing to do with c.l.l.

Cheers,
Jon.
From: Rob Thorpe
Subject: Re: Eval performance
Date: 
Message-ID: <1130595778.946459.25950@o13g2000cwo.googlegroups.com>
Dr Jon D Harrop wrote:
> Peter Seibel wrote:
> > Uh, why do you need to use EVAL at all to do symbolic differentiation?
> > Isn't the whole point that it's symbolic?
>
> I'm trying to combine different, interesting tasks into a single
> program. Ultimately, I'm trying to make a benchmark that will show
> Lisp/Scheme in the best possible light.
>
> As other people have already shown, the derivative function in Lisp can
> be written fairly clearly and succinctly (especially compared to C/C++,
> Java etc.) so I think that is a good demonstration of clarity. With
> s-exprs, you don't have the overhead of declaring an expr type in Lisp,
> as I do in the other implementations (including OCaml), and there is
> continuity in the sytax (as opposed to a+b and Plus(a, b) in the ML).
>
> Currently, I'm using a derivative function to differentiate a big
> expression. Then I'm evaluating the derivate at a few points. The Lisp
> uses eval for the evaluation because the derivative function generated
> an s-expr. My other implementations have to include a custom eval
> function, which requires more code and they (typically) cannot compile
> to native code so Lisp should be a lot faster.
>
> However, compilation time is clearly going to be overwhelming (now that
> I've got it "working" I can't actually execute it because compilation
> takes too long and uses too much RAM) because the expression is huge.
> So I need to use small expressions and, preferably, ones with recursive
> functions in them.
>
> To make Lisp look good (assuming the compiled Lisp s-expr will be
> evaluated more quickly than the interpreters written in other
> languages), evaluation must be done much more than all other
> operations. So, perhaps it would be best to symbolically differentiate
> a medium-sized expression and then tabulate it over a large range of
> parameter values, or to ditch symbolic differentiation and write a
> program to evaluate other programs (I think this is a much bigger task
> though, but the results would be much more interesting as well).

Is it a very big expression, is that why the compiler is having a
problem?

It's worth remembering:-
CMUCL and GCL contain an interpreter and a compiler.
SBCL does not, it only has a compiler.  When you type something into
the REPL it compiles in, then executes the compiled code.  I think the
authors did this because they didn't think it was worthwhile to to
maintain the interpreter code.  The interpreter is quite complex and
only really used for a very few things.

If you write a program that generates some lisp code in CMUCL or GCL
you could execute the code by evaling it.  In SBCL it may be more
appropriate to evaluate something like "(defun generated (args)
(...code...))", then call "generated" later in the code.  This will
avoid the compiler compiling it more than once.


I also don't think there's much to be said for writing a program to
make CL look good.  But it is useful to show what things CL is good at.
From: Paul F. Dietz
Subject: Re: Eval performance
Date: 
Message-ID: <0LKdnaAlzqM1G_7eRVn-hQ@dls.net>
Rob Thorpe wrote:

>  The interpreter is quite complex and
> only really used for a very few things.

It's very useful for testing the compiler.  :)

	Paul
From: Rob Warnock
Subject: Re: Eval performance
Date: 
Message-ID: <gsidnR3pA5p1sfneRVn-pw@speakeasy.net>
Rob Thorpe <·············@antenova.com> wrote:
+---------------
| If you write a program that generates some lisp code in CMUCL or GCL
| you could execute the code by evaling it.  In SBCL it may be more
| appropriate to evaluate something like "(defun generated (args)
| (...code...))", then call "generated" later in the code.  This will
| avoid the compiler compiling it more than once.
+---------------

Or simply wrap a LAMBDA around the generated code, eval *that*
[thus compiling it], and then FUNCALL the compiled LAMBDA multiple
times inside the timing loop, thus avoiding polluting the global
namespace with things like GENERATED...

Not that since COMPILE is is allow to (and usually will) return
the same object when given an already-compiled object, if you
further wrap a COMPILE around the EVAL (or the LAMBDA, not sure
it matters much which), you get a version that will "do the same thing"
on both compile-all-the-time and interpret-unless-told-to-compile
implementations (e.g., SBCL vs. CMUCL).


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Rob Thorpe
Subject: Re: Eval performance
Date: 
Message-ID: <1130750334.813272.148300@z14g2000cwz.googlegroups.com>
Rob Warnock wrote:
> Rob Thorpe <·············@antenova.com> wrote:
> +---------------
> | If you write a program that generates some lisp code in CMUCL or GCL
> | you could execute the code by evaling it.  In SBCL it may be more
> | appropriate to evaluate something like "(defun generated (args)
> | (...code...))", then call "generated" later in the code.  This will
> | avoid the compiler compiling it more than once.
> +---------------
>
> Or simply wrap a LAMBDA around the generated code, eval *that*
> [thus compiling it], and then FUNCALL the compiled LAMBDA multiple
> times inside the timing loop, thus avoiding polluting the global
> namespace with things like GENERATED...
>
> Not that since COMPILE is is allow to (and usually will) return
> the same object when given an already-compiled object, if you
> further wrap a COMPILE around the EVAL (or the LAMBDA, not sure
> it matters much which), you get a version that will "do the same thing"
> on both compile-all-the-time and interpret-unless-told-to-compile
> implementations (e.g., SBCL vs. CMUCL).

Good idea.
From: Pascal Costanza
Subject: Re: Eval performance
Date: 
Message-ID: <3smheiFompr0U1@individual.net>
Rob Thorpe wrote:
> Rob Warnock wrote:
> 
>>Rob Thorpe <·············@antenova.com> wrote:
>>+---------------
>>| If you write a program that generates some lisp code in CMUCL or GCL
>>| you could execute the code by evaling it.  In SBCL it may be more
>>| appropriate to evaluate something like "(defun generated (args)
>>| (...code...))", then call "generated" later in the code.  This will
>>| avoid the compiler compiling it more than once.
>>+---------------
>>
>>Or simply wrap a LAMBDA around the generated code, eval *that*
>>[thus compiling it], and then FUNCALL the compiled LAMBDA multiple
>>times inside the timing loop, thus avoiding polluting the global
>>namespace with things like GENERATED...
>>
>>Not that since COMPILE is is allow to (and usually will) return
>>the same object when given an already-compiled object, if you
>>further wrap a COMPILE around the EVAL (or the LAMBDA, not sure
>>it matters much which), you get a version that will "do the same thing"
>>on both compile-all-the-time and interpret-unless-told-to-compile
>>implementations (e.g., SBCL vs. CMUCL). 
> 
> Good idea.

It's important to note that (compile nil `(lambda () (eval 
,some-expression))) is not necessarily more efficient than just (eval 
some-expression). If you perform compilation at runtime, you have to 
take into account that the compilation process itself costs time and 
memory resources. So if the expression you want to evaluate is 
computationally inexpensive and you use it only for one-shot 
computations, then it will probably not pay off to compile it, because 
it is likely that (> (+ (time compilation) (time execution)) (time 
evalutation)). Only if you are reusing the compiled code later on, or if 
it is an expensive computation, the overhead of compilation can be 
compensated for.

BTW, that's the main reason why the performance characteristics of 
runtime code generation cannot be easily shown with small toy benchmarks.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Rob Thorpe
Subject: Re: Eval performance
Date: 
Message-ID: <1130765912.705244.225150@g47g2000cwa.googlegroups.com>
Pascal Costanza wrote:
> Rob Thorpe wrote:
> > Rob Warnock wrote:
> >
> >>Rob Thorpe <·············@antenova.com> wrote:
> >>+---------------
> >>| If you write a program that generates some lisp code in CMUCL or GCL
> >>| you could execute the code by evaling it.  In SBCL it may be more
> >>| appropriate to evaluate something like "(defun generated (args)
> >>| (...code...))", then call "generated" later in the code.  This will
> >>| avoid the compiler compiling it more than once.
> >>+---------------
> >>
> >>Or simply wrap a LAMBDA around the generated code, eval *that*
> >>[thus compiling it], and then FUNCALL the compiled LAMBDA multiple
> >>times inside the timing loop, thus avoiding polluting the global
> >>namespace with things like GENERATED...
> >>
> >>Not that since COMPILE is is allow to (and usually will) return
> >>the same object when given an already-compiled object, if you
> >>further wrap a COMPILE around the EVAL (or the LAMBDA, not sure
> >>it matters much which), you get a version that will "do the same thing"
> >>on both compile-all-the-time and interpret-unless-told-to-compile
> >>implementations (e.g., SBCL vs. CMUCL).
> >
> > Good idea.
>
> It's important to note that (compile nil `(lambda () (eval
> ,some-expression))) is not necessarily more efficient than just (eval
> some-expression). If you perform compilation at runtime, you have to
> take into account that the compilation process itself costs time and
> memory resources. So if the expression you want to evaluate is
> computationally inexpensive and you use it only for one-shot
> computations, then it will probably not pay off to compile it, because
> it is likely that (> (+ (time compilation) (time execution)) (time
> evalutation)). Only if you are reusing the compiled code later on, or if
> it is an expensive computation, the overhead of compilation can be
> compensated for.
>
> BTW, that's the main reason why the performance characteristics of
> runtime code generation cannot be easily shown with small toy benchmarks.

Sure.  My point to Jon was that this doesn't work very well on SBCL,
and using that implementation there's nothing to be lost in compiling
the code since it will be compiled anyway if you use eval.  And, if
it's kept around it may be useful in the future.
From: Marco Antoniotti
Subject: Re: Eval performance
Date: 
Message-ID: <9Su8f.56$pa3.20487@typhoon.nyu.edu>
Peter Seibel wrote:
> "Dr Jon D Harrop" <···@ffconsultancy.com> writes:
> 
> 
>>I'm trying to write a benchmark based on the symbolic differentiation
>>example discussed recently. By using s-exprs, the Lisp implementation
>>should be short and fast. However, I'm having trouble getting good
>>performance using "eval". I believe I need to use compile but I'm not
>>sure how.
> 
> 
> Uh, why do you need to use EVAL at all to do symbolic differentiation?
> Isn't the whole point that it's symbolic?

Because OCaml does not have EVAL (you have to build it from scratch 
using your home-brewed set of types to represent what in Lisp is 
represented by itself) and the OP is ticked by that :)

Cheers
--
Marco
From: Richard J. Fateman
Subject: Re: Eval performance / missing the point?
Date: 
Message-ID: <dl0s1u$1lh4$1@agate.berkeley.edu>
In addition to this code being clumsy, if you are trying to make
it fast, wouldn't you use  ...(safety 0) ...?

If you want to compute the derivative of an expression at a point,
you do not have to cons up the symbolic expression at all.

You could compute (f 2 g) at g=3
and its derivative with respect to g at that point
in approximately 0ms.

<value, deriv>  =<4.434264882430378d+38 , 1.0793576867959292d+41>

I just stuck this definition in to a suitably augmented CL
(generic arithmetic) with g = < 3 , 1>



> 
> (define (f n g)
>   (if (= n 0) g `(expt ,(f (- n 1) g) ,(f (- n 1) g))))
> 
>
>