|
|
Subscribe / Log in / New account

A missed invariant

A missed invariant

Posted Sep 4, 2024 19:32 UTC (Wed) by pizza (subscriber, #46)
In reply to: A missed invariant by ebiederm
Parent article: Whither the Apple AGX graphics driver?

> My sense is that you have paid attention to the Rust lifetimes, but have lost the real world hardware lifetimes.

To paraphrase the Red Queen, hardware has the remarkable ability of triggering six supposedly-impossible situations before breakfast, invariably wrecking your nice clean/consistent/clever abstractions in the process.

(I have no opinion on if that applies to this particular situation...)


to post comments

A missed invariant

Posted Sep 5, 2024 11:22 UTC (Thu) by taladar (subscriber, #68407) [Link]

That point applies just as much whether the clever abstraction is written down or is just a set of unwritten invariants that only exist in maintainer's heads. If anything changing the mental model as new behaviors are discovered is a lot harder than changing something that is written down since our brain has a way of making us confuse old versions and new versions of similar things that existed over time.

A missed invariant

Posted Sep 5, 2024 18:30 UTC (Thu) by NYKevin (subscriber, #129325) [Link] (2 responses)

Well, either that, or your abstractions are so nasty that they are actually worse than the hardware. The C++ spec says that relaxed atomics may be implemented using (effectively) a time machine, and therefore inherited all manner of temporal paradoxes from every bad sci-fi novel you've ever read (but they insist on using entirely new names for everything, so e.g. the bootstrap paradox is renamed to "out of thin air," the grandfather paradox is "read from unexecuted branch," etc.). Meanwhile, real compilers emit raw load and stores (in the case of simple atomic reads and writes) or real atomic instructions (for read-modify-write), and real CPUs are usually not time machines, and so this is all a purely theoretical problem that never actually happens.

Rust also inherits this model for its atomics, and to my understanding, it takes exactly the same "meh, theory is hard, we'll just assume the implementation is not insane" stance as C++. I like to imagine that some aggressive compiler writer is going to blow past the spec's non-normative "please do not actually do this" note and try to optimize a time machine into C++ and/or Rust, but realistically I think the compiler writers are smart people who understand that this would be a bad idea.

To further explain the motivation: Relaxed atomics are basically the "I don't want the compiler to turn my data race into UB" annotation. They don't actually do anything other than guarantee that the individual operations on that particular variable are atomic and consistent with some sequential ordering, and that the compiler is not allowed to deduce UB from any data races that may result, but other than that, there are no rules. This is intended to allow compilers to just emit loads and stores for simple (read-only or write-only) atomics, since the compiler may reason that any cache incoherency could also be interpreted as some reordering of the parallel loads and stores, and so you don't have to emit a fence. Since the "some" sequential ordering is not required to be consistent with the ordering of any other relaxed atomic variable, you can have two of these variables that interact with one another in such a way that the resulting ordering is permitted to contain a loop or cycle, in which case the results are not well-defined but also are not UB, and now you have rules that permit circular arguments like "x is 37 because x is 37." In C++14, they did add a rule prohibiting some specific cases (including the simple 37-because-37 case), but to the best of my understanding, this is not a comprehensive fix and there are still variations of the behavior that are not forbidden by the spec.

A missed invariant

Posted Sep 5, 2024 19:35 UTC (Thu) by khim (subscriber, #9252) [Link] (1 responses)

> real CPUs are usually not time machines

I would say that since Pentium Pro “real CPUs” are a time machines and thus all these paradoxes they speak about have become real

> so this is all a purely theoretical problem that never actually happens.

Except it does. It even happens on x86, as we all know. And x86 tries harder than most other CPUs to hide it's true nature.

> to the best of my understanding, this is not a comprehensive fix and there are still variations of the behavior that are not forbidden by the spec

The problem here is that creating a memory model that makes some sense and also is compatible with all these optimizations that hardware (not compiler!) is doing… it's not easy.

From what I understand C++ (and thus Rust) model is not well aligned with what hardware is doing but what Linux is doing is not compatible with some more exotic targets (e.g. GPUs) thus we just have to agree that designing sensible memory model for atomics is just hard.

A missed invariant

Posted Sep 7, 2024 23:18 UTC (Sat) by NYKevin (subscriber, #129325) [Link]

That link is not what I mean by "a time machine." I'm referring to real temporal paradoxes (such as both variables nonsensically taking on the value 42, because each supposedly got that value from the other), not just "the CPU executed things in a different order than I thought it would," nor even "the reordering which the CPU performed cannot be reconciled with a single global order of execution." Those are both normal and expected anomalies under relaxed atomics - they're the spec working as designed.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds