3 ms·
At leas on x86, acq/rel load/stores vs relaxed is basically free. Seq/cst loads are also free. Seq/cst are relatively fast, but at around 20-30 clock cycles sti
by gpderetta 3y ago
At leas on x86, acq/rel load/stores vs relaxed is basically free. Seq/cst loads are also free. Seq/cst are relatively fast, but at around 20-30 clock cycles still measurably slower thant everything else.
The catch is that x86 only has seq/cst atomic RMW so even if you ask for, say, a relaxed CAS or XADD, you will still get an expensive one.
So the c++11 memory model allows you to more easily maintain correctness (and your sanity), but for performance you still have to know how to map to the underlying microarchitecture.
- ComputerGuru 3y ago> At leas on x86, acq/rel load/stores vs relaxed is basically free. The corollary to this is that using them doesn't buy you any performance (under x86). (Also it makes it difficult to test that your code itself synchronizes correctly if you're developing on x86, since bugs may only show up under ARM or RISC or whatever, and even there, only some of the time... and that's why project loom, tsan, and miri exist.)
- klabb3 3y ago> Seq/cst are relatively fast, but at around 20-30 clock cycles Did you mean to say seq/cst store? Also, what operation is “set the value to X unconditionally and return me the previous value”? Is that possible with a store or something different? (Golang calls this op atomic swap) In either case, sounds like the room for optimizing for performance with granular memory models on x86 is even narrower than I thought.
- gpderetta 3y ago> Did you mean to say seq/cst store? Indeed! > set the value to X unconditionally and return me the previous value That would be atomic::exchange that maps to XCHG on x86, which, as all atomic RMW is sequentially consistent. Incidentally seq-cst stores are also typically lowered to XCHG on x86 as opposed to the more obvious MFENCE+MOV. There is still room for optimization, as if you can implement your algos with just load/stores and as few strategically placed RMW as you can, it can be a win. Of course if there is any contention, cache coherence traffic is going to dominate over any atomic cost.
- klabb3 3y agoThanks a ton! This matches my own micro-benchmarks in golang ish. I see basically either ~4ns for any write op, including store, swap, add, etc. And ~1ns for loads. I assume it’s all seq-cst.