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
void apply(
int* ptr,
int v)
64 static ARCCORE_DEVICE
void apply(
int* ptr,
int v)
75 static ARCCORE_DEVICE
void apply(
int* ptr,
int v)
86 static ARCCORE_DEVICE
void apply(
Int64* ptr,
Int64 v)
88 static_assert(
sizeof(
Int64) ==
sizeof(
long long int),
"Bad pointer size");
89 ::atomicAdd((
unsigned long long int*)ptr, v);
99 static ARCCORE_DEVICE
void apply(
Int64* ptr,
Int64 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);
112 static ARCCORE_DEVICE
void apply(
Int64* ptr,
Int64 v)
114 ::atomicMax((
long long int*)ptr, v);
125 static ARCCORE_DEVICE
void apply(
Int64* ptr,
Int64 v)
127 unsigned long long int* address_as_ull =
reinterpret_cast<unsigned long long int*
>(ptr);
128 unsigned long long int old = *address_as_ull, assumed;
132 Int64 assumed_as_int64 =
static_cast<Int64>(assumed);
133 old = atomicCAS(address_as_ull, assumed,
134 static_cast<unsigned long long int>(v < assumed_as_int64 ? v : assumed_as_int64));
135 }
while (assumed != old);
138 static ARCCORE_DEVICE
void apply(
Int64* ptr,
Int64 v)
140 ::atomicMin((
long long int*)ptr, v);
148__device__
inline double
149preArch60atomicAdd(
double* address,
double val)
151 unsigned long long int* address_as_ull = (
unsigned long long int*)address;
152 unsigned long long int old = *address_as_ull, assumed;
156 old = atomicCAS(address_as_ull, assumed,
157 __double_as_longlong(val +
158 __longlong_as_double(assumed)));
160 }
while (assumed != old);
162 return __longlong_as_double(old);
164__device__
inline double
165atomicMaxDouble(
double* address,
double val)
167 unsigned long long int* address_as_ull = (
unsigned long long int*)address;
168 unsigned long long int old = *address_as_ull, assumed;
172 double assumed_as_double = __longlong_as_double(assumed);
173 old = atomicCAS(address_as_ull, assumed,
174 __double_as_longlong(val > assumed_as_double ? val : assumed_as_double));
176 }
while (assumed != old);
178 return __longlong_as_double(old);
181__device__
inline double
182atomicMinDouble(
double* address,
double val)
184 unsigned long long int* address_as_ull = (
unsigned long long int*)address;
185 unsigned long long int old = *address_as_ull, assumed;
189 double assumed_as_double = __longlong_as_double(assumed);
190 old = atomicCAS(address_as_ull, assumed,
191 __double_as_longlong(val < assumed_as_double ? val : assumed_as_double));
193 }
while (assumed != old);
195 return __longlong_as_double(old);
203 static ARCCORE_DEVICE
void apply(
double* ptr,
double v)
205#if __CUDA_ARCH__ >= 600
208 preArch60atomicAdd(ptr, v);
218 static ARCCORE_DEVICE
void apply(
double* ptr,
double v)
220 atomicMaxDouble(ptr, v);
229 static ARCCORE_DEVICE
void apply(
double* ptr,
double v)
231 atomicMinDouble(ptr, v);
eAtomicOperation
Type d'opération atomique supportée.
std::int64_t Int64
Type entier signé sur 64 bits.