2018-03-18 9:34 GMT-07:00 Michael Jones <
michae...@gmail.com>:
> Subtle observation--it is not fundamentally the memory model theorized in Go
> or C++ specifications that causes this--rather it is the least strong
> guarantee of the hardware on which these languages promise that standard
> programs will work as specified, and following that, the decision of
> language designers how efficiently they want to use the fastest of that
> hardware.
If I might reflect this differently: it's a combination of what
language designers want to target based on the hardware platforms they
intend to support. Is that understanding your point correctly?
> If one is designing a language that is more demanding than the execution
> hardware promises, that's fine. It just means that the generated/evaluated
> code must virtualize what appears to be simple things. For example, if we
> want multiple threads to be able to do "i++" against the same variable, we
> can generate an implicit mutex around every access to every "i" that could
> ever be visible to a concurrent thread. There is nothing wrong with this,
> but the resulting code will not generally be as fast as the code of other
> languages where the offer is less general, say, requiring developers to put
> locks around critical sections or use atomic increments when they know
> memory could be accessed concurrently.
Some (maybe less academic) examples of where Go does this:
* There is no way to force at least 16 byte alignment of data per the
language spec, so there is no way to implement DCAS (notably missing
from sync/atomic) on amd64 (cmpxchg16b requires 16 byte alignment of
its target operand). DCAS is useful in lock-free protocols to avoid
ABA problems. These issues can be avoided in Go by copying, but this
usually inefficient (and maybe ends up holding locks anyway if you
need to allocate to copy)
.
* The sync.atomic interface implements full memory barriers around
all operations. This is designed to obviate the need for understanding
memory barriers, but this is inefficient if all you need is (for
example) a load fence to guarantee loads observed in some order.
(I get that the applications for such things are "clever" and folks
are encouraged not to be "clever" in this way. But if one has a
relatively good understanding of this stuff, it's rather unfortunate.)
> As it happens, the "auto-magic" mode can be just as fast in some cases. On
> IBM POWER9+ there are special memory ranges where the synchronization is
> hardware facilitated. On the CPUs most people have, though, the code would
> be much slower and this would likely be seen as a flaw.
This is an excellent point. I wish that people would more often talk
about applications for these things (like lock-freedom) in terms of
system predictability (and therefore scalability) than performance
(and therefore speed). Scalability doesn't automatically imply
performance, but it sometimes results in improved performance, and is
sometimes more preferable (predictability is hugely important for
correct capacity modeling) even when it does not improve performance.
[1] provides another example of this kind of thing. Table 4 shows
uncontended latency for push/pop operations on a stack on x86-64 vs
POWER7. Spinlocks are easier to acquire on x86-64 than on POWER7, so
if writing for that platform, you might protect mostly-uncontended
access with spinlocks instead of using a lock-free stack. You'd come
to the opposite conclusion on POWER7. And so targeting either
platform, one might be likely to see the less performant approach as a
flaw. But at the end of the day, Figure 6 (just below) does a great
job at illustrating what you actually get from the progress guarantees
of lock-freedom, once you introduce contention.
(I'd really like the ability to do this in Go...)
--dho
[1]
https://queue.acm.org/detail.cfm?id=2492433 "Nonblocking
Algorithms and Scalable Multicore Programming", Samy Al Bahra, 2013
>> >> >> email to
golang-nuts...@googlegroups.com.
>> >> >> For more options, visit
https://groups.google.com/d/optout.
>> >>
>> >> --
>> >> You received this message because you are subscribed to the Google
>> >> Groups
>> >> "golang-nuts" group.
>> >> To unsubscribe from this group and stop receiving emails from it, send
>> >> an
>> >> email to
golang-nuts...@googlegroups.com.
>> >> For more options, visit
https://groups.google.com/d/optout.
>> >
>> >
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to
golang-nuts...@googlegroups.com.