использование атомарных операций на стандартных типах - PullRequest
0 голосов
/ 07 мая 2018

Цель: я хочу реализовать эту функцию:

int atomicCAS(int* address, int compare, int val);

Что является функцией CUDA , но я хочу реализовать ее для ЦП на C ++. Он должен быть совместим с этим API, т.е. я не могу изменить тип address.

Я предполагаю, что общее оборудование, например, amd64 и общий компилятор, например GCC или Clang.

Соответствующая функция C ++ STL - std::atomic::compare_exchange_strong, однако для этого требуется тип std::atomic, и я не уверен, разрешено ли мне просто делать что-то вроде:

((std::atomic<int>&) address)->compare_exchange_strong(...)

Я также мог бы использовать встроенную функцию GCC __atomic_compare_exchange_n, но не уверен, есть ли какие-либо предостережения или что будет хорошей проверкой, чтобы утверждать, что это верно.

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

Я считаю, что нет портативного способа сделать это, в основном потому, что в C ++ atomic s может быть реализован с блокировкой (или вообще sizeof(T)! = sizeof(atomic<T>)).

Как вы упомянули, вы можете использовать встроенные функции GCC. Они также используются libstdc++ для реализации std::atomic<Integral>, поэтому, когда вам нужно реализовать эквивалент std::atomic метода, вы можете взглянуть на bits/atomic_base.h.

Для atomic::compare_exchange_strong:

_GLIBCXX_ALWAYS_INLINE bool
  compare_exchange_strong(__int_type& __i1, __int_type __i2,
              memory_order __m1,
              memory_order __m2) volatile noexcept
  {
     memory_order __b2 = __m2 & __memory_order_mask;
     memory_order __b1 = __m1 & __memory_order_mask;

     __glibcxx_assert(__b2 != memory_order_release);
     __glibcxx_assert(__b2 != memory_order_acq_rel);
     __glibcxx_assert(__b2 <= __b1);

     return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, __m1, __m2);
  }

РЕДАКТИРОВАТЬ: Адаптация из предыдущего кода:

int atomicCAS(int* address, int *compare, int val)
{
    return __atomic_compare_exchange_n(address, compare, val, 0,
                                       __ATOMIC_SEQ_CST,
                                       __ATOMIC_ACQUIRE);
}

Обратите внимание, что compare является аргументом in-out, при сбое он будет перезаписан с текущим значением *address. Эта версия эквивалентна atomic<int>::compare_exchange_strong с упорядочением памяти по умолчанию, см. godbolt .

0 голосов
/ 07 мая 2018

__sync_val_compare_and_swap это, вероятно, то, что вы ищете

...