4 ms·
> This is actually wrong [...]. I fairly sure it's correct! precisely because of the initial store `int x = 0;`, for the reason given by the article. If that w
by agalunar 5y ago
> This is actually wrong [...].
I fairly sure it's correct! precisely because of the initial store `int x = 0;`, for the reason given by the article. If that were `int x = 2;` instead, then I agree that the transformation would be invalid.
(Perhaps this is what you meant? but I wanted to clarify.)
In case anyone is curious, here are the relevant parts of the C++ reference:
> Absent any constraints on a multi-core system, when multiple threads simultaneously read and write to several variables, one thread can observe the values change in an order different from the order another thread wrote them. Indeed, the apparent order of changes can even differ among multiple reader threads. Some similar effects can occur even on uniprocessor systems due to compiler transformations allowed by the memory model.
> If an atomic store in thread A is tagged memory_order_release and an atomic load in thread B from the same variable is tagged memory_order_acquire, all memory writes (non-atomic and relaxed atomic) that happened-before the atomic store from the point of view of thread A, become visible side-effects in thread B. That is, once the atomic load is completed, thread B is guaranteed to see everything thread A wrote to memory.
> The synchronization is established only between the threads releasing and acquiring the same atomic variable. Other threads can see different order of memory accesses than either or both of the synchronized threads.
https://en.cppreference.com/w/cpp/atomic/memory_order https://en.cppreference.com/w/cpp/atomic/memory_order
- a1369209993 5y ago> because of the initial store `int x = 0;` That's a global variable declaration; it only happens once, but rlo can be called multiple times, or after some other code mutates x.
- agalunar 5y agoRight, but writes to x from another thread (i.e. by a thread other than the one in which rlo is called or the thread reading y) aren't required to be visible when y is read. Edit: ah, I think I understand what you're saying – if a thread that calls rlo also modifies x elsewhere, beforehand, then yeah, the store can't be eliminated.
- gizmo686 5y agoThat depends. rlo() is not the only function that is allowed to have synchronization primitives. It is possible that before rlo() is called, some other code modifies x, and all threads use some synchronization primitive to guarantee that they observe it. There is no notion of lexical or compilation unit scope for synchronization, so (unless it is doing whole program optimization) the compiler has no way of knowing that no other writes are visible after initialization.
- agalunar 5y agoAgreed, but we might be stepping outside the scope of the example. Likely, you can make most examples incorrect if you're allowed to add arbitrary code; I read this section of the article with the implicit assumption that "the thread calling rlo() performs no other writes to x" and "there's no additional synchronization", since the author didn't put any such code in their example and only claimed that the optimization was possible for the example they gave. (This is Grice's maxim of quantity, I suppose?) Although they probably should have been more careful and clarified that the example they gave doesn't work regardless of context.