Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
DualUniqueArray.h
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 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/* DualUniqueArray.h (C) 2000-2024 */
9/* */
10/* 1D array allocated both on CPU and accelerator. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_DUALUNIQUEARRAY_H
13#define ARCANE_UTILS_DUALUNIQUEARRAY_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arccore/collections/Array.h"
18#include "arcane/utils/NumArray.h"
19
20/*---------------------------------------------------------------------------*/
21/*---------------------------------------------------------------------------*/
22
23namespace Arcane
24{
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29/*!
30 * \brief Base class for DualUniqueArray
31 *
32 * \warning API is currently under definition. Do not use outside of Arcane.
33 */
34class ARCANE_UTILS_EXPORT DualUniqueArrayBase
35{
36 protected:
37
38 static void _memoryCopy(Span<const std::byte> from, Span<std::byte> to);
39};
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44/*!
45 * \brief Represents an array having a view on both CPU and accelerator.
46 *
47 * \warning API is currently under definition. Do not use outside of Arcane.
48 */
49template <typename DataType>
50class DualUniqueArray
52{
53 using NumArrayType = NumArray<DataType, MDDim1>;
54 using ThatClass = DualUniqueArray<DataType>;
55
56 private:
57
58 class IModifierImpl
59 {
60 protected:
61
62 virtual ~IModifierImpl() = default;
63
64 public:
65
66 virtual SmallSpan<DataType> view() = 0;
67 virtual void resize(Int32 new_size) = 0;
68 virtual void endUpdate() = 0;
69 };
70
71 public:
72
73 class Modifier
74 {
75 friend class DualUniqueArray<DataType>;
76
77 private:
78
79 explicit Modifier(IModifierImpl* p)
80 : m_p(p)
81 {}
82
83 public:
84
85 ~Modifier()
86 {
87 m_p->endUpdate();
88 }
89
90 public:
91
92 SmallSpan<DataType> view() { return m_p->view(); }
93 void resize(Int32 new_size) { m_p->resize(new_size); }
94
95 private:
96
97 IModifierImpl* m_p = nullptr;
98 };
99
100 class HostModifier
101 : public Modifier
102 {
103 friend class DualUniqueArray<DataType>;
104
105 private:
106
107 explicit HostModifier(ThatClass* data)
108 : Modifier(&data->m_array_modifier)
109 , m_data(data)
110 {}
111
112 public:
113
114 Array<DataType>& container() { return m_data->m_array; }
115
116 private:
117
118 ThatClass* m_data = nullptr;
119 };
120
121 private:
122
123 class NumArrayModifierImpl
124 : public IModifierImpl
125 {
126 friend class DualUniqueArray<DataType>;
127
128 private:
129
130 NumArrayModifierImpl(ThatClass* v)
131 : m_data(v)
132 {}
133 SmallSpan<DataType> view() override
134 {
135 SmallSpan<DataType> v = *(m_data->m_device_array);
136 return v;
137 }
138 void resize(Int32 new_size) override
139 {
140 m_data->resizeDevice(new_size);
141 }
142 void endUpdate() override
143 {
144 m_data->endUpdate(true);
145 }
146
147 private:
148
149 ThatClass* m_data = nullptr;
150 };
151
152 class UniqueArrayModifierImpl
153 : public IModifierImpl
154 {
155 friend class DualUniqueArray<DataType>;
156
157 public:
158
159 UniqueArrayModifierImpl(ThatClass* v)
160 : m_data(v)
161 {}
162 SmallSpan<DataType> view() override
163 {
164 return m_data->m_array.view();
165 }
166 void resize(Int32 new_size) override
167 {
168 m_data->m_array.resize(new_size);
169 }
170 void endUpdate() override
171 {
172 m_data->endUpdate(false);
173 }
174
175 private:
176
177 ThatClass* m_data = nullptr;
178 };
179
180 public:
181
182 DualUniqueArray()
183 : m_numarray_modifier(this)
184 , m_array_modifier(this)
185 {
186 }
187 explicit DualUniqueArray(IMemoryAllocator* a)
188 : DualUniqueArray()
189 {
190 m_array = UniqueArray<DataType>(a);
191 }
192
193 public:
194
195 SmallSpan<const DataType> hostSmallSpan() const { return m_array.view(); }
196 ConstArrayView<DataType> hostView() const { return m_array.view(); }
197
198 void reserve(Int64 capacity)
199 {
200 m_array.reserve(capacity);
201 }
202 void resizeHost(Int32 new_size)
203 {
204 m_array.resize(new_size);
205 m_is_valid_numarray = false;
206 }
207 void fillHost(const DataType& value)
208 {
209 m_array.fill(value);
210 m_is_valid_numarray = false;
211 }
212 void resizeDevice(Int32 new_size)
213 {
214 _checkCreateNumArray();
215 m_device_array->resize(new_size);
216 m_is_valid_array = false;
217 }
218 void clearHost()
219 {
220 m_array.clear();
221 m_is_valid_numarray = false;
222 }
223 Int64 size() const { return m_array.size(); }
224 SmallSpan<const DataType> view(bool is_device)
225 {
226 sync(is_device);
227 if (is_device) {
228 SmallSpan<const DataType> v = *(m_device_array.get());
229 return v;
230 }
231 else {
232 return hostSmallSpan();
233 }
234 }
235 void sync(bool is_device)
236 {
237 if (is_device) {
238 _checkUpdateDeviceView();
239 }
240 else {
241 _checkUpdateHostView();
242 }
243 }
244 void endUpdateHost()
245 {
246 m_is_valid_array = true;
247 m_is_valid_numarray = false;
248 }
249 void endUpdate(bool is_device)
250 {
251 m_is_valid_array = !is_device;
252 m_is_valid_numarray = is_device;
253 }
254 Modifier modifier(bool is_device)
255 {
256 if (is_device) {
257 _checkCreateNumArray();
258 return Modifier(&m_numarray_modifier);
259 }
260 return Modifier(&m_array_modifier);
261 }
262 HostModifier hostModifier()
263 {
264 return HostModifier(this);
265 }
266
267 private:
268
269 UniqueArray<DataType> m_array;
270 std::unique_ptr<NumArrayType> m_device_array;
271 SmallSpan<DataType> m_device_view;
272 NumArrayModifierImpl m_numarray_modifier;
273 UniqueArrayModifierImpl m_array_modifier;
274 bool m_is_valid_array = true;
275 bool m_is_valid_numarray = false;
276
277 private:
278
279 void _checkUpdateDeviceView()
280 {
281 if (!m_is_valid_numarray) {
282 _checkCreateNumArray();
283 MDSpan<DataType, MDDim1> s(m_array.data(), ArrayIndex<1>(m_array.size()));
284 m_device_array->copy(s);
285 m_is_valid_numarray = true;
286 }
287 m_device_view = *(m_device_array.get());
288 }
289 void _checkUpdateHostView()
290 {
291 if (!m_is_valid_array) {
292 _checkCreateNumArray();
293 SmallSpan<const DataType> device_view = *(m_device_array.get());
294 m_array.resize(device_view.size());
295 _memoryCopy(asBytes(device_view), asWritableBytes(m_array.span()));
296 m_is_valid_array = true;
297 }
298 }
299 void _checkCreateNumArray()
300 {
301 if (!m_device_array) {
302 m_device_array = std::make_unique<NumArrayType>(eMemoryRessource::Device);
303 if (m_is_valid_array)
304 m_device_array->resize(m_array.size());
305 }
306 }
307};
308
309/*---------------------------------------------------------------------------*/
310/*---------------------------------------------------------------------------*/
311
312} // namespace Arcane
313
314/*---------------------------------------------------------------------------*/
315/*---------------------------------------------------------------------------*/
316
317#endif
Base class for 1D data vectors.
Base class for DualUniqueArray.
Multi-dimensional arrays for numerical types accessible on accelerators.
View of an array of elements of type T.
Definition Span.h:805
View of an array of elements of type T.
Definition Span.h:635
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
Impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converts the view into an array of non-modifiable bytes.
Definition Span.h:1032
Impl::SpanTypeFromSize< std::byte, SizeType >::SpanType asWritableBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converts the view into an array of modifiable bytes.
Definition Span.h:1068
std::int32_t Int32
Signed integer type of 32 bits.