Subject: Re: macro question From: Erik Naggum <firstname.lastname@example.org> Date: Sat, 09 Mar 2002 18:14:57 GMT Newsgroups: comp.lang.lisp Message-ID: <email@example.com> * Rolf Wester <firstname.lastname@example.org> | My point is performance. * Erik Naggum wrote: > Are you quite sure about that? * Rolf Wester <email@example.com> | 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.