Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation: Relaxed Memory Ordering maybe wrong statement? #368

Open
steckes opened this issue Nov 5, 2024 · 7 comments
Open

Documentation: Relaxed Memory Ordering maybe wrong statement? #368

steckes opened this issue Nov 5, 2024 · 7 comments

Comments

@steckes
Copy link

steckes commented Nov 5, 2024

In the section about Relaxed Memory Ordering in the docs it is stated, that B can run before A.

loom/src/lib.rs

Line 294 in 31dfebd

//! ## Relaxed Memory Ordering

thread::spawn(move || {
  let r1 = y.load(Ordering::Relaxed); // A
  x.store(r1, Ordering::Relaxed);     // B
});
thread::spawn(move || {
  let r2 = x.load(Ordering::Relaxed); // C
  y.store(42, Ordering::Relaxed);     // D
});

How should the compiler be able to move B in front of A, if r1 is not existing at this time?
I guess you meant that D can run before C, what makes perfect sense, because D has no connection to C that is visible for the compiler.

I am quite new to understanding this stuff, so happy if you correct me :)

@steckes
Copy link
Author

steckes commented Nov 5, 2024

Okay, theoretically r1 could exist because of shadowing, but this is not the point that should be done here no? :D

@Darksonn
Copy link
Contributor

Darksonn commented Nov 6, 2024

The correct search term is "out of thin air values".

@steckes
Copy link
Author

steckes commented Nov 6, 2024

Oh very good hint, super interesting topic, I can't wait to understand more.
So it is actually right the B can run before A?

@Darksonn
Copy link
Contributor

Darksonn commented Nov 6, 2024

In general, reordering of operations is the wrong way to look at it. Different threads may disagree about the order things happened in, since they may see the effects of an atomic operation in a delayed manner.

@steckes
Copy link
Author

steckes commented Nov 6, 2024

But is my assumption here a valid path of execution?

  1. D -> y = 42
  2. A -> r1 = y (42)
  3. B -> x = r1 (42)
  4. C -> r2 = x (42)

Which would lead to r1 == r2 == 42, what only involved reordering D and C plus executing thread 1 in between.

I just read this blog article, where the person tries to explain the out of thin air value with a quite similar example.

So thread 1 reads r1 before storing it, but thread two sees the store before the load?

I saw that @jonhoo was writing this bit, do you think there is a way to make this a bit clearer in the documentation or do you think it is all good? In this case feel free to close this ticket. Thank you @Darksonn for the help.

@sbarral
Copy link

sbarral commented Nov 7, 2024

I would actually agree with @sainteckes analysis here: in my understanding, out-of-thin air values are literally values that are not stored at any point of the execution and the C++ spec actually forbids compilers from creating them.

It looks therefore to me more likely that this particular section in the Loom doc is about the specific execution order that @sainteckes mentioned (D before C), which Loom cannot emulate.

@Darksonn
Copy link
Contributor

Yeah, I guess you're right. The problem is not just out-of-thin-air. Loom works by interleaving different accesses in many different ways, but atomics can involve cases where different threads disagree on the order in which things happened. With loom, those cases cannot happen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants