I wrote a lisp interpreter, and I'm now finding that speed is
becoming important for me. Could any one supply me with
info on what order of magnitude speed up I can expect
(roughly) when I add in a byte-code compiler? (I do want to
keep it portable...)
Thanks in advance.
Ayal Pinkus
I wrote a lisp interpreter, and I'm now finding that speed is
becoming important for me. Could any one supply me with
info on what order of magnitude speed up I can expect
(roughly) when I add in a byte-code compiler? (I do want to
keep it portable...)
Thanks in advance.
Ayal Pinkus
If what you mean by byte-code compiler is that the compiler generates byte
codes that are then interpreted by a byte-code interpreter, then you could
get Emacs (free). Emacs implements a byte-code compiler and interpreter.
You could compare test code using your interpreter then with Emacs, which is
probably (my guess) as fast as your going to get for a p-code interpreter
(anyone know differently?).
I recommend that you FTP Emacs 19 as it includes a pretty full Common Lisp
addition. You can FTP Emacs 19 from site prep.ai.mit.edu in directory
pub/gnu .
--
William P. Vrotney - vro...@netcom.com
>I recommend that you FTP Emacs 19 as it includes a pretty full Common Lisp
>addition.
Note, however, that elisp (Emacs Lisp) is not lexically scoped, so you
won't have closures. You get the CL extensions by doing (require 'cl);
they are not in the default environment in either GNU Emacs or XEmacs.
XEmacs 19.13 also has CL-style backquote in the default
environment. You can get a version of backquote in GNU Emacs via
(require 'backquote), but (at least in 19.27) it is quite a bit
different than CL-style backquote. Finally, XEmacs lets you do
#'(lambda ...) so that the lambda gets byte-compiled, but you still
don't get closures, and #'foo looks up the definition of foo at
runtime, unlike in CL where you get the definition at compile time.
Thus:
(defun foo () "Foo")
(setq test #'foo)
(funcall test) --> [CL and elisp] "Foo"
(defun foo () "Bar")
(funcall test) --> [elisp] "Bar"
[CL] "Foo"
Cheers-
- Marty
(proclaim '(inline skates))
Well, it's not like a real common lisp. You're probably much better off with
CLISP.
] Note, however, that elisp (Emacs Lisp) is not lexically scoped, so you
] won't have closures. You get the CL extensions by doing (require 'cl);
Actually you do get closures, but you have to use lexical-let rather than let.
Those closures are a bad hack, but it works.
And generally the CL support in emacs is slow (elisp is not a speed deamon, but
it's worse when you add the CL layer on top of it).
Stefan
| I wrote a lisp interpreter, and I'm now finding that speed is becoming
| important for me. Could any one supply me with info on what order of
| magnitude speed up I can expect (roughly) when I add in a byte-code
| compiler? (I do want to keep it portable...)
take a look at CLISP. it compiles to a reasonably fast byte code.
ftp://ma2s2.mathematik.uni-karlsruhe.de/pub/lisp/clisp or see the FAQ.
#<Erik 3020494548>
--
there's a car that has more computing power than it took to get man
to the moon: the BMW 750. but _you_ are stuck here on earth. haha.
| XEmacs 19.13 also has CL-style backquote in the default environment.
so did Emacs 19.29 (released 1995-06-21).
| Finally, XEmacs lets you do #'(lambda ...) so that the lambda gets
| byte-compiled, but you still don't get closures, and #'foo looks up the
| definition of foo at runtime, unlike in CL where you get the definition
| at compile time.
I didn't know that XEmacs had #'. I proposed adding it to Emacs because I
wanted to make it easier to make lambda forms compilable (seeing how so few
Emacs Lisp programmers know how to do this right). RMS convinced me it was
not a good idea when I admitted that #'foo meant (symbol-function 'foo) in
CL and not in the proposed Emacs syntax change. however, this is not an
entirely sound argument. (function 'foo) in Emacs and Common Lisp is the
real difference, while #'foo would mean (function 'foo) in both syntaxes.
#<Erik 3020520968>
> I wrote a lisp interpreter, and I'm now finding that speed is
> becoming important for me. Could any one supply me with
> info on what order of magnitude speed up I can expect
> (roughly) when I add in a byte-code compiler? (I do want to
> keep it portable...)
>
This is a recent post to the genetic programming mailing list. It briefly
describes Marc Feeley's approach of compiling with closures.
;;; Here is some Common Lisp code that outlines some evaluation strategies
;;; that can be useful in genetic programming. The approach used here
;;; basically follows the approach in Koza's first book.
;;; For example, say we have some data:
(setq data '(1.0 2.0 3.0))
;;; and we'd like to evaluate the expression, EXP, which was generated by a
;;; genetic program:
(setq exp '(+ (* 3.0 (square x)) 2.0))
;;; Here we use Lisp s-expressions, but the follow ideas work for other
;;; data structures as well.
;;; How the expression is evaluated is a major performance issue in genetic
;;; programming. See for example, ftp: openmap.bbn.com: pub/kanderson/
;;; faster94/faster94/postscript/profile.ps
;;; Here are 4 approaches to EVAL. The fourth one, gp-eval-3, uses the
;;; closure compiler idea of Marc Feeley, which is the main point of this
;;; message. This compiler is very fast and can do some very useful
;;; optimizations. I have not used this in a genetic programming
;;; application, i thought the idea was worth sharing.
;;; While the examples are in Lisp, the ideas can be ported to other
;;; languages, perhaps with a bit more work.
(defun square (x) (* x x))
(defun gp-eval-0 (data exp)
;; Use Common Lisp's EVAL.
;; Problem: EVAL is too general.
(mapcar
#'(lambda (x)
(declare (special x))
(eval exp))
data))
(defun gp-eval-1 (data exp)
;; Use COMPILE and FUNCALL instead of EVAL.
;; Problem: Combined time of COMPILE + N*FUNCALL can be larger than N*EVAL.
(let ((f (compile 'nil `(lambda (x) ,exp))))
(mapcar f data)))
(defun gp-eval-error (exp) (error "Can't handle ~a" exp))
(defun gp-eval-2 (data exp)
;; Use specialized version of EVAL
;; Problem: still must recursively EVAL EXP.
;; Could do a data parallel version.
;; Could unroll the recursion.
;; Could use a variable stack rather than recursion.
(labels
((eval (x exp)
(cond ((eq exp 'x) x)
((consp exp)
(case (car exp)
(+ (+ (eval x (cadr exp)) (eval x (caddr exp))))
(* (* (eval x (cadr exp)) (eval x (caddr exp))))
(square (square (eval x (cadr exp))))
(t (gp-eval-error exp))))
(t exp)))) ; Constant.
(mapcar #'(lambda (x) (eval x exp)) data)))
(defun gp-eval-3 (data exp)
;; Use closure compiler.
;; Could perform optimizations by adding more cases, like (+ x <constant>).
;; Memoizing would be very useful in a gentic program.
;; Could evolve compiled code directly.
;; Can be used in languages that do not have closures.
(macrolet
((code (form) `#'(lambda (x) ,form))
(call (code) `(funcall ,code x)))
(labels
((gen (exp)
(cond ((eq exp 'x) (code x))
((consp exp)
(case (car exp)
(+ (let ((a (gen (cadr exp)))
(b (gen (caddr exp))))
(code (+ (call a) (call b)))))
(* (let ((a (gen (cadr exp)))
(b (gen (caddr exp))))
(code (* (call a) (call b)))))
(square (let ((a (gen (cadr exp))))
(code (square (call a)))))
(t (gp-eval-error exp))))
(t (code exp)))))
(let ((f (gen exp)))
(mapcar #'(lambda (x) (call f)) data)))))
--
Ken Anderson
Internet: kand...@bbn.com
BBN ST Work Phone: 617-873-3160
10 Moulton St. Home Phone: 617-643-0157
Mail Stop 6/4a FAX: 617-873-2794
Cambridge MA 02138
USA
Results may vary depending on consing and whether or not your binary
has generational garbage collection. Also, some parts of the runtime
are faster than others (some are written in C, some are written Lisp).
Obviously, the C parts don't have the bytecode interpreter overhead.
This is a recent post to the genetic programming mailing list. It briefly
describes Marc Feeley's approach of compiling with closures.
The book "On Lisp" by Graham has nice coverage of this kind of technique.
(I don't think it is what the original poster was asking for when
he mentioned byte compilers, but it is useful in other situations...)
Sadly, most of my code does intensive file processing, and so the
increased performance you should get from compiling with CLISP isn't
as great as with some other programs. So, I agree with you about the
advantages of compiling CLISP code, and CL code in general, but for
file processing, I've been tempted to turn to other Lisps for writing
and running my file utilities.
--
<URL:http://www.demon.co.uk/community/index.html>
<URL:http://www.enrapture.com/cybes/namaste.html>
"You can never browse enough."