4 ms·
> Tesla's autopilot has a guarantee for its accuracy. Which (if true) is completely beside my the point. Just pick something that doesn't have a guarantee. The
by dataflow 5y ago
> Tesla's autopilot has a guarantee for its accuracy.
Which (if true) is completely beside my the point. Just pick something that doesn't have a guarantee. The comment wasn't about Tesla. It was about empirical performance vs. written guarantees.
> Normally when this type of situation comes up, the programmers perspective is at least understandable, since what they were doing was somewhat reasonable, even if not allowed by the standard.
Okay great, we agree on that.
> In this case, the point is that I cannot come up with any reasonable program that would rely on an interleaving happening 50% of the time.
That's easily explained by our lack of imagination. No need to assume the person relying on it is being unreasonable.
Hypothetical example: suppose two threads are trying to alternate running some specific instructions with minimal latency. Maybe there are hardware requirements (e.g. they want to avoid overheating come specific components of a CPU core for too long?), so they try to alternate work via an atomically increasing counter? That's a starting point at least, feel free to improve the scenario.
- kllrnohj 5y ago> so they try to alternate work via an atomically increasing counter? Then why did they asked for an atomic that doesn't provide that instead of one that does? The docs on memory_order_relaxed are pretty clear it provides no thread synchronization of any kind: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxe... This isn't some undefined behavior quirk being used to optimize, this is well-defined behavior being optimized in a well-defined fashion.
- dataflow 5y ago> The docs on memory_order_relaxed are pretty clear it provides no thread synchronization of any kind No, that's not what it's saying. "Synchronization" is an imprecise term, and you're misunderstanding what it means here. Atomics (as is literally in their name) perform each operation atomically; by definition they provide at least that thread synchronization guarantee, even if you believe they provide nothing else. The documentation explains what "are not synchronization operations" refers to in the subsequent sentences; it's most certainly not saying it doesn't provide thread synchronization "of any kind" (again, I already listed one above). In fact, it lists 2 specific kinds of thread synchronization it does provide: "atomicity" (i.e. operations are all-or-nothing, as above) and "modification order consistency" (i.e. alterations of that same variable occur in a consistent order across different threads, even under std::memory_order_relaxed). What it does not provide is a consistent ordering across different variables ("an order among concurrent memory accesses"), which is fine as it's not not something we need in this example. Collapsing multiple atomic operations into one has nothing to do with ordering, nor with multiple locations in memory. In fact, I don't think even std::memory_order_seq_cst can prevent this. The only way I can imagine preventing it is to mark atomics as volatile, and even then I'm not sure if it's guaranteed under the as-if rule.
- gpderetta 5y agovolatile should work. Each volatile access is a side effect from the point of view of the abstract machine and compilers are supposed to document this mapping to the concrete CPU (and usually is the obvious one). In fact the fact that volatile atomic has additional guarantees is a strong reason for plain atomic not to have them, otherwise there wouldn't be a way to express the more relaxed requirement. I think atomic not being volatile by default is a good default: the majority of code doesn't need to care about atomic in the first place, for the majority of the remaining code, these sort of optimizations are benign and desirable. For the remaining code that cares, volatile is the safety hatch.
- dataflow 5y agoI'm not so sure volatile is sufficient... I expect it would depend at least on how the variable is allocated/stored. Merely putting volatile shouldn't be sufficient to prevent access to it being optimized out. I forget if this was disallowed since C++20, but consider the program 'int main() { volatile int x = 0; ++x; }'. I'm fairly certain the compiler can optimize out the body despite the use of volatile, because of the as-if rule: it would be impossible to tell the difference from within the program. Moreover, I'm not sure 'volatile' memory access without some sort of external linkage is even meaningful. The idea of volatile is that access to a volatile variable could have observable side effects outside the program, but that discussion seems rather moot for a variable that doesn't have connections to the outside world to begin with. Heck, by the same reasoning, even for a variable with external linkage, the rules might still permit it to be optimized out under link-time optimization, unless it has been declared to be externally reachable somehow (e.g. at a fixed/exported/otherwise 'known' address)... otherwise it's by definition externally unreachable and thus again unobservable under the as-if rule. At least, I could see the reasoning going that way, and that's how it makes sense to me as far as the abstract machine goes. I can also see people disputing it though, and claiming (say) a debugger inspecting a program is sufficient accessibility for considering side effects, or something like that. I'm not sure I agree with every objection, but I see room for debate. It's just not clear what the implications are under the as-if rule.
- 5y ago