4 ms·
Julia is my tool of choice for writing numerical code where performance is critical. I work in computational physics, and have found Julia and its ecosystem to
by kbarros 2y ago
Julia is my tool of choice for writing numerical code where performance is critical. I work in computational physics, and have found Julia and its ecosystem to be far nicer than Rust in this space.
It's true that accidental dynamic behaviors are a real concern and can be a performance killer. Fortunately, the language has nice tooling. In VSCode, I often use the visual profiling tool `@profview` to get a flame graph. Anything dynamic gets highlighted in red, and is quick to diagnose. There also exist nice static analysis packages like JET.jl. During development, one can use `report_opt` to statically rule out accidental dynamical behaviors. Such checks can also be incorporated into a project's unit tests. In practice, it's not much of an issue for me anymore. But to be fair, there is a big learning curve for new Julia users. See, e.g., https://docs.julialang.org/en/v1/manual/performance-tips/ https://docs.julialang.org/en/v1/manual/performance-tips/
- catgary 2y agoThose tools didn’t actually exist the year or so I was writing Julia professionally (and that was only 3 years ago) so it’s nice to see the language coming along. At the same time, I would expect the Rust ecosystem to overtake Julia’s in that domain in the next couple of years. Polars is already nicer than pandas, I’ve seen a some promising work on numpy-style tensor libraries, and I’m pretty impressed by the progress with getting enzyme integrated into Rust (I could never make it work with Julia). Here’s a nice example repo I saw recently: https://github.com/ChemAI-Lab/molpipx/ https://github.com/ChemAI-Lab/molpipx/
- thunkingdeep 2y agoNot the person you’re respond to, but Rust is never going to have a REPL and is likely to never compile very quickly. For a lot of numerical and scientific use cases that’s a fundamentally restraining factor. WRT performance, you’re ofc correct but that’s not always as paramount as it may seem if you need to tweak the data dozens or hundreds or thousands of time. In that case, having to wait more than say 5 seconds or so is prohibitively annoying. I think something in between Zig and Rust will emerge someday as a sort of optimal compromise between compile speed, safety, and programmability wrt memory and performance tradeoffs.
- catgary 2y agoIt is really easy to write python bindings for Rust, which is probably the easiest way to “consume” a high-performance library (e.g. a physics simulator, data-frames, graphing, a type-checker, etc).
- xgdgsc 2y agoNot easier than https://github.com/Suzhou-Tongyuan/jnumpy https://github.com/Suzhou-Tongyuan/jnumpy
- catgary 2y agoRight, but Julia is just not terribly well-suited for large scale software development, which is why I’d rather use Rust.
- kennysoona 2y ago> Julia is just not terribly well-suited for large scale software development Why not and how so?
- kbarros 2y agoI'll speak as someone who began as a Julia skeptic, but now finds it invaluable for my day-to-day work. Here are some reasons why you might prefer Rust today: - Julia's lack of formal interface specification. Julia gets a lot of flexibility from its multi-method dispatch. This feature is often considered a major selling point in allowing code reuse. Many Julia packages in the ecosystem can be combined in a way that "just works". Consider, for example, combining CuArrays.jl with KrylovKit.jl to get GPU acceleration of sparse iterative solvers (https://github.com/Jutho/KrylovKit.jl/issues/15 https://github.com/Jutho/KrylovKit.jl/issues/15). But it's not always clear who actually "owns" such integrations. Because public interfaces aren't always well documented in Julia, things are prone to breakage, and it can sometimes feel like "action at a distance". This was especially painful with the OffsetArrys.jl package, which suddenly introduced arrays that could begin at any integer index. (That was the major theme of Yuri's blog post, and the simple solution for most people was to avoid OffsetArrays.) Rust's community philosophy and formal trait system err on the side of providing static guarantees for correctness. But these constraints also take away flexibility to fit distinct packages together. For example, Julia has always had excellent support for type specialization, and this has been notoriously challenging to fit into Rust, even in a very limited form: https://users.rust-lang.org/t/the-state-of-specialization/113560 https://users.rust-lang.org/t/the-state-of-specialization/11.... Conversely, there have been many discussions about designing a formal interface system in Julia, but it remains a challenge: https://discourse.julialang.org/t/proposal-adding-optional-static-interface-traits-checking-to-julia/125846 https://discourse.julialang.org/t/proposal-adding-optional-s... - Julia is designed around just-in-time compilation. For example, every time a function is called with new argument types, it will be freshly compiled for that specialization. This is great when you care about getting optimal performance. Also, because Julia allows to reify syntax as value-level objects, you can assemble Julia code that is custom optimized to run-time values. All of this is amazingly powerful for certain kinds of number crunching codes. But carrying around a full LLVM system is clearly a blocker for distributing small, precompiled binaries. Hence the LWN discussion about the preview juliac feature, which will offer a mode for fully static compilation. - Rust's borrow checker is something to envy. In any other language, I miss the ability to safely passing around references to stack allocated variables, or to know that a referenced value cannot be mutated. Finally, I would probably recommend Python (not Rust!) for most machine learning or data analysis projects that aren't too "bespoke". There's just so much momentum behind PyTorch and JAX. The Julia community is developing some very interesting packages in this space. Notably, Lux.jl, Enzyme.jl, Reactant.jl, and all of SciML. These are super powerful, but still very researchy. For simple things, Python will probably be less friction. The best language will depend on your use case. Julia serves its niche very well, even if it doesn't fit every possible use case.
- thetwentyone 2y agoAnother tool in this regard is https://github.com/JuliaLang/AllocCheck.jl https://github.com/JuliaLang/AllocCheck.jl, "a Julia package that statically checks if a function call may allocate by analyzing the generated LLVM IR of it and its callees using LLVM.jl and GPUCompiler.jl"