Arcane  4.1.12.0
User documentation
Loading...
Searching...
No Matches
MemoryAllocator.cc
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/* MemoryAllocator.cc (C) 2000-2025 */
9/* */
10/* Memory allocators. */
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/common/DefaultMemoryAllocator.h"
20#include "arccore/common/AlignedMemoryAllocator.h"
21#include "arccore/common/AllocatedMemoryInfo.h"
22
23#include <cstdlib>
24#include <cstring>
25#include <errno.h>
26
27#if defined(ARCCORE_OS_WIN32)
28#include <malloc.h>
29#endif
30
31#include <iostream>
32
33#if defined(ARCCORE_OS_LINUX) || defined(ARCCORE_OS_MACOS)
34#define ARCCORE_USE_POSIX_MEMALIGN
35#endif
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40namespace Arcane
41{
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
46DefaultMemoryAllocator DefaultMemoryAllocator::shared_null_instance;
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
53{
54 return this->guaranteedAlignment(args);
55}
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
69copyMemory([[maybe_unused]] MemoryAllocationArgs args, AllocatedMemoryInfo destination,
71{
72 std::memcpy(destination.baseAddress(), source.baseAddress(), source.size());
73}
74
75/*---------------------------------------------------------------------------*/
76/*---------------------------------------------------------------------------*/
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80
83{
84 return true;
85}
86
87/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
92{
93 return { ::malloc(new_size), new_size };
94}
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
98
101{
102 return { ::realloc(current_ptr.baseAddress(), new_size), new_size };
103}
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
116
118adjustedCapacity(MemoryAllocationArgs, Int64 wanted_capacity, Int64) const
119{
120 return wanted_capacity;
121}
122
123/*---------------------------------------------------------------------------*/
124/*---------------------------------------------------------------------------*/
125
126/*---------------------------------------------------------------------------*/
127/*---------------------------------------------------------------------------*/
128
129AlignedMemoryAllocator AlignedMemoryAllocator::
131
132AlignedMemoryAllocator AlignedMemoryAllocator::
134
135/*---------------------------------------------------------------------------*/
136/*---------------------------------------------------------------------------*/
137
138/*!
139 * NOTE: Normally the _mm_alloc() and _mm_free() functions allow
140 * allocating aligned memory. It should be checked if they are
141 * available everywhere.
142 */
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
148allocate([[maybe_unused]] MemoryAllocationArgs args, Int64 new_size)
149{
150#if defined(ARCCORE_USE_POSIX_MEMALIGN)
151 void* ptr = nullptr;
152 int e = ::posix_memalign(&ptr, m_alignment, new_size);
153 if (e == EINVAL)
154 throw ArgumentException(A_FUNCINFO, "Invalid argument to posix_memalign");
155 if (e == ENOMEM)
156 return AllocatedMemoryInfo(nullptr);
157 return AllocatedMemoryInfo(ptr, new_size);
158#elif defined(ARCCORE_OS_WIN32)
159 return AllocatedMemoryInfo(_aligned_malloc(new_size, m_alignment), new_size);
160#else
161 throw NotImplementedException(A_FUNCINFO);
162#endif
163}
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
167
169reallocate([[maybe_unused]] MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size)
170{
171#if defined(ARCCORE_USE_POSIX_MEMALIGN)
172 ARCCORE_UNUSED(current_ptr);
173 ARCCORE_UNUSED(new_size);
174 throw NotSupportedException(A_FUNCINFO);
175#elif defined(ARCCORE_OS_WIN32)
176 return AllocatedMemoryInfo(_aligned_realloc(current_ptr.baseAddress(), new_size, m_alignment), new_size);
177#else
178 throw NotImplementedException(A_FUNCINFO);
179#endif
180}
181
182/*---------------------------------------------------------------------------*/
183/*---------------------------------------------------------------------------*/
184
186deallocate([[maybe_unused]] MemoryAllocationArgs args, AllocatedMemoryInfo ptr)
187{
188#if defined(ARCCORE_USE_POSIX_MEMALIGN)
189 ::free(ptr.baseAddress());
190#elif defined(ARCCORE_OS_WIN32)
191 return _aligned_free(ptr.baseAddress());
192#else
193 throw NotImplementedException(A_FUNCINFO);
194#endif
195}
196
197/*---------------------------------------------------------------------------*/
198/*---------------------------------------------------------------------------*/
199
200namespace
201{
202 bool is_verbose = false;
203}
204
205size_t
206adjustMemoryCapacity(size_t wanted_capacity, size_t element_size, size_t alignment)
207{
208 if (element_size == 0)
209 return wanted_capacity;
210 // If \a element_size is smaller than \a m_alignment, consider that
211 // the allocated memory must be a multiple of the alignment.
212 // (We could be more restrictive depending on the types but it is not in
213 // general useful).
214 size_t block_size = alignment / element_size;
215 if (block_size <= 1)
216 return wanted_capacity;
217
218 // If the alignment is not a multiple of the element size,
219 // it means that the element will not be used for vectorization.
220 // Therefore, it is not necessary in this case to modify the capacity.
221 size_t nb_element = alignment % element_size;
222 if (nb_element != 0)
223 return wanted_capacity;
224
225 if (is_verbose)
226 std::cout << " wanted_capacity=" << wanted_capacity
227 << " element_size=" << element_size
228 << " block_size=" << block_size << '\n';
229
230 // Adds to the capacity what is needed for the modulo to be 0.
231 size_t modulo = wanted_capacity % block_size;
232 if (modulo != 0)
233 wanted_capacity += (block_size - modulo);
234 if (is_verbose)
235 std::cout << " final_wanted_capacity=" << wanted_capacity
236 << " modulo=" << modulo << '\n';
237 ARCCORE_ASSERT(((wanted_capacity % block_size) == 0), ("Bad capacity"));
238 return wanted_capacity;
239}
240
241/*---------------------------------------------------------------------------*/
242/*---------------------------------------------------------------------------*/
243
245adjustedCapacity([[maybe_unused]] MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const
246{
247 return adjustMemoryCapacity(wanted_capacity, element_size, m_alignment);
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
257allocate(MemoryAllocationArgs args, Int64 new_size)
258{
259 AllocatedMemoryInfo mem_info = Base::allocate(args, new_size);
260 std::cout << "DEF_ARRAY_ALLOCATE new_size=" << new_size << " ptr=" << mem_info.baseAddress() << '\n';
261 return mem_info;
262}
263
264/*---------------------------------------------------------------------------*/
265/*---------------------------------------------------------------------------*/
266
268reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size)
269{
270 AllocatedMemoryInfo mem_info = Base::reallocate(args, current_ptr, new_size);
271 std::cout << "DEF_ARRAY_REALLOCATE new_size=" << new_size
272 << " current_ptr=" << current_ptr.baseAddress()
273 << " new_ptr=" << mem_info.baseAddress() << '\n';
274 return mem_info;
275}
276
277/*---------------------------------------------------------------------------*/
278/*---------------------------------------------------------------------------*/
279
282{
283 std::cout << "DEF_ARRAY_DEALLOCATE ptr=" << ptr.baseAddress() << '\n';
284 Base::deallocate(args, ptr);
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290} // namespace Arcane
291
292/*---------------------------------------------------------------------------*/
293/*---------------------------------------------------------------------------*/
Memory allocator with specific memory alignment.
AllocatedMemoryInfo allocate(MemoryAllocationArgs args, Int64 new_size) override
static constexpr Integer simdAlignment()
Alignment for structures using vectorization.
void deallocate(MemoryAllocationArgs args, AllocatedMemoryInfo ptr) override
Frees the memory whose base address is ptr.
Int64 adjustedCapacity(MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const override
Adjusts the capacity based on the element size.
AllocatedMemoryInfo reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size) override
Reallocates memory for new_size bytes and returns the pointer.
static constexpr Integer cacheLineAlignment()
Alignment for a cache line.
Information about an allocated memory region.
void * baseAddress() const
Address of the start of the allocated region.
Int64 size() const
Size in bytes of the used memory region. (-1) if unknown.
Memory allocator via malloc/realloc/free.
void deallocate(MemoryAllocationArgs, AllocatedMemoryInfo ptr) override
Frees the memory whose base address is ptr.
AllocatedMemoryInfo reallocate(MemoryAllocationArgs, AllocatedMemoryInfo current_ptr, Int64 new_size) override
Reallocates memory for new_size bytes and returns the pointer.
Int64 adjustedCapacity(MemoryAllocationArgs, Int64 wanted_capacity, Int64 element_size) const override
Adjusts the capacity based on the element size.
AllocatedMemoryInfo allocate(MemoryAllocationArgs, Int64 new_size) override
Allocates memory for new_size bytes and returns the pointer.
bool hasRealloc(MemoryAllocationArgs) const override
Indicates whether the allocator supports realloc semantics.
virtual void copyMemory(MemoryAllocationArgs args, AllocatedMemoryInfo destination, AllocatedMemoryInfo source)
Copies memory between two regions.
virtual void notifyMemoryArgsChanged(MemoryAllocationArgs old_args, MemoryAllocationArgs new_args, AllocatedMemoryInfo ptr)
Notifies of a change in instance-specific arguments.
virtual size_t guarantedAlignment(MemoryAllocationArgs args) const
Value of the alignment guaranteed by the allocator.
virtual size_t guaranteedAlignment(MemoryAllocationArgs args) const =0
Value of the alignment guaranteed by the allocator.
Class containing information to specialize allocations.
AllocatedMemoryInfo reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_ptr, Int64 new_size) override
Reallocates memory for new_size bytes and returns the pointer.
void deallocate(MemoryAllocationArgs args, AllocatedMemoryInfo ptr) override
Frees the memory whose base address is ptr.
AllocatedMemoryInfo allocate(MemoryAllocationArgs args, Int64 new_size) override
Allocates memory for new_size bytes and returns the pointer.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.