On Sep 27, 9:17 am, Timothy Pratley <timothyprat...@gmail.com> wrote:
> 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.
>

Hello friend,

The time difference you are seeing between the 2-d version and the 1-d
version is actually due to in-lining...
If you try, for example:

(defn aget
       "Returns the value at the index/indices. Works on Java arrays
of all
  types."
       {:inline (fn ([a i] `(. clojure.lang.RT (aget ~a ~i)))
                  ([a i & idxs]
                     (reduce (fn [inner idx] `(aget ~inner (int ~idx)))
                             `(aget ~a (int ~i)) idxs)))
        :inline-arities #{2 3 4 5 6 7} ;; actually i used a special 'all-
arities' set here
       ([array idx]
          (clojure.lang.Reflector/prepRet (. Array (get array (int idx)))))
       ([array idx & idxs]
          (apply aget (aget array (int idx)) idxs)))
and rebuild core...

I got results like so:

(time (doseq [i (range 100), j (range 100)] (aget a i j)))
"Elapsed time: 27.410739 msecs"

(time (doseq [i (range 100), j (range 100)] (aget b (int (+ i (* j
100))))))
"Elapsed time: 28.009345 msecs"

I don't really have any idea about the other stuff.
--~--~---------~--~----~------------~-------~--~----~
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