Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
MemoryAllocator.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2023 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/* MemoryAllocator.cc (C) 2000-2023 */
9/* */
10/* Allocateurs mémoires. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/base/ArgumentException.h"
15#include "arccore/base/NotSupportedException.h"
16#include "arccore/base/NotImplementedException.h"
17#include "arccore/base/TraceInfo.h"
18
19#include "arccore/collections/IMemoryAllocator.h"
20
21#include <cstdlib>
22#include <cstring>
23#include <errno.h>
24
25#if defined(ARCCORE_OS_WIN32)
26#include <malloc.h>
27#endif
28
29#include <iostream>
30
31#if defined(ARCCORE_OS_LINUX) || defined(ARCCORE_OS_MACOS)
32#define ARCCORE_USE_POSIX_MEMALIGN
33#endif
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arccore
39{
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
47DefaultMemoryAllocator3 DefaultMemoryAllocator3::shared_null_instance;
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
61copyMemory([[maybe_unused]] MemoryAllocationArgs args, AllocatedMemoryInfo destination,
63{
64 std::memcpy(destination.baseAddress(), source.baseAddress(), source.size());
66
67/*---------------------------------------------------------------------------*/
68/*---------------------------------------------------------------------------*/
69
70bool DefaultMemoryAllocator::
71hasRealloc() const
72{
73 return true;
74}
76/*---------------------------------------------------------------------------*/
77/*---------------------------------------------------------------------------*/
78
79void* DefaultMemoryAllocator::
80allocate(size_t new_size)
81{
82 return ::malloc(new_size);
83}
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88void* DefaultMemoryAllocator::
89reallocate(void* current_ptr, size_t new_size)
90{
91 return ::realloc(current_ptr, new_size);
92}
93
94/*---------------------------------------------------------------------------*/
95/*---------------------------------------------------------------------------*/
96
97void DefaultMemoryAllocator::
98deallocate(void* ptr)
100 ::free(ptr);
101}
102
103/*---------------------------------------------------------------------------*/
104/*---------------------------------------------------------------------------*/
105
106size_t DefaultMemoryAllocator::
107adjustCapacity(size_t wanted_capacity, size_t)
108{
109 return wanted_capacity;
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115/*---------------------------------------------------------------------------*/
116/*---------------------------------------------------------------------------*/
117
118bool DefaultMemoryAllocator3::
119hasRealloc(MemoryAllocationArgs) const
121 return true;
122}
123
124/*---------------------------------------------------------------------------*/
125/*---------------------------------------------------------------------------*/
126
129{
130 return { ::malloc(new_size), new_size };
131}
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135
138{
139 return { ::realloc(current_ptr.baseAddress(), new_size), new_size };
140}
141
142/*---------------------------------------------------------------------------*/
143/*---------------------------------------------------------------------------*/
144
150
151/*---------------------------------------------------------------------------*/
152/*---------------------------------------------------------------------------*/
153
155adjustedCapacity(MemoryAllocationArgs, Int64 wanted_capacity, Int64 ) const
156{
157 return wanted_capacity;
158}
159
160/*---------------------------------------------------------------------------*/
161/*---------------------------------------------------------------------------*/
162
163/*---------------------------------------------------------------------------*/
164/*---------------------------------------------------------------------------*/
165
166AlignedMemoryAllocator AlignedMemoryAllocator::
168
169AlignedMemoryAllocator AlignedMemoryAllocator::
171
172AlignedMemoryAllocator3 AlignedMemoryAllocator3::
174
175AlignedMemoryAllocator3 AlignedMemoryAllocator3::
177
178/*---------------------------------------------------------------------------*/
179/*---------------------------------------------------------------------------*/
180/*!
181 * NOTE: Normalement les fonctions _mm_alloc() et _mm_free() permettent
182 * d'allouer de la mémoire alignée. Il faudrait vérifier si elles sont
183 * disponibles partout.
184 */
185
186/*---------------------------------------------------------------------------*/
187/*---------------------------------------------------------------------------*/
188
190hasRealloc() const
191{
192 return false;
193}
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
197
198void* AlignedMemoryAllocator::
199allocate(size_t new_size)
200{
201#if defined(ARCCORE_USE_POSIX_MEMALIGN)
202 void* ptr = nullptr;
203 int e = ::posix_memalign(&ptr, m_alignment, new_size);
204 if (e == EINVAL)
205 throw ArgumentException(A_FUNCINFO, "Invalid argument to posix_memalign");
206 if (e == ENOMEM)
207 return nullptr;
208 return ptr;
209#elif defined(ARCCORE_OS_WIN32)
210 return _aligned_malloc(new_size, m_alignment);
211#else
212 throw NotImplementedException(A_FUNCINFO);
213#endif
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
220allocate([[maybe_unused]] MemoryAllocationArgs args, Int64 new_size)
221{
222#if defined(ARCCORE_USE_POSIX_MEMALIGN)
223 void* ptr = nullptr;
224 int e = ::posix_memalign(&ptr, m_alignment, new_size);
225 if (e == EINVAL)
226 throw ArgumentException(A_FUNCINFO, "Invalid argument to posix_memalign");
227 if (e == ENOMEM)
228 return AllocatedMemoryInfo(nullptr);
229 return AllocatedMemoryInfo(ptr, new_size);
230#elif defined(ARCCORE_OS_WIN32)
231 return AllocatedMemoryInfo(_aligned_malloc(new_size, m_alignment), new_size);
232#else
233 throw NotImplementedException(A_FUNCINFO);
234#endif
235}
236
237/*---------------------------------------------------------------------------*/
238/*---------------------------------------------------------------------------*/
239
240void* AlignedMemoryAllocator::
241reallocate(void* current_ptr, size_t new_size)
242{
243#if defined(ARCCORE_USE_POSIX_MEMALIGN)
244 ARCCORE_UNUSED(current_ptr);
245 ARCCORE_UNUSED(new_size);
246 throw NotSupportedException(A_FUNCINFO);
247#elif defined(ARCCORE_OS_WIN32)
248 return _aligned_realloc(current_ptr, new_size, m_alignment);
249#else
250 throw NotImplementedException(A_FUNCINFO);
251#endif
252}
253
254/*---------------------------------------------------------------------------*/
255/*---------------------------------------------------------------------------*/
256
258reallocate([[maybe_unused]] MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size)
259{
260#if defined(ARCCORE_USE_POSIX_MEMALIGN)
261 ARCCORE_UNUSED(current_ptr);
262 ARCCORE_UNUSED(new_size);
263 throw NotSupportedException(A_FUNCINFO);
264#elif defined(ARCCORE_OS_WIN32)
265 return AllocatedMemoryInfo(_aligned_realloc(current_ptr.baseAddress(), new_size, m_alignment), new_size);
266#else
267 throw NotImplementedException(A_FUNCINFO);
268#endif
269}
270
271/*---------------------------------------------------------------------------*/
272/*---------------------------------------------------------------------------*/
273
274void AlignedMemoryAllocator::
275deallocate(void* ptr)
276{
277#if defined(ARCCORE_USE_POSIX_MEMALIGN)
278 ::free(ptr);
279#elif defined(ARCCORE_OS_WIN32)
280 return _aligned_free(ptr);
281#else
282 throw NotImplementedException(A_FUNCINFO);
283#endif
284}
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
288
290deallocate([[maybe_unused]] MemoryAllocationArgs args, AllocatedMemoryInfo ptr)
291{
292#if defined(ARCCORE_USE_POSIX_MEMALIGN)
293 ::free(ptr.baseAddress());
294#elif defined(ARCCORE_OS_WIN32)
295 return _aligned_free(ptr.baseAddress());
296#else
297 throw NotImplementedException(A_FUNCINFO);
298#endif
299}
300
301/*---------------------------------------------------------------------------*/
302/*---------------------------------------------------------------------------*/
303
304namespace
305{
306 bool is_verbose = false;
307}
308
309size_t
310adjustMemoryCapacity(size_t wanted_capacity, size_t element_size, size_t alignment)
311{
312 if (element_size == 0)
313 return wanted_capacity;
314 // Si \a element_size est plus petit que \a m_alignment, considère que
315 // la mémoire allouée doit être un multiple de l'alignement.
316 // (On pourrait être plus restrictif suivant les types mais ce n'est en
317 // général pas utile).
318 size_t block_size = alignment / element_size;
319 if (block_size <= 1)
320 return wanted_capacity;
321
322 // Si l'alignement n'est pas un multiple de la taille d'un élément,
323 // cela signifie que l'élément ne sera pas utilisé pour la vectorisation.
324 // Il n'est donc pas nécessaire dans ce cas de modifier la capacité.
325 size_t nb_element = alignment % element_size;
326 if (nb_element != 0)
327 return wanted_capacity;
328
329 if (is_verbose)
330 std::cout << " wanted_capacity=" << wanted_capacity
331 << " element_size=" << element_size
332 << " block_size=" << block_size << '\n';
333
334 // Ajoute à la capacité ce qu'il faut pour que le module soit 0.
335 size_t modulo = wanted_capacity % block_size;
336 if (modulo != 0)
337 wanted_capacity += (block_size - modulo);
338 if (is_verbose)
339 std::cout << " final_wanted_capacity=" << wanted_capacity
340 << " modulo=" << modulo << '\n';
341 ARCCORE_ASSERT(((wanted_capacity % block_size) == 0), ("Bad capacity"));
342 return wanted_capacity;
343}
344
345/*---------------------------------------------------------------------------*/
346/*---------------------------------------------------------------------------*/
347
348size_t AlignedMemoryAllocator::
349adjustCapacity(size_t wanted_capacity, size_t element_size)
350{
351 return adjustMemoryCapacity(wanted_capacity, element_size, m_alignment);
352}
353
354/*---------------------------------------------------------------------------*/
355/*---------------------------------------------------------------------------*/
356
358adjustedCapacity([[maybe_unused]] MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const
359{
360 return adjustMemoryCapacity(wanted_capacity, element_size, m_alignment);
361}
362
363/*---------------------------------------------------------------------------*/
364/*---------------------------------------------------------------------------*/
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
369void* PrintableMemoryAllocator::
370allocate(size_t new_size)
371{
372 void* ptr = Base::allocate(new_size);
373 std::cout << "DEF_ARRAY_ALLOCATE new_size=" << new_size << " ptr=" << ptr << '\n';
374 return ptr;
375}
376
377/*---------------------------------------------------------------------------*/
378/*---------------------------------------------------------------------------*/
379
380void* PrintableMemoryAllocator::
381reallocate(void* current_ptr, size_t new_size)
382{
383 void* ptr = Base::reallocate(current_ptr, new_size);
384 std::cout << "DEF_ARRAY_REALLOCATE new_size=" << new_size
385 << " current_ptr=" << current_ptr
386 << " new_ptr=" << ptr << '\n';
387 return ptr;
388}
389
390/*---------------------------------------------------------------------------*/
391/*---------------------------------------------------------------------------*/
392
393void PrintableMemoryAllocator::
394deallocate(void* ptr)
395{
396 std::cout << "DEF_ARRAY_DEALLOCATE ptr=" << ptr << '\n';
397 Base::deallocate(ptr);
398}
399
400/*---------------------------------------------------------------------------*/
401/*---------------------------------------------------------------------------*/
402
403bool IMemoryAllocator::
404hasRealloc(MemoryAllocationArgs) const
405{
406 return hasRealloc();
407}
408
414
417{
418 return AllocatedMemoryInfo(this->reallocate(current_ptr.baseAddress(), new_size));
419}
420
426
428adjustedCapacity(MemoryAllocationArgs, Int64 wanted_capacity, Int64 element_size) const
429{
430 auto* x = const_cast<IMemoryAllocator*>(this);
431 return x->adjustCapacity(wanted_capacity, element_size);
432}
433
434size_t IMemoryAllocator::
435guarantedAlignment(MemoryAllocationArgs) const
436{
437 auto* x = const_cast<IMemoryAllocator*>(this);
438 return x->guarantedAlignment();
439}
440
441/*---------------------------------------------------------------------------*/
442/*---------------------------------------------------------------------------*/
443
444bool IMemoryAllocator3::
445hasRealloc() const
446{
447 return hasRealloc(MemoryAllocationArgs{});
448}
450allocate(size_t new_size)
451{
452 return allocate(MemoryAllocationArgs{}, new_size).baseAddress();
453}
455reallocate(void* current_ptr, size_t new_size)
456{
457 return reallocate(MemoryAllocationArgs{},AllocatedMemoryInfo(current_ptr), new_size).baseAddress();
458}
460deallocate(void* ptr)
461{
462 deallocate(MemoryAllocationArgs{},AllocatedMemoryInfo(ptr));
463}
464size_t IMemoryAllocator3::
465adjustCapacity(size_t wanted_capacity, size_t element_size)
466{
467 return adjustedCapacity(MemoryAllocationArgs{},wanted_capacity, element_size);
468}
469size_t IMemoryAllocator3::
470guarantedAlignment()
471{
472 return guarantedAlignment(MemoryAllocationArgs{});
473}
474
475/*---------------------------------------------------------------------------*/
476/*---------------------------------------------------------------------------*/
477
478} // namespace Arccore
479
480/*---------------------------------------------------------------------------*/
481/*---------------------------------------------------------------------------*/
Allocateur mémoire avec alignement mémoire spécifique.
AllocatedMemoryInfo reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size) override
Réalloue de la mémoire pour new_size octets et retourne le pointeur.
static constexpr Integer simdAlignment()
Alignement pour les structures utilisant la vectorisation.
void deallocate(MemoryAllocationArgs args, AllocatedMemoryInfo ptr) override
Libère la mémoire dont l'adresse de base est ptr.
AllocatedMemoryInfo allocate(MemoryAllocationArgs args, Int64 new_size) override
Alloue de la mémoire pour new_size octets et retourne le pointeur.
Int64 adjustedCapacity(MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const override
Ajuste la capacité suivant la taille d'élément.
Allocateur mémoire avec alignement mémoire spécifique.
static constexpr Integer simdAlignment()
Alignement pour les structures utilisant la vectorisation.
static constexpr Integer cacheLineAlignment()
Alignement pour une ligne de cache.
Informations sur une zone mémoire allouée.
Int64 size() const
Taille en octets de la zone mémoire utilisée. (-1) si inconnue.
void * baseAddress() const
Adresse du début de la zone allouée.
Exception lorsqu'un argument est invalide.
AllocatedMemoryInfo reallocate(MemoryAllocationArgs, AllocatedMemoryInfo current_ptr, Int64 new_size) override
Réalloue de la mémoire pour new_size octets et retourne le pointeur.
Int64 adjustedCapacity(MemoryAllocationArgs, Int64 wanted_capacity, Int64 element_size) const override
Ajuste la capacité suivant la taille d'élément.
void deallocate(MemoryAllocationArgs, AllocatedMemoryInfo ptr) override
Libère la mémoire dont l'adresse de base est ptr.
AllocatedMemoryInfo allocate(MemoryAllocationArgs, Int64 new_size) override
Alloue de la mémoire pour new_size octets et retourne le pointeur.
virtual Int64 adjustedCapacity(MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const =0
Ajuste la capacité suivant la taille d'élément.
virtual AllocatedMemoryInfo reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size)=0
Réalloue de la mémoire pour new_size octets et retourne le pointeur.
virtual AllocatedMemoryInfo allocate(MemoryAllocationArgs args, Int64 new_size)=0
Alloue de la mémoire pour new_size octets et retourne le pointeur.
virtual void deallocate(MemoryAllocationArgs args, AllocatedMemoryInfo ptr)=0
Libère la mémoire dont l'adresse de base est ptr.
virtual size_t guarantedAlignment(MemoryAllocationArgs args) const =0
Valeur de l'alignement garanti par l'allocateur.
virtual bool hasRealloc(MemoryAllocationArgs args) const
Indique si l'allocateur supporte la sémantique de realloc.
virtual AllocatedMemoryInfo reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size)
Réalloue de la mémoire pour new_size octets et retourne le pointeur.
virtual void notifyMemoryArgsChanged(MemoryAllocationArgs old_args, MemoryAllocationArgs new_args, AllocatedMemoryInfo ptr)
Notifie du changement des arguments spécifiques à l'instance.
virtual size_t guarantedAlignment(MemoryAllocationArgs args) const
Valeur de l'alignement garanti par l'allocateur.
virtual AllocatedMemoryInfo allocate(MemoryAllocationArgs args, Int64 new_size)
Alloue de la mémoire pour new_size octets et retourne le pointeur.
virtual void deallocate(MemoryAllocationArgs args, AllocatedMemoryInfo ptr)
Libère la mémoire dont l'adresse de base est ptr.
virtual void copyMemory(MemoryAllocationArgs args, AllocatedMemoryInfo destination, AllocatedMemoryInfo source)
Copie la mémoire entre deux zones.
virtual Int64 adjustedCapacity(MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const
Ajuste la capacité suivant la taille d'élément.
Classe contenant des informations pour spécialiser les allocations.
Espace de nom de Arccore.
Definition ArcaneTypes.h:24
std::int64_t Int64
Type entier signé sur 64 bits.