12#ifndef ARCANE_ACCELERATOR_COMMONCUDHIPATOMICIMPL_H
13#define ARCANE_ACCELERATOR_COMMONCUDHIPATOMICIMPL_H
32namespace Arcane::Accelerator::impl
38template <
typename DataType, enum eAtomicOperation>
41template <
typename DataType>
43template <
typename DataType>
45template <
typename DataType>
53 static ARCCORE_DEVICE
int apply(
int* ptr,
int v)
55 return ::atomicAdd(ptr, v);
64 static ARCCORE_DEVICE
int apply(
int* ptr,
int v)
66 return ::atomicMax(ptr, v);
75 static ARCCORE_DEVICE
int apply(
int* ptr,
int v)
77 return ::atomicMin(ptr, v);
88 static_assert(
sizeof(
Int64) ==
sizeof(
long long int),
"Bad pointer size");
89 return static_cast<Int64>(::atomicAdd((
unsigned long long int*)ptr, v));
101 unsigned long long int* address_as_ull =
reinterpret_cast<unsigned long long int*
>(ptr);
102 unsigned long long int old = *address_as_ull, assumed;
106 Int64 assumed_as_int64 =
static_cast<Int64>(assumed);
107 old = atomicCAS(address_as_ull, assumed,
108 static_cast<unsigned long long int>(v > assumed_as_int64 ? v : assumed_as_int64));
109 }
while (assumed != old);
110 return static_cast<Int64>(old);
115 return static_cast<Int64>(::atomicMax((
long long int*)ptr, v));
128 unsigned long long int* address_as_ull =
reinterpret_cast<unsigned long long int*
>(ptr);
129 unsigned long long int old = *address_as_ull, assumed;
133 Int64 assumed_as_int64 =
static_cast<Int64>(assumed);
134 old = atomicCAS(address_as_ull, assumed,
135 static_cast<unsigned long long int>(v < assumed_as_int64 ? v : assumed_as_int64));
136 }
while (assumed != old);
137 return static_cast<Int64>(old);
142 return static_cast<Int64>(::atomicMin((
long long int*)ptr, v));
150__device__
inline double
151preArch60atomicAdd(
double* address,
double val)
153 unsigned long long int* address_as_ull = (
unsigned long long int*)address;
154 unsigned long long int old = *address_as_ull, assumed;
158 old = atomicCAS(address_as_ull, assumed,
159 __double_as_longlong(val +
160 __longlong_as_double(assumed)));
162 }
while (assumed != old);
164 return __longlong_as_double(old);
166__device__
inline double
167atomicMaxDouble(
double* address,
double val)
169 unsigned long long int* address_as_ull = (
unsigned long long int*)address;
170 unsigned long long int old = *address_as_ull, assumed;
174 double assumed_as_double = __longlong_as_double(assumed);
175 old = atomicCAS(address_as_ull, assumed,
176 __double_as_longlong(val > assumed_as_double ? val : assumed_as_double));
178 }
while (assumed != old);
180 return __longlong_as_double(old);
183__device__
inline double
184atomicMinDouble(
double* address,
double val)
186 unsigned long long int* address_as_ull = (
unsigned long long int*)address;
187 unsigned long long int old = *address_as_ull, assumed;
191 double assumed_as_double = __longlong_as_double(assumed);
192 old = atomicCAS(address_as_ull, assumed,
193 __double_as_longlong(val < assumed_as_double ? val : assumed_as_double));
195 }
while (assumed != old);
197 return __longlong_as_double(old);
205 static ARCCORE_DEVICE
double apply(
double* ptr,
double v)
207#if __CUDA_ARCH__ >= 600
208 return ::atomicAdd(ptr, v);
210 return preArch60atomicAdd(ptr, v);
220 static ARCCORE_DEVICE
double apply(
double* ptr,
double v)
222 return atomicMaxDouble(ptr, v);
231 static ARCCORE_DEVICE
double apply(
double* ptr,
double v)
233 return atomicMinDouble(ptr, v);
eAtomicOperation
Type d'opération atomique supportée.
std::int64_t Int64
Type entier signé sur 64 bits.