An alternative to the complexities involved may be to write number-crunching hot spots in Java. Thus I'd add to Tip 10 that it ain't so bad if you exploit some JVM-platform-goodness *you* just wrote; by definition it's not much code, it's much simpler and can be done in a functional style.
On Monday, March 26, 2012 10:40:23 AM UTC-7, Daniel Solano Gómez wrote: > > Hello, > > Having given a talk on precisely this topic at Clojure/West, I may be > able to give you a couple of hints and explanations. You can find the > slides at > < > https://github.com/strangeloop/clojurewest2012-slides/raw/master/Solano-G%C3%B3mez-Crunching-Numbers-with-Clojure.pdf > >, > and I am planning on writing a more detailed set of blog posts over the > next few months. > > > On Mon Mar 26 13:37 2012, Sergey Didenko wrote: > > Hi, > > > > I believe I've heard claims that nothing stops Clojure 1.3 code to be > > made very close to Java in terms of execution speed. > > > > However when trying to match the speed of ad-hoc Heapsort > > implementation I have faced essential obstacles. > > > > Setting type hints and coercions was quite easy. A bit harder was to > > realize that "aset" is much faster than "aset-int" and that "(int -1)" > > inside "if" condition can be faster than "-1". > > You can best understand why these things happen by looking at the > examining the bytecode generated by the Clojure compiler. Just > AOT-compile the code and look at the output of 'javap -c'. > > One of the things you're battling with in your code is Clojure's > 64-bit primitives. If using longs in your application isn't a > deal-breaker, consider making all your primitives 64-bit. This will > eliminate the need of having to do a lot of casting back and forth > between 32-bit and 64-bit integers. > > One additional benefit to using longs is that you can replace all of > your (unchecked-op-int) calls to the plain arithmetic function. For > example, instead of (unchecked-add-int), you can just do (+). When you > set *unchecked-math* to true during compile time, you get the unchecked > long operations. > > > However I'm still far from the Java speed ( 1.5 times slower on a cut > > code - first part of the Heapsort ). > > > > What I can't understand now is why inlining the following function > > makes a noticeable speedup (~20%). Isn't it supposed to be solved in > > 1.3? > > What you're running into is the overhead of get the root value of vars > like swap! and move-up!. The only way to avoid this is use something > like definline. > > > (defn move-up! [^long pos] > > (let [array (ints array)] > > (loop [pos pos ppos (unchecked-divide-int pos 2)] > > (if (or (= pos 0) > > (>= (aget array ppos) (aget array pos))) > > nil > > (do ;(swap! array ppos pos) > > (recur ppos (unchecked-divide-int ppos 2))))))) > > > > I'm attaching the full sources if anyone is interested to measure the > > difference. > > I don't have the time to run your example code, but I hope some of the > above pointers help. > > Sincerely, > > Daniel > > -- 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