14#include "arcane/accelerator/cuda/CudaAccelerator.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/Array.h"
18#include "arcane/utils/TraceInfo.h"
19#include "arcane/utils/NotSupportedException.h"
20#include "arcane/utils/FatalErrorException.h"
21#include "arcane/utils/ValueConvert.h"
22#include "arcane/utils/IMemoryAllocator.h"
23#include "arcane/utils/OStringStream.h"
24#include "arcane/utils/ITraceMng.h"
25#include "arcane/utils/internal/MemoryPool.h"
27#include "arcane/accelerator/core/internal/MemoryTracer.h"
34namespace Arcane::Accelerator::Cuda
36using namespace Arcane::impl;
43enum class MemoryPoolFlags
99 void dumpStats(std::ostream&
ostr,
const String& name)
140 uintptr_t
addr =
reinterpret_cast<uintptr_t
>(
ptr);
211 ARCANE_CHECK_CUDA(m_base->m_concrete_allocator->_allocate(&out, size));
212 m_base->m_block_wrapper.doAllocate(out, size);
217 ARCANE_CHECK_CUDA_NOTHROW(m_base->m_concrete_allocator->_deallocate(
ptr));
230 , m_direct_sub_allocator(this)
232 , m_sub_allocator(&m_direct_sub_allocator)
236 m_print_level = v.value();
239 ~CudaMemoryAllocatorBase()
247 if (m_print_level >= 1) {
249 if (m_use_memory_pool) {
250 m_memory_pool.dumpStats(
ostr());
251 m_memory_pool.dumpFreeMap(
ostr());
253 ostr() <<
"Allocator '" << m_allocator_name <<
"' nb_realloc=" << m_nb_reallocate
254 <<
" realloc_copy=" << m_reallocate_size <<
"\n";
255 m_block_wrapper.dumpStats(
ostr(), m_allocator_name);
259 std::cout <<
ostr.str();
273 ARCANE_FATAL(
"Bad alignment for CUDA allocator: offset={0}", (a % 128));
274 m_tracer.traceAllocate(out,
new_size, args);
284 const bool do_print = (m_print_level >= 2);
286 std::cout <<
"Reallocate allocator=" << m_allocator_name
291 if (
array_name.null() && m_print_level >= 3) {
292 std::cout <<
" stack=" << platform::getStackTrace();
296 if (m_print_level >= 4)
297 std::cout <<
" stack=" << platform::getStackTrace();
301 if (m_use_memory_pool)
313 if (m_use_memory_pool)
318 m_tracer.traceDeallocate(
mem_info, args);
337 impl::MemoryTracerWrapper m_tracer;
338 std::unique_ptr<ConcreteAllocator> m_concrete_allocator;
339 UnderlyingAllocator m_direct_sub_allocator;
342 bool m_use_memory_pool =
false;
344 std::atomic<Int32> m_nb_reallocate = 0;
345 std::atomic<Int64> m_reallocate_size = 0;
346 Int32 m_print_level = 0;
350 BlockAllocatorWrapper m_block_wrapper;
354 void _setTraceLevel(
Int32 v) { m_tracer.setTraceLevel(v); }
356 void _setUseMemoryPool(
bool is_used)
365 ARCANE_FATAL(
"Invalid value '{0}' for memory pool max block size");
366 size_t block_size =
static_cast<size_t>(v.value());
395 m_use_ats = v.value();
405 return ::cudaFree(
ptr);
428 bool m_use_ats =
false;
437 _setTraceLevel(v.value());
450 use_memory_pool = (v.value() &
static_cast<int>(MemoryPoolFlags::UVM)) != 0;
459 void*
p =
ptr.baseAddress();
475 if (
hint == eMemoryLocationHint::MainlyDevice ||
hint == eMemoryLocationHint::HostAndDeviceMostlyRead) {
479 if (
hint == eMemoryLocationHint::MainlyDevice ||
hint == eMemoryLocationHint::HostAndDeviceMostlyRead) {
483 if (
hint == eMemoryLocationHint::MainlyHost) {
487 if (
hint == eMemoryLocationHint::HostAndDeviceMostlyRead) {
494 if (
hint == eMemoryLocationHint::None)
502 bool m_use_ats =
false;
524 return ::cudaFreeHost(
ptr);
541 use_memory_pool = (v.value() &
static_cast<int>(MemoryPoolFlags::HostPinned)) != 0;
562 m_use_ats = v.value();
585 return ::cudaFree(
ptr);
590 bool m_use_ats =
false;
606 use_memory_pool = (v.value() &
static_cast<int>(MemoryPoolFlags::Device)) != 0;
626getCudaMemoryAllocator()
632getCudaDeviceMemoryAllocator()
638getCudaUnifiedMemoryAllocator()
644getCudaHostPinnedMemoryAllocator()
652void initializeCudaMemoryAllocators()
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classe commune pour gérer l'allocation par bloc.
bool m_do_block_allocate
Indique si l'allocation en utilisant m_block_size.
std::atomic< Int32 > m_nb_allocate
Nombre d'allocations.
std::atomic< Int32 > m_nb_unaligned_allocate
Nombre d'allocations non alignées.
Int64 m_block_size
Taille d'un bloc. L'allocation sera un multiple de cette taille.
void freeMemory(void *ptr, size_t size) override
Libère le bloc situé à l'adresse address contenant size octets.
void * allocateMemory(size_t size) override
Alloue un bloc pour size octets.
Classe de base d'un allocateur spécifique pour 'Cuda'.
bool hasRealloc(MemoryAllocationArgs) const final
Indique si l'allocateur supporte la sémantique de realloc.
AllocatedMemoryInfo reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_info, Int64 new_size) final
Réalloue de la mémoire pour new_size octets et retourne le pointeur.
AllocatedMemoryInfo allocate(MemoryAllocationArgs args, Int64 new_size) final
Alloue de la mémoire pour new_size octets et retourne le pointeur.
Int64 adjustedCapacity(MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const final
Ajuste la capacité suivant la taille d'élément.
void deallocate(MemoryAllocationArgs args, AllocatedMemoryInfo mem_info) final
Libère la mémoire dont l'adresse de base est ptr.
Allocateur pour la mémoire unifiée.
void notifyMemoryArgsChanged(MemoryAllocationArgs old_args, MemoryAllocationArgs new_args, AllocatedMemoryInfo ptr) final
Notifie du changement des arguments spécifiques à l'instance.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Flot de sortie lié à une String.
Interface d'un allocateur pour un MemoryPool.
virtual void * allocateMemory(size_t size)=0
Alloue un bloc pour size octets.
virtual void freeMemory(void *address, size_t size)=0
Libère le bloc situé à l'adresse address contenant size octets.
Classe pour gérer une liste de zone allouées.
void setMaxCachedBlockSize(size_t v)
Positionne la taille en octet à partir de laquelle on ne conserve pas un bloc dans le cache.
void freeCachedMemory()
Libère la mémoire dans le cache.
Allocateur mémoire avec alignement mémoire spécifique.
Int64 adjustedCapacity(MemoryAllocationArgs args, Int64 wanted_capacity, Int64 element_size) const override
Ajuste la capacité suivant la taille d'élément.
Informations sur une zone mémoire allouée.
Exception lorsqu'une erreur fatale est survenue.
Interface d'un allocateur pour la mémoire.
Interface du gestionnaire de traces.
Classe contenant des informations pour spécialiser les allocations.
Chaîne de caractères unicode.
TraceMessage info() const
Flot pour un message d'information.
Espace de nom de Arccore.
eMemoryLocationHint
Indices sur la localisation mémoire attendue.
std::int64_t Int64
Type entier signé sur 64 bits.
std::int32_t Int32
Type entier signé sur 32 bits.