Hi Ranjit,
The big perf differences you're seeing are due to reflective calls.
Getting the Java array bits properly type-hinted is especially tricky,
since you don't always get good reflection warnings.
Note that aset is only fast for reference types:
user> (doc aset)
-------------------------
clojure.core/aset
([array idx val] [array idx idx2 & idxv])
Sets the value at the index/indices. Works on Java arrays of
reference types. Returns val.
So, if you want to speed things up ... here's your starting point:
user> (set! *warn-on-reflection* true)
true
user> (import java.util.Random)
(def r (Random. ))
(defn next-gaussian [] (.nextGaussian r))
(defn gaussian-matrix1 [arr L]
(doseq [x (range L) y (range L)] (aset arr x y (next-gaussian))))
(defn gaussian-matrix2 [L]
(into-array (map double-array (partition L (repeatedly (* L L)
next-gaussian)))))
Reflection warning, NO_SOURCE_FILE:1 - reference to field nextGaussian
can't be resolved.
user> (do (microbench (gaussian-matrix1 (make-array Double/TYPE 10
10) 10)) (microbench (gaussian-matrix2 10)) )
min; avg; max ms: 2.944 ; 4.693 ; 34.643 ( 424 iterations)
min; avg; max ms: 0.346 ; 0.567 ; 11.006 ( 3491 iterations)
;; Now, we can get rid of the reflection in next-guassian:
user> (defn next-gaussian [] (.nextGaussian #^Random r))
#'user/next-gaussian
user> (do (microbench (gaussian-matrix1 (make-array Double/TYPE 10
10) 10)) (microbench (gaussian-matrix2 10)) )
min; avg; max ms: 2.639 ; 4.194 ; 25.024 ( 475 iterations)
min; avg; max ms: 0.068 ; 0.130 ; 10.766 ( 15104 iterations)
nil
;; which has cut out the main bottleneck in gaussian-matrix2.
;; 1 is still slow because of its array handling.
;; here's a fixed version:
user> (defn gaussian-matrix3 [^doubles arr ^int L]
(doseq [x (range L) y (range L)] (aset-double2 arr (int x) (int
y) (.nextGaussian ^Random r))))
#'user/gaussian-matrix3
user> (do (microbench (gaussian-matrix1 (make-array Double/TYPE 10
10) 10)) (microbench (gaussian-matrix2 10)) (microbench (gaussian-
matrix3 (make-array Double/TYPE 10 10) 10)) )
min; avg; max ms: 2.656 ; 4.164 ; 12.752 ( 479 iterations)
min; avg; max ms: 0.065 ; 0.128 ; 9.712 ( 15255 iterations)
min; avg; max ms: 0.000 ; 0.035 ; 10.180 ( 54618 iterations)
nil
;; which is 100x faster than where we started.
A profiler is often a great way to figure out what's eating up time.
Personally, I've never found the need to use a disassembler.
Cheers, Jason
--
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