Subject: Re: macro question
From: Erik Naggum <erik@naggum.net>
Date: Sat, 09 Mar 2002 18:14:57 GMT
Newsgroups: comp.lang.lisp
Message-ID: <3224686506363980@naggum.net>

* Rolf Wester <wester@ilt.fhg.de>
| My point is performance.

* Erik Naggum wrote:
> Are you quite sure about that?

* Rolf Wester <rolf.wester@t-online.de>
| I know that in the  CL community performance isn't considered to be a
| serious design goal.

  Then you "know" wrong.  You also read what I wrote completley wrong, for
  which you may easily be forgiven: Your point seemed to be do it Your Way.

  Performance is vitally important and a veyy serious design goal of the
  serious developers , but it so happens that it is not at the top of the
  list: Correctness is more important than performaing incorrectly faster.
  C++ has a slightly different priorities.  _Java_ is fairly accused of not
  having performance as a serious design goal, but some people still have.

| I would be happy if perfomance wouldn't be so important in many of my
| projects.

  I am puzzled by your use of CLISP if you want performance.  It has a very
  peculiar performance profile, and no tools to help you discover where to
  optimize your code.  Use a commercial Common Lisp implementation like
  Allegro CL or LispWorks if you want the kind of performance that others
  are willing to pay for.

| The program is written in C++ and a run takes about a day.

  Yikes.

| I would really prefer to do it in CL but even the fastest CL
| implementations I tested where about five times slower in floating point
| operations compared to C++.

  Which CL implementation was that?  Did you declare the types of all
  relevant variables to be doublt-float?  (It does not matter in CLISP, but
  both CMUCL and Allegro CL benefit greatly from such declarations.)

| This would mean not 1 day but 5 (roughly estimated).

  Well, gee, I have almost 2GHz of spare CPU power at any time, and you
  have none?  :)  Seriously, if it is possible to divide up your problem
  into separately calculable chunks, like the SETI project does, you could
  use some of the amazing amount of unused cycles around the world, or just
  your lab.

| And presently I'm using only a simplified discharge model. In the general
| case it would take to long to be practical even using C++. Of course
| using Fortran (which I seriously considered) or Assembler (which is
| beyond my skills) would make my code faster,  using C++ is a trade off
| between performance and expressive power.

  It might be possible to write much more complex (and faster) C++ with
  Common or Emacs Lisp, or even to write C code so you could write code
  that would be impossible to maintain manually.  When I had to work with
  C++ (fall of 1993), it was so painful for me that I wrote a lot of Emacs
  Lisp code to produce C++ for me.  This turned out to be a good basis for
  my transition to Common Lisp after I had made up my mind never to waste
  my time on anything so ill-designed as C++ again.  (Things may have
  changed.  Nobody I trust think I would be any happier with C++ today. :)

| In the actual problem performance isn't really a big problem.

  One of the solutions to performance is not to do so much work.  You could
  refactor your algorithms so you keep a large number of intermediate
  results around.

| But the function  will be called thousands of times.  The time difference
| between calling the original function with three parameters and the
| closure that only has one parameter is a factor of 3. Maybe this isn't
| worth the effort.

  It appears to me to be smarter to compute and pass c1 and c2 to such a
  function than passing temp and m.  You could also obtain unboxed floating
  point calculations by not calling any user functions in your code.  This
  is sometimes extremely useful advice despite the high overhead of coding
  in this style.  But if a single run takes a day, you have time to tinker
  with the code, too.

| Is this pratical for functions with a very large number (1e6 -1e7) of parameter
| combinations?

  That is irrelevant.  It might be useful to store the mapping from a set
  of parameters to the result of a function call in an external database,
  as long as it takes longer to compute than to fetch a pre-computed value,
  even with billions of operations.  E.g., a caching DNS server for a web
  crawler has a tremendous amount of time available to optimize and keep
  around old values, compared to the time and bandwidth cost of using the
  DNS to find a non-expired value.  (Some hobbyist DNS implementations, one
  in Common Lisp, violate the expiration time to save you the trouble of
  getting correct results when a site changes address.  This is the wrong
  kind of optimization.)

| Using CLISP it is about as fast as calling a closure either created by a
| function or a macro.  I will also try it with CMUCL.

  Please do.  CLISP is not a performance-oriented implementations, although
  its internal performance is good enough that it offsets the slow byte
  code interpreter somewhat.  (It would be interesting to make a JIT
  compiler for CLISP.)

| Thanks for your helpful reply (load-time-value was new to me, and I guess
| there are quite a number of other CL functions/forms that I'm still not
| aware of).

  My pleasure.  One of the nice things about Common Lisp is that it is
  nearly sufficient to learn the language from the specification -- you do
  not need a large number of books about how to use it because of all the
  idioms you have to master, as well.

///
-- 
  In a fight against something, the fight has value, victory has none.
  In a fight for something, the fight is a loss, victory merely relief.