As far as I can tell there is currently no way to hint 2d array access
fast
(def a (make-array Double/TYPE 100 100))
(time (doseq [i (range 100), j (range 100)] (aget a (int i) (int j))))
"Elapsed time: 836.800335 msecs"
I can't find any combination of type hinting to speed it up.

However with a trivial change to core.clj [just added (int idx) in the
multi-arg case]:
>   (apply aget (aget array (int idx)) idxs)))
(time (doseq [i (range 100), j (range 100)] (aget a i j)))
"Elapsed time: 40.162875 msecs"
It is fast! Yay!

That's great, almost as fast as a 1d array:
(def b (make-array Double/TYPE 10000))
(time (doseq [i (range 100), j (range 100)] (aget b (int (+ i (* j
100))))))
"Elapsed time: 27.701047 msecs"
But still it seems for maximum speed you would go with a 1d array.

Now for 1d arrays, the index also cannot be anything other than an
integer, so we could do the same thing [just added (int ~i)]:
  {:inline (fn [a i] `(. clojure.lang.RT (aget ~a (int ~i))))

(time (doseq [i (range 100), j (range 100)] (aget b (+ i (* j 100)))))
"Elapsed time: 27.701047 msecs"
Great, it is just as fast as when we had to coerce to int.

But the coercion comes at a small cost when we don't need it:
(time (amap b idx ret (aset ret idx (inc (aget b idx)))))
original:  "Elapsed time: 23.06673 msecs"
modified: "Elapsed time: 27.457263 msecs"  <-- slower :( :( :(

So for the 1d case for maximum speed it appears better to leave it to
the user to coerce when necessary. The index must be an integer - is
there any way to have this fast in both cases? If not another
alternative would be to have an aget* and aget be a macro that
coerces, to allow both forms.

For multi-dimensional it appears the coercion must (and should) happen
in core?


Then I came across this post by cgrand:
http://clj-me.cgrand.net/2009/08/06/what-warn-on-reflection-doesnt-tell-you-about-arrays/
Indicates that type-hinting the array itself can provide a significant
speed-up, but I don't understand why, is this just more reflection or
is something else going on here?

In theory it should be possible to create a macro that creates
automatically type-hinted arrays (seeing the type is passed in) the
trick being to convert the type to a hint string. How would I do that?


And finally, it is actually faster to have an array of Objects and
store doubles in them than to use an array of doubles (due to boxing I
think). In my experimentation about 10% faster. Presumably an array of
doubles would be far less memory however.
(time (let [a #^"[Ljava.lang.Object;" (make-array Object 100)]
(dotimes [i 10000000] (aget a (int (rem i 100))))))
"Elapsed time: 3825.546843 msecs"
(time (let [a #^doubles (make-array Double/TYPE 100)] (dotimes [i
10000000] (aget a (int (rem i 100))))))
"Elapsed time: 4246.330734 msecs"


I know micro-benchmarks can be misleading, thanks for reading - please
point out any errors I've made.


Regards,
Tim.

--~--~---------~--~----~------------~-------~--~----~
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to