Michael Gardner wrote:
As a style issue I'd suggest using inc, dec, neg?, pos?, and zero? instead of the
various (+ x 1), (< x 0), etc. in your code. This actually seems to improve
performance a bit on my laptop, but it's nothing amazing. To get good performance
you're likely going to need to do some type hinting.
Thanks for the style suggestion, this is something I will use. I have
been playing a little with type hinting without much improvement. It is
perfectly possible I have done it wrong, but my algorithm is not that
intensive in integer arithmetic. My Java version with Integers instead
of ints (still using arrays) is some 4 times slower than the Java
version with ints and arrays, but still some 40 times faster than my
original Clojure attempt.
Luke VanderHart wrote:
I can't see your code due to the IT policies here, but I can make some
generalizations - these are assuming your code is correct and you're
not accidentally using an exponential algorithm (which I wouldn't
preclude, 4 minutes does sound truly excessively slow, even for
vectors).
Well, actually it is 4 seconds, if it was 4 minutes I would have been
too embarrassed even to
ask for help ;-)
Vectors are significantly slower than Java arrays due to their copy-on-
write semantics.
You have a few options, both of which are considered perfectly
acceptable Clojure for high-performance numerical code:
1. Use transients (http://clojure.org/transients) when you update your
vectors. This should give you a pretty significant speed increase.
2. Alternatively, use native java arrays. Clojure provides a complete
set of functions for creating and mutating raw Java arrays
3. Use type hints to eliminate reflection at choke points in your
processing.
It seems 2 and 3 must be in my to-learn list inmediately. Transients
look like a little bit
"advanced Clojure" for me now... :-)
Thank you.
Igor Rumiha wrote:
Here is a version that is approx 10 times faster: http://snipt.org/Olml
The code structure is basically the same but it uses integer arrays
for storage, some manual inlining and lots of type casts. I'm not
certain it _works_ correctly, but... :)
You did not have to do that, a simple "try with native Java arrays"
would have been
enough for me to do my homework. Any way, I truly appreciate your
effort... :-)
My observations:
- use the profiler. jvisualvm that comes with the sun JDK has received
some much needed love recently (especially in java 1.6.0_20) and has
helped me alot in profiling the code. Install an additional plugin:
Sampler. It is has a much lower overhead compared to the Profiler
plugin that is installed by default. Both are useful, though.
- native clojure data structures (seqs, vectors, maps, etc.) are slow
(compared to native Java arrays for instance). There is no going
around that. Immutability and other very nice features come with a
price. Dynamic languages are also, by their nature, slower than their
static companions.
- jvisualvm shows that in my version 40% - 50% of the time is spent in
the ur-8neigh-minmax function. That time is further split into array
fetches, casts to int, arithmetic (inc, dec, add, multiply,
comparisons). I simply don't know how to optimise that further without
changing the algorithm. On that note, the Clojure compiler and core
libraries are getting better: http://snipt.org/Olmn Current Clojure
1.2.0 gives approx 10% better results.
I have never been a "man of profilers", so I do not have experience with
them. Maybe another
thing for my to-learn list. Yes, that function is called once per every
cell in the CA, and reads
the value of every neighoubr of that cell, so it is quite natural it
takes most of the time. The
truth is that I am a bit surprised it is just 40-50 percent of the time,
I would have guessed it
was more. I'll have to think about it...
Hope this helps... :)
It helps, thank you very much :-)
Laurent Petit asked:
If you change the size of your CA, is the ( java time / clojure time
ratio ) roughly constant ?
Not really sure. For instance, in Java (array of ints) a 2000x2000 CA is
updated
in some 180 ms. (the 500x500 was 16ms, but I measured it with
System.currentTimeMillis(), which
is not very precise with that short periods of time) and in Clojure the
2000x2000 CA
is updated in 98 secs some times and up to 150 s. other times (the
500x500 was 4 secs),
but I have just measured it in my home laptop, so it is really not fair
to compare with my
original measurement at my work desktop. I will make some more tests
tomorrow if I can,
bur for now I would say that in the worst case my Clojure algorithm may
be slightlly worse than
the one I have implemented in Java (that it is the basic one you would
apply after
taking "Programming 101").
Thanks to all of you for your interest, I will inform of any further
advance...
:-)
Rubén
--
Rubén BÉJAR HERNÁNDEZ
Dpto. de Informática e Ingeniería de Sistemas - Universidad de Zaragoza
(Computing and Systems Engineering Department - Universidad de Zaragoza)
c/ María de Luna 1, 50018 Zaragoza, Spain
Tel: (+34) 976 76 2332 (Fax: 1914)
e-mail: rbe...@unizar.es
Grupo IA3 (IA3 Laboratory) - http://iaaa.cps.unizar.es
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en