Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

No, the point is that Rust makes it much easier to add parallelism than C++:

1) Global state is discouraged by the Rust compiler: You have to explicitly put code which modifies global state inside unsafe blocks, to alert you that you have to manually ensure thread-safety for that state. gcc, for example, is infamously reliant on global state, to the point where it's impossible to have two targets within the same binary.

2) The compiler prevents you from sharing non-thread-safe data structures across thread boundaries (again, unless you explicitly use unsafe blocks). As a result, if the compiler accepts your code, you can be reasonably sure that the third-party library you're using to compress your data in parallel is also thread-safe and doesn't trigger concurrency bugs. Anecdote: Recently I wanted to use LLVM's new JIT infrastructure – which was re-designed with the explicit goal of being thread-safe! It worked fine when single-threaded, but resulted in weird errors when running in two threads in parallel. It turned out that the optimization passes used by the JIT weren't thread-safe after all... Of course, this wasn't documented anywhere. I guess I could count myself lucky that I discovered this problem so quickly, instead of hard-to-debug errors in production. Rust, in contrast, would've rejected that program outright.



sort by: page size:

Rust wasn't created to make programming for parallel execution "easier". What Rust does is make writing implicitly unsafe parrellel code impossible to write.

This is a good thing, but is orthogonal to single threaded performance (which from what I've read, the Rust team definitely cares about).


Also Rust is risky to parallelize: you can get deadlocks.

I don't get the obsession of parallel code in low level languages by the way. If you have an architecture where you can afford real parallelism you can afford higher level languages anyway.

In embedded applications you don't usually have the possibility to have parallel code, and even in low level software (for example the classical UNIX utilities), for simplicity and solidity using a single thread is really fine.

Threads also are not really as portable as they seem, different operating systems have different way to manage threads, or even don't supports thread at all.


Yeah, Rust is built from the ground up for programming at scale. One of the consequences is that it makes you think about thread safety from the start. (Imagine if you're on a large team and not everyone is aligned on whether some part of the code is thread-safe or not.) Some things are harder, but the benefit is that you can often make a program multithreaded, and many times faster on real workloads, with just a few minutes of work (an experience that's unmatched in all of programming).

One of the ways Rust is successful at scale is that the intraprocedural analysis is sophisticated, but the interprocedural analysis is deliberately quite basic. It's not quite in keeping with that to do things like selectively enforce bounds on global variables.

For use cases like the one you mentioned, the general strategy Rust wants you to use is to pass around a context with your data inside it (and the data could be in OnceCells if it's lazily fetched). This is also a more testable design. Global state is meant to be used sparingly.


Yes, as I do more rust, I love the fact I can safely parallelise more than I love the memory protection.

Before Rust, I was close to saying that thread-based parallelization was almost impossible to do safely, and was moving to only doing process-level parallelization.


In my experience multithreaded Rust isn't substantially more restrictive then multithreaded C++ at writing code free of data races (although it very much is at writing single-threaded code free of use-after-free). The primary methods in Rust to share memory across threads (in my experience writing high-performance wait-free but userspace not kernel code) are custom UnsafeCell wrappers which implement Send and Sync and have safe locking mechanisms preventing data races, safe atomics, or safe mutexes.

Rust’s solution to concurrency is a hell of a lot more than just solving memory management. As long as you avoid `unsafe`, Rust statically prevents all race conditions. Rust also makes it so if you can parallelize something, then you’ve proven that it’s safe to parallelize it, and therefore you can parallelize complex systems in Rust that you simply wouldn’t have the confidence to do with other languages.

I think you misunderstood Rust. There’s no additional mental cost compared to C++. In C++ you must do thing the same way (keep track of references, variable lifetimes) in order to write any sane program. Rust just help you to declare those things and ask the compiler to enforce it. And no, message passing is not the savior to parallelisation.

Exactly! Rust doesn't solve any parallelism problems. It's no better than established languages like C# or F#, and probably worse.

The advantages of Rust come when trying to do complex things with concurrency, and wanting to know that they're either going to be safe, or fail to compile.

Consider the now-classic "Fearless Concurrency" post about Stylo: https://blog.rust-lang.org/2017/11/14/Fearless-Concurrency-I...

Strictly, C++ pretty much has to be no slower than Rust. But it's certainly possible that a regular human might in practice write higher-performing parallel code when using Rust.


In C++ you can compile each file independently from every other file. You can't do that in Rust; you can only compile crates (which are made of many files) independently. Within a crate you can have circular references for example.

So the smallest chunk of work that can be parallelised is much bigger in Rust than in C++. (Unless you are writing atypically small Rust crates and atypically enormous C++ files.)


I don't dispute that, but I thought you were having C++ with threads as the starting point, in which case Rust very much gives you valuable guarantees.

Not really. Many other mainstream languages give you memory safety, strict type systems and overall robustness without having to deal with memory management or low-level details.

Even for parallelism this holds true. I would say it is even more pronounced there, in fact. Some high-level languages even come with simple, effective ways of doing parallelism without multithreading, which simplifies problems a lot.

Of course, they may not reach the top performance that C++ or Rust might, but that is the trade off. Performance vs. development cost.


Maintaining memory safety, thread safety, and avoiding UB is still much easier in Rust than C++. In C++ you have be vigilant to avoid a mistake slipping in. In Rust, you get a compile error if you make a mistake.

It's more complicated than that. Compilers love restrictions, because that means they can optimize more aggressively. And there are features that Rust doesn't have that C++ does have that can make Rust faster; for example, because Rust doesn't have move constructors, moving is an incredibly cheap operation, whereas it can execute arbitrary code (including throwing an exception!) in C++.

There are also... I don't know how to frame this, social issues? Rust's guarantees often let you do some very aggressive things that you could write in C++, but wouldn't, because it's not maintainable. For example, if you must use reference counting, but don't need threads, Rust has a split between Rc<T> and Arc<T>. You can afford to not use the atomic version in Rust code because if you ever refactor later, you know the compiler will catch this for you, whereas you're just asking for latent, hard to track down bugs if you tried this in C++.

This goes both ways; there is some stuff that C++ is better at than Rust too. It's more complex than "unsafe Rust lets you do anything C++ can do directly and so if it's 100% unsafe in Rust it will be the same speed and if it's safe Rust it will be slower."


Rust parallism guarantees are only applicable to threaded code and internal resources.

We have already learned to scale down from threads and go back to processes for security and stability reasons.

Here Rust doesn't help across IPC and data races of external resources.

One way that Rust compiles way slower than C++ is its Gentoo approach to libraries. With C++ I only compile my own code.


If you consider that robust and memory efficient parallelization is way more easily achieved in Rust than in C, Rust might already win today for some applications if you limit the developer time. In C it's hard to fulfill the requirements at all.

I guess you meant memory-safety reasons because Rust is attempting to be as fast as C and C++, not the other way around.

The point of rust is you get the performance of C++ with additional safety.

I think Rust makes a lot of very hard things possible, at the expense of making some easy things more annoying.

That's a tradeoff that bothers a lot of people who hear the Rust hype, only to find that it's more annoying to write the things they want to write. But if you use Rust and it makes a very hard thing possible, this is an incredibly empowering experience and you'll become a passionate believer. This is a dynamic that leads to arguments on the internet.

I've never done any substantial low-level systems programming, but there are high-level situations where I think Rust was better than anything else.

In one case, I simply couldn't get decent performance for something out of any garbage collected language I tried -- and GC time was the actual bottleneck. Rewriting in C++ seemed very intimidating and likely to be error-prone. Doing the same thing in Rust gave me the same benefits with the confidence that I hadn't made any dumb memory errors.

The second benefit of Rust is that concurrency and parallelism is easy, in the sense that 1) for basic parallelism, you can use Rayon without even thinking about it, and 2) in more complex cases, you can share stuff across threads and be confident that you haven't introduced any weird, hard-to-debug race conditions.

next

Legal | privacy