Comparison of Rust to Julia for scientific computing?

I had some students come ask me about implementing material from my numerical analysis course (which used Julia) in part of their Rust student group. I’m not an expert, but my feeling is that Rust is a “safer” language, which to me means it must be slower. That is, Rust is designed for “systems” where safety is more important than speed. Also, I believe the landscape for scientific computing packages in Rust is no where as developed as compared to Julia.

Anyone with more experience with Rust know if my intuition is correct? I’d hate to be unnecessarily discouraging to students trying to be proactive.

2 Likes

It’s safer for concurrent (and some more stuff than e.g. C) and I believe that part just works, and doesn’t make for slower. Julia and other languages with garbage collection (GC), are already safe regarding memory-handling, getting rid of some issues manual memory management has, and Rust does things differently, without GC, also in a safe way, unlike most languages without GC. I believe that neither makes for slower. I suppose Rust has bound-checking, by default, just as Julia, and that does make for slower, unless you opt out. Julia is the only language I know of that allows for doing that locally (plus globally), but I don’t know how Rust does it. It does allow for all safety off, so you can have full C speed (in parts of your code, then must be careful there).

Note also there’s a package for Rust to call Julia. I.e. then Rust is the “driver language”, and the package allows for bidirectional calling. Also you can have Julia as your main language, calling C, or Rust (I understand Rust allows for “extern C”, same as you can do for C++, there at least non-ideal, which you would use, and have to use in that case).

5 Likes

Non-scientific evidence seems to favor Rust slightly.

As Julia’s is in comparison to Python?

Edit: improved the reference.

1 Like

I would not say python is more developed for writing scientific computing. It’s more developed as a user (eg if you want to use Fenics/Firedrake there’s no Julia equivalent but there is a lot more for writing sci comp algorithms)

Rust is on par with C and C++ when it comes to speed. The language’s main selling point is that its safety is achieved in a way that incurs minimal performance cost.

Your intuition about the maturity of the scientific computing ecosystem is spot on, though. Are we learning yet? is a website dedicated to providing status updates on Rust’s Machine Learning capabilities. It shows that there are a lot of basics which are missing or incomplete.

Another disadvantage of Rust is that the language’s syntax is not designed with scientific computing in mind. This will be a major leg up for Julia even when(/if) Rust’s scientific computing ecosystem matures.

Lastly, Rust’s safety comes at a cost to the developer (because of the time spent wrestling with the borrow checker), and I’m not sure you get nearly as much payoff for that effort in your own scientific computing projects as you would in a systems application. Rust might save some companies from a 3 AM phone call from a distressed client, but you don’t get those anyway if you aren’t shipping your code for production use.

So, my two cents would be that you should use Julia instead of Rust for scientific computing projects unless you need a binary executable or just really want to learn Rust.

17 Likes

Interesting. Do you have a simple explanation how it can be safe and fast? @inbounds is an essential to get good performance in Julia so I don’t understand why Rust would be different.

1 Like

Type systems allow the compiler to derive program invariants…

1 Like

Interesting challenge. I won’t be able to do it justice here, but I’ll share a few thoughts.

In short, Rust does as much safety work as possible at compile time. The language is designed around this goal, in much the same way that Julia is designed to facilitate fast runtime execution at the cost of upfront compilation time. It does this by incorporating a language-level notion of ownership that allows the compiler to prevent race conditions, stop you from accessing freed memory, etc.

There are some things that cannot be handled at compile time, like array bounds checking, at least in certain cases. So there are some runtime checks, and they do incur some runtime cost. However, the ownership model gives the compiler leverage to apply optimizations which would not be available in an unsafe language like C or C++, particularly as it pertains to parallelization. So on average you get similar performance, with C++ being slightly faster in some benchmarks, and Rust being faster in others. (You should take these last two sentences with a grain of salt, because I don’t have the experience to make these assertions unequivocally.)

7 Likes

To me “scientific computing” is almost synonymous with arrays. So when you say it can’t handle array bounds checking that means it can’t do scientific computing efficiently…

3 Likes

Rust is a fine programming language. It’s not interactive though, so it really boils down to the question of “why doesn’t everyone use C, C++, or Fortran for scientific computing?” The answer is that people did, they tried it for years, but found that interpreters and REPLs are a really nice thing to have. Going to compile a binary to just see the difference of one argument change in a plot (meaning re-running code, or remembering to write things out to files, etc.) is a major painpoint to actually doing research. So a language that mixes interactivity with compilation (Julia), fills a nice role in here.

You can of course go into some deeper compiler and performance details, but I think all of those will miss the point that many people will even choose MATLAB/Python/R over Rust simply because this workflow matches what a lot of what scientists are looking for. The question for Julia is to give a Rust-like performance and compiler-checking experience while giving the interactivity.

42 Likes

It is not possible to do bounds checking in general at compile time. Imagine that you define an integer variable to be the solution of some deep mathematical problem (depending on some runtime input) and then use that integer to index an array. The only possible way to know whether the index is out of bounds is to do a runtime check. This is not specific to Rust.

3 Likes

“scientific computing” is almost synonymous with arrays.

I would go further and say it’s about 2D arrays (even n-D), i.e. matrices (and tensors). While this (with ndarray), i.e. linear algebra is possible in Rust, it just seems non-ideal there, unless I missed something looking into it, and the same in C, C++, and even Python. Unlike in Julia which is ideal regarding indexing/bounds-checking (and syntax).

steveklabnik on Feb 28, 2019 | root | parent | prev | next [–]
You only pay for bounds checks if you use them, same with the overflow stuff, or option types. That’s not in contradiction to this principle.

That’s the main Rust guy, so he should know. But it’s unclear to me if this is even easy, and possible locally as in Julia, as opposed to only disablable at some more granular level (I know e.g. in D it’s globally or at best for "@safe functions"). And also as with C++, when you build up libraries like ndarray, as with Vector in std in C++, I think the bounds-checking logic may be in library code, so maybe non-trivial if not impossible to disable (I’ve asked, and tried to look up, but not yet had an answer for C++).

C++ doesn’t have the ideal arr[1, 2] syntax until C++23 (not yet approved as a standard). http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2128r6.pdf

We make the expressions deprecated in C++20 ill-formed while allowing multi-dimensional
subscript expressions in new standard types and user types. We do not propose modifications
to C arrays, so as to leave a cycle before giving new meaning to syntax that was still valid in
C++20.

The syntax for (construction of) at least 2D arrays wasn’t too bad in Rust, while not as natural as in Julia, and the small linear algebra section I found in docs, suggested Rust is immature for it, has a lot of catching-up to do. It’s not the target audience of Rust, and so I doubt that will ever happen. This is all before you bring up the REPL issue Chris brought up, but I think they may have some interactivity (also even C++) by now, e.g. can use Rust in Jupyther. I don’t think it changes the picture.

3 Likes

For scientific computing can Rust have any advantage over Fortran?

Yes. Generic programming. Most high performance Fortran requires a preprocessor in another language because Fortran doesn’t give you the necessary tools to write fast code in Fortran.

4 Likes

There is a Jupyter kernel for Rust GitHub - google/evcxr.

I’ve written a fair share of Rust lately (juliaup is written in Rust), and in my mind the biggest thing why I wouldn’t use Rust for scientific computing is what is also one of the nicest things about Rust for systems programming: the language really forces you to handle and think about every single corner case where something could go wrong. That is fantastic if one writes a piece of code that will run on tens of thousand of machines and that just must work always, but for the typical scientific computing code that just imposes a huge amount of mental overhead that I think most folks wouldn’t want.

I could see a different situation where someone is building a production system, say some web app that has a backend that does some scientific computing. In such a scenario the static typing and all the rest of the things that the compiler forces you to handle in Rust might be welcome.

31 Likes

This can be done in languages with dependent types such as Idris when you work with the proper types. For example, from Type-Driven Development with Idris:

4.2.3. Indexing vectors with bounded numbers using Fin
Because Vects carry their length as part of their type, the type checker has additional knowledge that it can use to check that operations are implemented and used correctly. One example is that if you wish to look up an element in a Vect by its location in the vector, you can know at compile time that the location can’t be out of bounds when the program is run.

Working the bounded types and providing proofs is a pretty high onus on the programmer, so it is highly unlikely be undertaken in research scientific computing where Julia’s interactivity shines.

3 Likes

I believe Fortran has at least good array handling, and while I don’t really know it, I found: Generic programming in Fortran Wiki

So I’m not sure Rust even has the generic programming advantage, that Oscar mentioned. Maybe in practice it’s not done much in Fortran, people slow to adopt modern Fortran standards (and Fortran 2003, not even brand-new, since then Fortran 2008 and 2018)?

I’m a big believer in languages working together, and it seems Julia can reuse everything Rust comes up with (i.e. its easy to call), like it’s easy to call C or Fortran, so all libraries in those languages can be reused. Of course the whole will not be fully safe as if all of it had been done in Rust.

I can my own idea while reading and answering this thread (and posted a link to some bounds-checking research there, that I’ve not yet read…):

Gridap seems to be rapidly catching up there…

6 Likes

I played with Rust briefly, and rather liked it.
In large part because I did get the impression that software written in it would tend towards being built to last and be easy to maintain, which are things I’ve been longing for.
Rust’s traits are a great example of what I’m talking about here.

However, scientific computing is dominated by exploratory analysis and throw away scripts. Thus, Rust’s tradeoffs don’t seem like the right ones for Julia’s use cases.

I do think however that it would be reasonable for Julia libraries to be wrappers of Rust libraries, when there isn’t much to gain from being pure-Julia.
E.g., I have no desire to differentiate the reading of a CSV file, so writing a Julia CSV library in Rust seems like a solid choice. Same goes for plotting.
Of course, we already have CSV.jl and plenty of plotting libraries, so that’s just an example.

15 Likes