3 ms·
To be fair, much potential of such a memory model (notably, where the data dependency of pointer-chasing (and anything else where an earlier load is used to com
by namibj 4y ago
To be fair, much potential of such a memory model (notably, where the data dependency of pointer-chasing (and anything else where an earlier load is used to compute a later load's address) doesn't force a matching order of when the load instructions execute (pull the data out of cache and into a register)) is only unlocked once you have substantial contention (or some contention plus latency between cache and actual memory, like if you go across PCIe/some-other-NUMA-fabric, or access Optane memory) along with load address speculation (this can be done automatically or through explicit prefetch instructions).
In the absence of a read fence, you can speculate the address of a second load, execute this second load in parallel with a first load, and ignore a cache invalidation (or just not wait until you can rule out an asynchronously transmitted one) hitting the second load so long as the address (computed from the first load's data) was correctly predicted.
It hits even harder when the predicted address was a cache hit and the first load experienced a cache miss, because now you can speculate execution using the second load's data (delivered from the cache) and retain/confirm/retire the results of the speculated computation as soon as the first load's data returns and the computation of the second load's address confirms the speculated one.
An example is read-only access to data structures with pointer chasing while a different core performs copying garbage collection. Because the data is (semantically) read-only, the old copy and the new copy are both equally valid, and as long as you don't accidentally read the new space before the copy was written into it, you can pointer-chase freely through these structures reading the next e.g. linked-list entry from either the old or the new place (if you speculate correctly).
Critically, this could get by with invalidating only cached data for the copy target range, ensuring readers don't get the uninitialized data, without invalidating their cache of the copy source range. Of course that would require sufficiently targeted invalidation.
Other cases like e.g. typical union-find / disjoint-set datastructures work just fine with standard fence-free Alpha memory accesses, at the slight cost of `union` operations not coherently affecting outcomes of `find` operations. That's often not a problem, though, as parallel applications already have to cope with the `union` racing the "subsequent" `find` operations (and ending up with the `union` happening last).