Arcane  v3.16.7.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
MemoryUtils.h
Aller à la documentation de ce fichier.
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/* MemoryUtils.h (C) 2000-2025 */
9/* */
10/* Fonctions utilitaires de gestion mémoire. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_MEMORYUTILS_H
13#define ARCANE_UTILS_MEMORYUTILS_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
17#include "arcane/utils/MemoryRessource.h"
18#include "arcane/utils/MemoryView.h"
19
20#include "arccore/collections/MemoryAllocationArgs.h"
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25namespace Arcane::MemoryUtils
26{
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30/*!
31 * \brief Ressource mémoire utilisée par l'allocateur par défaut pour les données.
32 *
33 * Par défaut, si un runtime accélérateur est initialisé, la ressource
34 * associé est eMemoryResource::UnifiedMemory. Sinon, il s'agit de
35 * eMemoryResource::Host.
36 *
37 * \sa getDefaultDataAllocator();
38 */
39extern "C++" ARCANE_UTILS_EXPORT eMemoryResource
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44/*!
45 * \brief Retourne la ressource mémoire par son nom.
46 *
47 * Le nom correspond au nom de la valeur de l'énumération (par exemple
48 * 'Device' pour eMemoryResource::Device.
49 *
50 * Si \a name est nul, retourne eMemoryResource::Unknown.
51 * Si \a name ne correspondant pas à une valeur valide, lève une exception.
52 */
53extern "C++" ARCANE_UTILS_EXPORT eMemoryResource
54getMemoryResourceFromName(const String& name);
55
56/*---------------------------------------------------------------------------*/
57/*---------------------------------------------------------------------------*/
58/*!
59 * \brief Allocateur par défaut pour les données.
60 *
61 * L'allocateur par défaut pour les données est un allocateur qui permet
62 * d'accéder à la zone mémoire à la fois par l'hôte et l'accélérateur.
63 *
64 * Il est possible de récupérer la ressource mémoire associée via
65 * getDefaultDataMemoryResource();
66 *
67 * Cet appel est équivalent à getAllocator(getDefaultDataMemoryResource()).
68 *
69 * Il est garanti que l'alignement est au moins celui retourné par
70 * AlignedMemoryAllocator::Simd().
71 */
72extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator*
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77/*!
78 * \brief Allocateur par défaut pour les données avec informations sur
79 * la localisation attendue.
80 *
81 * Cette fonction retourne l'allocateur de getDefaulDataAllocator() mais
82 * ajoute les informations de gestion mémoire spécifiées par \a hint.
83 */
84extern "C++" ARCANE_UTILS_EXPORT MemoryAllocationOptions
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89/*!
90 * \brief Retourne l'allocateur sur l'hôte ou sur le device.
91 *
92 * Si un runtime accélérateur est initialisé, l'allocateur retourné permet
93 * d'allouer en utilisant la mémoire de l'accélérateur par défaut
94 * (eMemoryResource::Device). Sinon, utilise l'allocateur de l'hôte
95 * (eMemoryResource::Host).
96 */
97extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator*
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102/*!
103 * \brief Allocateur par défaut pour les données essentiellement en
104 * lecture.
105 *
106 * Cet appel est équivalent à getDefaultDataAllocator(eMemoryLocationHint::HostAndDeviceMostlyRead).
107 */
108extern "C++" ARCANE_UTILS_EXPORT MemoryAllocationOptions
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113/*!
114 * \brief Allocateur spécifique pour les accélérateurs.
115 *
116 * \deprecated Use MemoryUtils::getDefaultDataAllocator() instead.
117 */
118extern "C++" ARCANE_DEPRECATED_REASON("Y2024: Use getDefaultDataAllocator() instead.")
119ARCANE_UTILS_EXPORT IMemoryAllocator*
121
122/*---------------------------------------------------------------------------*/
123/*---------------------------------------------------------------------------*/
124/*!
125 * \brief Allocation par défaut pour la ressource \a mem_resource.
126 *
127 * Lève une exception si aucune allocateur n'est disponible pour la ressource
128 * (par exemple si on demande eMemoryResource::Device et qu'il n'y a pas de
129 * support pour les accélérateurs.
130 *
131 * La ressource eMemoryResource::UnifiedMemory est toujours disponible. Si
132 * aucun runtime accélérateur n'est chargé, alors c'est équivalent à
133 * eMemoryResource::Host.
134 */
135extern "C++" ARCANE_UTILS_EXPORT MemoryAllocationOptions
137
138/*---------------------------------------------------------------------------*/
139/*---------------------------------------------------------------------------*/
140/*!
141 * \brief Allocateur par défaut pour la ressource \a mem_resource.
142 *
143 * \sa getAllocationOptions().
144 */
145extern "C++" ARCANE_UTILS_EXPORT IMemoryAllocator*
146getAllocator(eMemoryResource mem_resource);
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
151namespace impl
152{
153 //! Calcule une capacité adaptée pour une taille de \a size
154 extern "C++" ARCANE_UTILS_EXPORT Int64
155 computeCapacity(Int64 size);
156} // namespace impl
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160/*!
161 * \brief Redimensionne un tableau en ajoutant une réserve de mémoire.
162 *
163 * Le tableau \a array est redimensionné uniquement si \a new_size est
164 * supérieure à la taille actuelle du tableau ou si \a force_resize est vrai.
165 *
166 * Si le tableau est redimensionné, on réserve une capacité supplémentaire
167 * pour éviter de réallouer à chaque fois.
168 *
169 * \retval 2 si on a réalloué via reserve()
170 * \retval 1 si on a re-dimensionné sans réallouer.
171 * \retval 0 si aucune opération n'a eu lieu.
172 */
173template <typename DataType> inline Int32
174checkResizeArrayWithCapacity(Array<DataType>& array, Int64 new_size, bool force_resize)
175{
176 Int32 ret_value = 0;
177 Int64 s = array.largeSize();
178 if (new_size > s || force_resize) {
179 ret_value = 1;
180 if (new_size > array.capacity()) {
181 array.reserve(impl::computeCapacity(new_size));
182 ret_value = 2;
183 }
184 array.resize(new_size);
185 }
186 return ret_value;
187}
188
189/*---------------------------------------------------------------------------*/
190/*---------------------------------------------------------------------------*/
191/*!
192 * \brief Redimensionne un tableau en ajoutant une réserve de mémoire.
193 *
194 * Cet appel est équivalent à checkResizeArrayWithCapacity(array, new_size, false).
195 */
196template <typename DataType> inline Int32
198{
199 return checkResizeArrayWithCapacity(array, new_size, false);
200}
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
204/*!
205 * \brief Copie de \a source vers \a destination en utilisant la file \a queue.
206 *
207 * Il est possible de spécifier la ressource mémoire où se trouve la source
208 * et la destination. Si on ne les connait pas, il est préférable d'utiliser
209 * la surcharge copy(MutableMemoryView destination, ConstMemoryView source, const RunQueue* queue).
210 */
211extern "C++" ARCANE_UTILS_EXPORT void
212copy(MutableMemoryView destination, eMemoryResource destination_mem,
213 ConstMemoryView source, eMemoryResource source_mem,
214 const RunQueue* queue = nullptr);
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219//! Copie de \a source vers \a destination en utilisant la file \a queue.
220inline void
221copy(MutableMemoryView destination, ConstMemoryView source, const RunQueue* queue = nullptr)
222{
224 copy(destination, mem_type, source, mem_type, queue);
225}
226
227/*---------------------------------------------------------------------------*/
228/*---------------------------------------------------------------------------*/
229
230//! Copie de \a source vers \a destination en utilisant la file \a queue.
231template <typename DataType> inline void
233 const RunQueue* queue = nullptr)
234{
235 ConstMemoryView input(asBytes(source));
236 MutableMemoryView output(asWritableBytes(destination));
237 copy(output, input, queue);
238}
239
240/*---------------------------------------------------------------------------*/
241/*---------------------------------------------------------------------------*/
242
243//! Copie de \a source vers \a destination en utilisant la file \a queue.
244template <typename DataType> inline void
246 const RunQueue* queue = nullptr)
247{
248 copy(Span<DataType>(destination), Span<const DataType>(source), queue);
249}
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253/*!
254 * \brief Copie sur l'hôte des données avec indirection.
255 *
256 * Copie dans \a destination les données de \a source
257 * indexées par \a indexes
258 *
259 * L'opération est équivalente au pseudo-code suivant:
260 *
261 * \code
262 * Int64 n = indexes.size();
263 * for( Int64 i=0; i<n; ++i )
264 * destination[i] = source[indexes[i]];
265 * \endcode
266 *
267 * \pre destination.datatypeSize() == source.datatypeSize();
268 * \pre source.nbElement() >= indexes.size();
269 */
270extern "C++" ARCANE_UTILS_EXPORT void
272 Span<const Int32> indexes);
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276/*!
277 * \brief Copie sur l'hôte des données avec indirection.
278 *
279 * Copie dans \a destination les données de \a source
280 * indexées par \a indexes
281 *
282 * \code
283 * Int32 n = indexes.size();
284 * for( Int32 i=0; i<n; ++i )
285 * destination[i] = source[indexes[i]];
286 * \endcode
287 *
288 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
289 *
290 * \pre destination.datatypeSize() == source.datatypeSize();
291 * \pre source.nbElement() >= indexes.size();
292 */
293extern "C++" ARCANE_UTILS_EXPORT void
296 RunQueue* run_queue = nullptr);
297
298/*---------------------------------------------------------------------------*/
299/*---------------------------------------------------------------------------*/
300/*!
301 * \brief Copie dans \a destination les données de \a source.
302 *
303 * Utilise std::memmove pour la copie.
304 *
305 * \pre source.bytes.size() >= destination.bytes.size()
306 */
307extern "C++" ARCANE_UTILS_EXPORT void
308copyHost(MutableMemoryView destination, ConstMemoryView source);
309
310/*---------------------------------------------------------------------------*/
311/*---------------------------------------------------------------------------*/
312/*!
313 * \brief Copie dans l'instance les données indexées de \a v.
314 *
315 * L'opération est équivalente au pseudo-code suivant:
316 *
317 * \code
318 * Int64 n = indexes.size();
319 * for( Int64 i=0; i<n; ++i )
320 * destination[indexes[i]] = source[i];
321 * \endcode
322 *
323 * \pre destination.datatypeSize() == source.datatypeSize();
324 * \pre destination.nbElement() >= indexes.size();
325 */
326extern "C++" ARCANE_UTILS_EXPORT void
328 Span<const Int32> indexes);
329
330/*---------------------------------------------------------------------------*/
331/*---------------------------------------------------------------------------*/
332/*!
333 * \brief Copie mémoire avec indirection
334 *
335 * Copie les données de \a source dans \a destination pour les indices
336 * spécifiés par \a indexes.
337 *
338 * L'opération est équivalente au pseudo-code suivant :
339 *
340 * \code
341 * Int32 n = indexes.size();
342 * for( Int32 i=0; i<n; ++i )
343 * destination[indexes[i]] = source[i];
344 * \endcode
345 *
346 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
347 *
348 * \pre destination.datatypeSize() == source.datatypeSize();
349 * \pre destination.nbElement() >= indexes.size();
350 */
351extern "C++" ARCANE_UTILS_EXPORT void
353 SmallSpan<const Int32> indexes, RunQueue* run_queue = nullptr);
354
355/*---------------------------------------------------------------------------*/
356/*---------------------------------------------------------------------------*/
357/*!
358 * \brief Remplit une zone mémoire indexée avec une valeur.
359 *
360 * Remplit les indices \a indexes de la zone mémoire \a destination avec
361 * la valeur de la zone mémoire \a source. \a source doit avoir une seule valeur.
362 * La zone mémoire \a source être accessible depuis l'hôte.
363 *
364 * L'opération est équivalente au pseudo-code suivant:
365 *
366 * \code
367 * Int32 n = indexes.size();
368 * for( Int32 i=0; i<n; ++i )
369 * destination[indexes[i]] = source[0];
370 * \endcode
371 *
372 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
373 *
374 * \pre destination.datatypeSize() == source.datatypeSize();
375 * \pre destination.nbElement() >= indexes.size();
376 */
377extern "C++" ARCANE_UTILS_EXPORT void
379 SmallSpan<const Int32> indexes, const RunQueue* run_queue = nullptr);
380
381/*---------------------------------------------------------------------------*/
382/*---------------------------------------------------------------------------*/
383/*!
384 * \brief Remplit une zone mémoire avec une valeur.
385 *
386 * Remplit les valeurs de la zone mémoire \a destination avec
387 * la valeur de la zone mémoire \a source. \a source doit avoir une seule valeur.
388 * La zone mémoire \a source être accessible depuis l'hôte.
389 *
390 * L'opération est équivalente au pseudo-code suivant :
391 *
392 * \code
393 * Int32 n = nbElement();
394 * for( Int32 i=0; i<n; ++i )
395 * destination[i] = source[0];
396 * \endcode
397 *
398 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
399 *
400 * \pre destination.datatypeSize() == source.datatypeSize();
401 */
402extern "C++" ARCANE_UTILS_EXPORT void
403fill(MutableMemoryView destination, ConstMemoryView source,
404 const RunQueue* run_queue = nullptr);
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408/*!
409 * \brief Copie dans \a destination les données de \a source indexées.
410 *
411 * L'opération est équivalente au pseudo-code suivant :
412 *
413 * \code
414 * Int32 n = indexes.size();
415 * for( Int32 i=0; i<n; ++i ){
416 * Int32 index0 = indexes[ (i*2) ];
417 * Int32 index1 = indexes[ (i*2)+1 ];
418 * destination[i] = source[index0][index1];
419 * }
420 * \endcode
421 *
422 * Le tableau \a indexes doit avoir une taille multiple de 2. Les valeurs
423 * paires servent à indexer le premier tableau et les valeurs impaires le 2ème.
424 *
425 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
426 *
427 * \pre destination.datatypeSize() == source.datatypeSize();
428 * \pre destination.nbElement() >= indexes.size();
429 */
430extern "C++" ARCANE_UTILS_EXPORT void
432 SmallSpan<const Int32> indexes, RunQueue* run_queue = nullptr);
433
434/*---------------------------------------------------------------------------*/
435/*---------------------------------------------------------------------------*/
436/*!
437 * \brief Copie les éléments indéxés de \a destination avec les données de \a source.
438 *
439 * L'opération est équivalente au pseudo-code suivant :
440 *
441 * \code
442 * Int32 n = indexes.size();
443 * for( Int32 i=0; i<n; ++i ){
444 * Int32 index0 = indexes[ (i*2) ];
445 * Int32 index1 = indexes[ (i*2)+1 ];
446 * destination[index0][index1] = source[i];
447 * }
448 * \endcode
449 *
450 * Le tableau \a indexes doit avoir une taille multiple de 2. Les valeurs
451 * paires servent à indexer le premier tableau et les valeurs impaires le 2ème.
452 *
453 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
454 *
455 * \pre destination.datatypeSize() == v.datatypeSize();
456 * \pre source.nbElement() >= indexes.size();
457 */
458extern "C++" ARCANE_UTILS_EXPORT void
460 SmallSpan<const Int32> indexes, RunQueue* run_queue = nullptr);
461
462/*---------------------------------------------------------------------------*/
463/*---------------------------------------------------------------------------*/
464/*!
465 * \brief Remplit les éléments indéxés de \a destination avec la donnée \a source.
466 *
467 * \a source doit avoir une seule valeur. Cette valeur sera utilisée
468 * pour remplir les valeurs de l'instance aux indices spécifiés par
469 * \a indexes. Elle doit être accessible depuis l'hôte.
470 *
471 * L'opération est équivalente au pseudo-code suivant :
472 *
473 * \code
474 * Int32 n = indexes.size();
475 * for( Int32 i=0; i<n; ++i ){
476 * Int32 index0 = indexes[ (i*2) ];
477 * Int32 index1 = indexes[ (i*2)+1 ];
478 * destination[index0][index1] = source[0];
479 * }
480 * \endcode
481 *
482 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
483 *
484 * \pre destination.datatypeSize() == source.datatypeSize();
485 * \pre destination.nbElement() >= indexes.size();
486 */
487extern "C++" ARCANE_UTILS_EXPORT void
489 SmallSpan<const Int32> indexes, RunQueue* run_queue = nullptr);
490
491/*---------------------------------------------------------------------------*/
492/*---------------------------------------------------------------------------*/
493/*!
494 * \brief Remplit les éléments de \a destination avec la valeur \a source.
495 *
496 * \a source doit avoir une seule valeur. Elle doit être accessible depuis l'hôte.
497 *
498 * L'opération est équivalente au pseudo-code suivant :
499 *
500 * \code
501 * Int32 n = nbElement();
502 * for( Int32 i=0; i<n; ++i ){
503 * Int32 index0 = (i*2);
504 * Int32 index1 = (i*2)+1;
505 * destination[index0][index1] = source[0];
506 * }
507 * \endcode
508 *
509 * Si \a run_queue n'est pas nul, elle sera utilisée pour la copie.
510 *
511 * \pre destination.datatypeSize() == source.datatypeSize();
512 */
513extern "C++" ARCANE_UTILS_EXPORT void
515 RunQueue* run_queue = nullptr);
516
517/*---------------------------------------------------------------------------*/
518/*---------------------------------------------------------------------------*/
519
520} // namespace Arcane::MemoryUtils
521
522/*---------------------------------------------------------------------------*/
523/*---------------------------------------------------------------------------*/
524
525#endif
Int64 computeCapacity(Int64 size)
Calcule une capacité adaptée pour une taille de size.
Integer capacity() const
Capacité (nombre d'éléments alloués) du vecteur.
Int64 largeSize() const
Nombre d'éléments du vecteur (en 64 bits)
File d'exécution pour un accélérateur.
Classe de base des vecteurs 1D de données.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
Vue constante sur une zone mémoire contigue contenant des éléments de taille fixe.
Definition MemoryView.h:38
Liste de vues constantes sur des zones mémoires contigues.
Definition MemoryView.h:259
Vue modifiable sur une zone mémoire contigue contenant des éléments de taille fixe.
Definition MemoryView.h:156
Liste de vues modifiables sur des zones mémoires contigues.
Definition MemoryView.h:295
Vue d'un tableau d'éléments de type T.
Definition Span.h:673
Vue d'un tableau d'éléments de type T.
Definition Span.h:513
Espace de noms pour les fonctions de gestion mémoire et des allocateurs.
void fill(MutableMemoryView destination, ConstMemoryView source, const RunQueue *run_queue=nullptr)
Remplit une zone mémoire avec une valeur.
IMemoryAllocator * getDeviceOrHostAllocator()
Retourne l'allocateur sur l'hôte ou sur le device.
void copyWithIndexedDestination(MutableMemoryView destination, ConstMemoryView source, SmallSpan< const Int32 > indexes, RunQueue *run_queue=nullptr)
Copie mémoire avec indirection.
MemoryAllocationOptions getAllocatorForMostlyReadOnlyData()
Allocateur par défaut pour les données essentiellement en lecture.
MemoryAllocationOptions getAllocationOptions(eMemoryResource mem_resource)
Allocation par défaut pour la ressource mem_resource.
IMemoryAllocator * getDefaultDataAllocator()
Allocateur par défaut pour les données.
void copyHostWithIndexedSource(MutableMemoryView destination, ConstMemoryView source, Span< const Int32 > indexes)
Copie sur l'hôte des données avec indirection.
eMemoryResource getMemoryResourceFromName(const String &name)
Retourne la ressource mémoire par son nom.
void fillIndexed(MutableMemoryView destination, ConstMemoryView source, SmallSpan< const Int32 > indexes, const RunQueue *run_queue=nullptr)
Remplit une zone mémoire indexée avec une valeur.
Int32 checkResizeArrayWithCapacity(Array< DataType > &array, Int64 new_size, bool force_resize)
Redimensionne un tableau en ajoutant une réserve de mémoire.
void copyHostWithIndexedDestination(MutableMemoryView destination, ConstMemoryView source, Span< const Int32 > indexes)
Copie dans l'instance les données indexées de v.
void copyHost(MutableMemoryView destination, ConstMemoryView source)
Copie dans destination les données de source.
Definition MemoryView.cc:90
IMemoryAllocator * getAcceleratorHostMemoryAllocator()
Allocateur spécifique pour les accélérateurs.
IMemoryAllocator * getAllocator(eMemoryResource mem_resource)
Allocateur par défaut pour la ressource mem_resource.
eMemoryResource getDefaultDataMemoryResource()
Ressource mémoire utilisée par l'allocateur par défaut pour les données.
void copy(MutableMemoryView destination, eMemoryResource destination_mem, ConstMemoryView source, eMemoryResource source_mem, const RunQueue *queue=nullptr)
Copie de source vers destination en utilisant la file queue.
void copyWithIndexedSource(MutableMemoryView destination, ConstMemoryView source, SmallSpan< const Int32 > indexes, RunQueue *run_queue=nullptr)
Copie sur l'hôte des données avec indirection.
impl::SpanTypeFromSize< std::byte, SizeType >::SpanType asWritableBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets modifiables.
Definition Span.h:919
std::int64_t Int64
Type entier signé sur 64 bits.
eMemoryLocationHint
Indices sur la localisation mémoire attendue.
impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Converti la vue en un tableau d'octets non modifiables.
Definition Span.h:884
eMemoryResource
Liste des ressources mémoire disponibles.
@ Unknown
Valeur inconnue ou non initialisée.
std::int32_t Int32
Type entier signé sur 32 bits.