not recommended but in case you do need both the lazyness and the dynamic var:
(binding [*boundvar* :a] (map (bound-fn* myfn) [0 1]))Hi, I'm very new to clojure and JVM world. I decided to give clojure a try in one of my pet projects. Generally everything goes well, but there's one part of the project where I need to do some heave numerical calculations. I have reference implementation of that calculation in Rust, I did my best to write the same algorithm in clojure (using clojure.fastmath library for numerical integration and computing gamma function), but no matter how hard I try, the rust implementation is 13 times faster. I turned on warn on boxed math and warn on reflection, ensured that everything is unboxed and all type hints are there, put some memoization of repeating parts, but can't go faster than 13x compared to rust impl. I wonder, did I hit some limitation of clojure/jvm, or is it problem of my implementation specifically? If it's limitation of jvm, then I can just put the algo into a rust binary and call it from clojure, but if it's a problem with my implementation I can try better. From your experience guys, is 13x slowness in numerical tasks typical?
You can achieve comparable results in Clojure, sometimes it requires less idiomatic approach (like reaching for primitive arrays and local mutation). Of course in your case fastmath implementation can be a bottleneck too (however I do my best to optimize critical paths). It would be great to see the code you've produced.
I'll take a look soon! Stay tuned.
First what I see from just looking at the code: you use a map structure on the hot path. I would change it to a custom type and use fields directly as a first optimization step.
yea, that's actually a good point, I will try to do some benches with custom types bit later. Thanks!
You can also ask for help in #C03L9H1FBM4. Whenever I'm trying to optimize code, I almost always start with https://github.com/clojure-goes-fast/clj-async-profiler to find out where the bottlenecks are.
This ^^^
I had a chance to look at this more carefully. n-x function can be called many times during integration (depends on its smoothness) and it should be a target for more agressive optimization. Things like first, nth can be slow, using list/vector for storing numbers always forces boxing. A I mentioned earlier, an access to a map entries also slows down in this case. Some things can be precomputed or pregenerated, for example i-h variable (and i-i second time the same). d, k, i-power , scale are configuration constants, no need to access them every n-x call.
I can help more but I think I need actual input example and expected result to play a little bit with this.