Hi Timothy,
On Sun, Sep 27, 2009 at 3:17 PM, Timothy Pratley
<[email protected]>wrote:
> 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.
>
As I replied to your comment
http://clj-me.cgrand.net/2009/08/06/what-warn-on-reflection-doesnt-tell-you-about-arrays/#comment-44
here, your timing is dominated by boxed arithmetic. You must also hint i and
j.
Regarding multi-dim arrays, the best way to achieve high performance is to
break access:
(def dd (make-array Double/TYPE 1000 1000))
user=> (time (dotimes [i 1000] (dotimes [j 1000] (aget dd i j))))
"Elapsed time: 455.514388 msecs"
user=> (time (dotimes [i 1000] (dotimes [j 1000] (-> dd (aget i) (aget
j)))))
"Elapsed time: 257.625829 msecs"
user=> (time (dotimes [i 1000] (dotimes [j 1000] (-> #^objects dd (#^doubles
aget i) (aget j)))))
"Elapsed time: 157.095175 msecs"
But since aget is inlined, the #^doubles hint is ignored so let's introduce
a local:
user=> (time (dotimes [i 1000] (dotimes [j 1000] (let [a #^doubles (aget
#^objects dd i)] (aget a j)))))
"Elapsed time: 158.134344 msecs"
No gain because the inlining "ate" the hint. We have to put the hint on
something more stable:
user=> (time (dotimes [i 1000] (dotimes [j 1000] (let [#^doubles a (aget
#^objects dd i)] (aget a j)))))
"Elapsed time: 17.412548 msecs"
It doesn't apply for random access but here we can even put the let out of
the inner loop:
user=> (time (dotimes [i 1000] (let [#^doubles a (aget #^objects dd i)]
(dotimes [j 1000] (aget a j)))))
"Elapsed time: 8.393386 msecs"
The following macro can help:
(defmacro deep-aget
([hint array idx]
`(aget ~(vary-meta array assoc :tag hint) ~idx))
([hint array idx & idxs]
`(let [a# (aget ~(vary-meta array assoc :tag 'objects) ~idx)]
(deep-aget ~hint a# ~...@idxs)))))
user=> (time (dotimes [i 1000] (dotimes [j 1000] (deep-aget doubles dd i
j))))
"Elapsed time: 16.937279 msecs"
hth,
Christophe
--
Professional: http://cgrand.net/ (fr)
On Clojure: http://clj-me.blogspot.com/ (en)
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---