> Or 3) Decide that for performance reasons, reads/writes to an array (even a char* array or string) would be locked in 64-byte chunks at a minimum.
First note that this doesn't have anything to do with arrays specifically: any type of adjacent elements (in a struct, loose on the stack, whatever) have this problem.
That said, I have no idea how you would implement this suggestion.
E.g., how would you compile the following very simple function?
void write1(char *c) {
*c = 1;
}
> My point with false-sharing is that "true" byte-granularity comes with severe performance penalties on modern x86 systems. Its a thing that you want to avoid.
It obviously does not! x86 has true byte granularity and loads and stores are very fast, just as fast as any other size. Just because the possibility of false sharing exists, doesn't mean it somehow slows down byte writes. False sharing doesn't even have anything to do with byte writes: it affects any size of access. So I am really not following your argument.
To summarize my claim:
- Modern memory models generally require that writing some "object" (which could be a primitive value like a char, int, whatever) not interfere with adjacent objects.
- This applies to all writes, unless perhaps the compiler can prove the data never escaped and cannot be shared, so in practice it means that you can only efficiently write at the smallest granularity supported by hardware.
- This means that you pretty much need 32-bit char on platforms where the smallest hardware write is 32 bits, or just give up on supporting the memory model.
None of that has anything to do with false sharing really. Not even really performance: we are just trying to get it to be correct. Saying "well you don't want to concurrently read nearby elements anyways" doesn't mean much because it doesn't lead to a practical way to implement the language (unless I am missing something).
> I guess your point is that the CPU will "do the right thing, even if they're forced to do it slowly" in this case. So I guess you're right about that. Your code CAN be written as multithreaded + byte granular, its just going to be slow in practice.
Not at all. My point has nothing to do with false sharing. You brought up false sharing.
My point is that the memory model is defined not prohibit behavior X, and platforms that need to do a large-word RMW to modify smaller elements can't effectively prohibit X.
This is true if you have false sharing or no false sharing or a small amount of false sharing. This is true even if you don't start any threads. This is true also for scenarios of "true sharing", e.g., where the other thread wants to share data (i.e., after reading the adjacent element maybe it is going to read the other one too).
> I guess my point is that the high-performance programmer needs to understand this situation anyway
It has nothing to do with the (application) programmer or performance. It is more fundamental than that: how does the compiler writer write a compiler that produces correct code under the memory model?