On Jul 7, 5:10 pm, John Harrop <jharrop...@gmail.com> wrote:
> Problem: Passing primitives from an inner loop to an outer loop efficiently.
> Here is what I've found.
>
> The fastest method of result batching, amazingly, is to pass out a list and:
>
> (let [foo (loop ... )
> x (double (first foo))
> r1 (rest foo)
> y (double (first r1))
> r2 (rest r1)
> z (double (first r2))] ... )
>
This isn't suprising if you think about it.
In the list situation you are just grabbing the next pointer,
in an array situation you have to do math to access a vector.
> (here passing out three doubles).
>
> About half as fast is:
>
> (let [[x y z] (loop ... )] ... ) with (double x), (double y), and (double z)
> used later in place of x y z and only one occurrence of each (so no more
> (double foo) conversions than before). The destructuring bind apparently
> exerts a higher run-time overhead compared to manual destructuring.
>
If you look at the source code this isn't that surprising.
The big difference between (for example):
(let [[x y z] [1 2 3]] ...) and
(let [v [1 2 3] x (v 0) y (v 1) z (v 2)] ...)
Most of the slowdown Seems to have to do with bounds checking:
The first is 'safe' and returns nil for out of bounds, the second
throws an exception.
but
If you look at the source the 2ary version of nth gets inlined and the
3ary version (which destructuring bind expands to) does not.
and
if you put a symbol in the second position you'll note that
Destructuring bind rebinds the symbol with a Gensym even though it
cannot suffer from multiple evaluation.
If you look here:
http://gnuvince.wordpress.com/2009/05/11/clojure-performance-tips/
And look at 'avoid destructuring binding for vectors'
I did some hacking and improved the worst case from about 500ms on my
computer to 300ms.
(By inlining the 3ary version and removing the duplication; compiling
a destructuring function without bounds checking breaks compilation
for obvious reasons...). There are probably better ways to optimize it
as this was just me screwing around ('What can i break this
evening?').
I will note that there is something very funny going on with the
destructuring/binding example in the link above. The fast version on
my machine returns every number of times(1e7 1e8 1e9 etc...) returns
26 ms. It is kind of like it all just got collapsed into a constant.
--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---