3 ms·
For those watching along at home, we're talking about these two comments from dragontamer: - https://news.ycombinator.com/item?id=27753913 https://news.ycombin
by kmeisthax 2y ago
For those watching along at home, we're talking about these two comments from dragontamer:
- https://news.ycombinator.com/item?id=27753913 https://news.ycombinator.com/item?id=27753913
- https://news.ycombinator.com/item?id=27762749 https://news.ycombinator.com/item?id=27762749
I interpreted dragontamer's comment to mean "x86 does not have relaxed stores", not "x86 does not have a strong memory model". The (presumed) problem is that you can't actually test acquire/release code on x86, because it won't crash if you get it wrong.
There's a second level of this in C++'s memory model: consume/release. I've no idea what the difference between acquire and consume are; when I look it up there's usually some reference to the DEC Alpha, a 30 year old workstation and server chip nobody uses today which was legendary for pushing the boundaries of memory ordering. My assumption is that no hardware provides memory ordering exactly as weak as consume, so I shouldn't bother asking for it, since it'll just get strengthened to acquire on any chip that matters.
Also, from you and one other person, it sounds like relaxed memory models aren't actually a performance benefit? Would the opposite - ARM mandating TSO in ARMv9.1-A or whatever - make sense? A lot of ink and code is wasted talking about memory model strengths.
- jcranmer 2y ago> There's a second level of this in C++'s memory model: consume/release. I've no idea what the difference between acquire and consume are; when I look it up there's usually some reference to the DEC Alpha, a 30 year old workstation and server chip nobody uses today which was legendary for pushing the boundaries of memory ordering. My assumption is that no hardware provides memory ordering exactly as weak as consume, so I shouldn't bother asking for it, since it'll just get strengthened to acquire on any chip that matters. You have it wrong here. So the basic idea behind release/consume comes from an observation that, on all hardware not named Alpha [1], there is no hardware fence needed to guarantee that a load happens-before another load that is data-dependent on the first load. So the C++ committee decided to add a memory model that would preserve this guarantee. A consume load is exactly like an acquire load, but only for other loads that are data-dependent on that load as opposed to all loads in general. So whereas an acquire load requires a fence on pretty much every hardware not x86 or SPARC in TSO mode, a consume load would only require a fence on Alpha. For various reasons, data-dependency isn't a property that compilers are in the position of guaranteeing, which means every compiler ended up implementing consume as the stronger acquire instead, defeating its entire design goal of eliminating unnecessary fences. There have been a couple of attempts within the committee to try to find a path that would let something like consume by tweaking the necessary data dependence definitions, but none of them have swayed the implementers, so the current state is that they've given up and let consume die. Of particular note is that release/consume is not designed to support the Alpha memory model; in fact, it's quite the opposite: it's designed to support everybody but Alpha, since for Alpha (and essentially only Alpha), release/consume is not usefully weaker than release/acquire. Instead, the people who benefit are the PPCs and the ARMs of the world, for whom release/consume is a better approximation of their native memory model and would allow many fences to be omitted. [1] Actually, some accelerator hardware might have memory models as weak as Alpha here, but I'm far less familiar with memory models as they apply to accelerators.
- gpderetta 2y agoThank you! I have argued this point so many times on HN :).
- kmeisthax 2y agoSo, just to confirm my own (new) understanding now: Consume is "I want to read data from a pointer, please do not reorder loads that go through the pointer" and Acquire is "I want to read data from a pointer, please do not reorder loads that happen after this one, *whether or not they go through the same pointer" there's no relation to the Alpha aside from it being the only processor that needs a barrier for Consume and for whatever reason compilers don't or can't do the dependency tracking that would let them take advantage of the weaker guarantees of Consume, so in practice it just becomes Acquire?
- gpderetta 2y agoConsume is for data dependency, loading through a pointer is the obvious one, but there are other variants (using the loaded value as an index for example). Acquire is also not about pointers but about independent reads: reading a flag and then reading data protected by that flag for example. Consume exists because it can be implemented cheaply on some platforms with relatively expensive acquire barriers (ARM, POWER). Alpha didn't respect load dependencies, so consume is as expensive as acquire.