I'm replacing some OpenMP code with standard C++11/C++14 atomics/thread support. Here is the OpenMP minimal code example:
#include <vector>
#include <cstdint>
void omp_atomic_add(std::vector<std::int64_t> const& rows,
                    std::vector<std::int64_t> const& cols,
                    std::vector<double>& values,
                    std::size_t const row,
                    std::size_t const col,
                    double const value)
{
    for (auto i = rows[row]; i < rows[row+1]; ++i)
    {
        if (cols[i] == col)
        {
            #pragma omp atomic
            values[i] += value;
            return;
        }
    }
}
The code updates a CSR matrix format and occurs in a hot path for scientific computation.  It is technically possible to use a std::mutex but the values vector can have millions of elements and is accessed many times more than that so a std::mutex is too heavy.
Checking the assembly https://godbolt.org/g/nPE9Dt, it seems to use CAS (with the disclaimer my atomic and assembly knowledge is severely limited so my comments are likely incorrect):
  mov rax, qword ptr [rdi]
  mov rdi, qword ptr [rax + 8*rcx]
  mov rax, qword ptr [rax + 8*rcx + 8]
  cmp rdi, rax
  jge .LBB0_6
  mov rcx, qword ptr [rsi]
.LBB0_2: # =>This Inner Loop Header: Depth=1
  cmp qword ptr [rcx + 8*rdi], r8
  je .LBB0_3
  inc rdi
  cmp rdi, rax
  jl .LBB0_2
  jmp .LBB0_6
 #### Interesting stuff happens from here onwards
.LBB0_3:
  mov rcx, qword ptr [rdx]             # Load values pointer into register
  mov rax, qword ptr [rcx + 8*rdi]     # Offset to value[i]
.LBB0_4: # =>This Inner Loop Header: Depth=1
  movq xmm1, rax                       # Move value into floating point register
  addsd xmm1, xmm0                     # Add function arg to the value from the vector<double>
  movq rdx, xmm1                       # Move result to register
  lock                                 # x86 lock
  cmpxchg qword ptr [rcx + 8*rdi], rdx # Compare exchange on the value in the vector
  jne .LBB0_4                          # If failed, go back to the top and try again
.LBB0_6:
  ret
Is this possible to do using C++ atomics?  The examples I've seen only use std::atomic<double> value{} and nothing in the context of accessing a value through a pointer.
 
    