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