0

I have a non-atomic 62-bit double which is incremented in one thread regularly. This access does not need to be atomic. However, this variable is occasionally read (not written) by another thread. If I align the variable on a 64-bit boundary the read is atomic.

However, is there any way I can ensure I do not read the variable mid-way during the increment? Could I call a CPU instruction which serialises the pipeline or something? Memory barrier?

I thought of declaring the variable atomic and using std::memory_order::memory_order_relaxed in my critical thread (and a stricter memory barrier in the rare thread), but it seems to be just as expensive.

user997112
  • 29,025
  • 43
  • 182
  • 361
  • 1
    Use the `` facilites. Anything else results in undefined behaviour. If *you* know that aligned 64-bit reads are atomic, then you can probably trust your compiler to know this, too. – Kerrek SB May 30 '15 at 15:36
  • 1
    @Kerrek SB: you're right (despite library writers being notoriously bad with multithreading, they're finally catching up). However, when using , one needs to understand what is going on "under the hood", or performance hit can be enormous. Answer by harold may be seen as an explanation _why_ certain things are faster when using atomics (for example, I'd expect that due to this fact, a good implementation on many platforms would make store(load()+1) an order of magnitude faster than atomic increment, though it certainly does have different semantics and is not always appropriate). – No-Bugs Hare May 30 '15 at 16:12

1 Answers1

4

Since you tagged x86, this will be x86-specific.

An increment is essentially three parts, read, add, write. The increment is not atomic, but all three steps (the add doesn't count I suppose, it's not observable anyway) of it are as long as the variable does not cross a cache line boundary (this condition is weaker than having to be aligned to its natural alignment, it has been like this as of P6, before that quadwords had to be aligned).

So you already can't read a torn value. The worst you could do is overwrite the variable in between the moments where it is read and the new value is written, but you're only reading it.

harold
  • 61,398
  • 6
  • 86
  • 164
  • Right. Moreover, most of other platforms (at least those which comply with RMO, PSO and TSO memory models, as well as all single-core-single-socket CPUs/MCUs) have this property of some-reads-and-writes-are-inherently-atomic-provided-proper-alignment (the only difference is maximum size of operand which is atomic). Power and ARM _might_ be an exception. – No-Bugs Hare May 30 '15 at 16:02
  • This is what I concluded. So long as I align the double to 64 bits, reading it should be atomic. – user997112 May 30 '15 at 19:09