Arcane  v4.1.0.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
accelerator/Atomic.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* Atomic.h (C) 2000-2025 */
9/* */
10/* Opérations atomiques. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_ACCELERATOR_ATOMIC_H
13#define ARCANE_ACCELERATOR_ATOMIC_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#if defined(ARCCORE_DEVICE_TARGET_CUDA) || defined(ARCCORE_DEVICE_TARGET_HIP)
18#include "arcane/accelerator/CommonCudaHipAtomicImpl.h"
19#endif
20
21#include <atomic>
22#include <concepts>
23
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
26
27namespace Arcane::Accelerator
28{
29//! Liste des types supportant les opérations atomiques.
30template <typename T>
31concept AcceleratorAtomicConcept = std::same_as<T, Real> || std::same_as<T, Int32> || std::same_as<T, Int64>;
32}
33
34namespace Arcane::Accelerator::impl
35{
36
37template <enum eAtomicOperation Operation>
39template <enum eAtomicOperation Operation>
41
42template <>
44{
45 public:
46
47 template <AcceleratorAtomicConcept DataType> static DataType
48 apply(DataType* ptr, DataType value)
49 {
50 std::atomic_ref<DataType> v(*ptr);
51 return v.fetch_add(value);
52 }
53};
54
55template <>
57{
58 public:
59
60 template <AcceleratorAtomicConcept DataType> static DataType
61 apply(DataType* ptr, DataType value)
62 {
63 std::atomic_ref<DataType> v(*ptr);
64 DataType prev_value = v;
65 while (prev_value < value && !v.compare_exchange_weak(prev_value, value)) {
66 }
67 return prev_value;
68 }
69};
70
71template <>
73{
74 public:
75
76 template <AcceleratorAtomicConcept DataType> static DataType
77 apply(DataType* ptr, DataType value)
78 {
79 std::atomic_ref<DataType> v(*ptr);
80 DataType prev_value = v;
81 while (prev_value > value && !v.compare_exchange_weak(prev_value, value)) {
82 }
83 return prev_value;
84 }
85};
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
90#if defined(ARCANE_COMPILING_SYCL)
91
92template <>
94{
95 public:
96
97 template <AcceleratorAtomicConcept DataType> static DataType
98 apply(DataType* ptr, DataType value)
99 {
100 sycl::atomic_ref<DataType, sycl::memory_order::relaxed, sycl::memory_scope::device> v(*ptr);
101 return v.fetch_add(value);
102 }
103};
104
105template <>
106class SyclAtomic<eAtomicOperation::Max>
107{
108 public:
109
110 template <AcceleratorAtomicConcept DataType> static DataType
111 apply(DataType* ptr, DataType value)
112 {
113 sycl::atomic_ref<DataType, sycl::memory_order::relaxed, sycl::memory_scope::device> v(*ptr);
114 return v.fetch_max(value);
115 }
116};
117
118template <>
120{
121 public:
122
123 template <AcceleratorAtomicConcept DataType> static DataType
124 apply(DataType* ptr, DataType value)
125 {
126 sycl::atomic_ref<DataType, sycl::memory_order::relaxed, sycl::memory_scope::device> v(*ptr);
127 return v.fetch_min(value);
128 }
129};
130
131#endif
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
137{
138 public:
139
140 template <AcceleratorAtomicConcept DataType, enum eAtomicOperation Operation>
141 ARCCORE_HOST_DEVICE static inline DataType
142 doAtomic(DataType* ptr, DataType value)
143 {
144#if defined(ARCCORE_DEVICE_TARGET_CUDA) || defined(ARCCORE_DEVICE_TARGET_HIP)
146#elif defined(ARCCORE_DEVICE_TARGET_SYCL)
147 return SyclAtomic<Operation>::apply(ptr, value);
148#else
149 return HostAtomic<Operation>::apply(ptr, value);
150#endif
151 }
152
153 template <AcceleratorAtomicConcept DataType, enum eAtomicOperation Operation>
154 ARCCORE_HOST_DEVICE static inline DataType
155 doAtomic(const DataViewGetterSetter<DataType>& view, DataType value)
156 {
157 return doAtomic<DataType, Operation>(view._address(), value);
158 }
159};
160
161/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
163
164} // namespace Arcane::Accelerator::impl
165
166namespace Arcane::Accelerator
167{
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171/*!
172 * \brief Applique l'opération atomique \a Operation à la valeur à l'adresse \a ptr avec la valeur \a value.
173 *
174 * \retval l'ancienne valeur avant ajout.
175 */
176template <enum eAtomicOperation Operation, AcceleratorAtomicConcept DataType, typename ValueType>
177ARCCORE_HOST_DEVICE inline DataType
178doAtomic(DataType* ptr, ValueType value)
179requires(std::convertible_to<ValueType, DataType>)
180{
181 DataType v = value;
182 return impl::AtomicImpl::doAtomic<DataType, Operation>(ptr, v);
183}
184
185/*---------------------------------------------------------------------------*/
186/*---------------------------------------------------------------------------*/
187/*!
188 * \brief Applique l'opération atomique \a Operation à la vue \a view avec la valeur \a value.
189 *
190 * \retval l'ancienne valeur avant ajout.
191 */
192template <enum eAtomicOperation Operation, AcceleratorAtomicConcept DataType, typename ValueType>
193ARCCORE_HOST_DEVICE inline DataType
194doAtomic(const DataViewGetterSetter<DataType>& view, ValueType value)
195requires(std::convertible_to<ValueType, DataType>)
196{
197 DataType v = value;
198 return impl::AtomicImpl::doAtomic<DataType, Operation>(view, v);
199}
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
204} // namespace Arcane::Accelerator
205
206/*---------------------------------------------------------------------------*/
207/*---------------------------------------------------------------------------*/
208
209#endif
Liste des types supportant les opérations atomiques.
Espace de nom pour l'utilisation des accélérateurs.
__host__ __device__ DataType doAtomic(DataType *ptr, ValueType value)
Applique l'opération atomique Operation à la valeur à l'adresse ptr avec la valeur value.
eAtomicOperation
Type d'opération atomique supportée.