Arcane  v4.1.1.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
AcceleratorMemoryAllocatorBase.cc
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/* AcceleratorMemoryAllocatorBase.cc (C) 2000-2025 */
9/* */
10/* Classe de base d'un allocateur spécifique pour accélérateur. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/common/accelerator/internal/AcceleratorMemoryAllocatorBase.h"
15
16#include "arccore/base/Convert.h"
17#include "arccore/base/PlatformUtils.h"
18#include "arccore/trace/ITraceMng.h"
19
20#include <iostream>
21#include <sstream>
22
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26namespace Arcane::Accelerator
27{
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32void BlockAllocatorWrapper::
33dumpStats(std::ostream& ostr, const String& name)
34{
35 ostr << "Allocator '" << name << "' : nb_allocate=" << m_nb_allocate
36 << " nb_unaligned=" << m_nb_unaligned_allocate
37 << "\n";
38}
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43/*---------------------------------------------------------------------------*/
44/*---------------------------------------------------------------------------*/
45
46AcceleratorMemoryAllocatorBase::
47AcceleratorMemoryAllocatorBase(const String& allocator_name, IUnderlyingAllocator* underlying_allocator)
48: AlignedMemoryAllocator(128)
49, m_direct_sub_allocator(underlying_allocator)
50, m_memory_pool(m_direct_sub_allocator.get(), allocator_name)
51, m_sub_allocator(m_direct_sub_allocator.get())
52, m_allocator_name(allocator_name)
53{
54 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ACCELERATOR_MEMORY_PRINT_LEVEL", true))
55 m_print_level = v.value();
56}
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61void AcceleratorMemoryAllocatorBase::
62finalize(ITraceMng* tm)
63{
64 if (m_print_level >= 1) {
65 std::ostringstream ostr;
66 if (m_use_memory_pool) {
67 m_memory_pool.dumpStats(ostr);
68 m_memory_pool.dumpFreeMap(ostr);
69 }
70 ostr << "Allocator '" << m_allocator_name << "' nb_realloc=" << m_nb_reallocate
71 << " realloc_copy=" << m_reallocate_size << "\n";
72 m_block_wrapper.dumpStats(ostr, m_allocator_name);
73 if (tm)
74 tm->info() << ostr.str();
75 else
76 std::cout << ostr.str();
77 }
78
79 m_memory_pool.freeCachedMemory();
80}
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
84
85AllocatedMemoryInfo AcceleratorMemoryAllocatorBase::
86reallocate(MemoryAllocationArgs args, AllocatedMemoryInfo current_info, Int64 new_size)
87{
88 ++m_nb_reallocate;
89 Int64 current_size = current_info.size();
90 m_reallocate_size += current_size;
91 String array_name = args.arrayName();
92 const bool do_print = (m_print_level >= 2);
93 if (do_print) {
94 std::cout << "Reallocate allocator=" << m_allocator_name
95 << " current_size=" << current_size
96 << " current_capacity=" << current_info.capacity()
97 << " new_capacity=" << new_size
98 << " ptr=" << current_info.baseAddress();
99 if (array_name.null() && m_print_level >= 3) {
100 std::cout << " stack=" << platform::getStackTrace();
101 }
102 else {
103 std::cout << " name=" << array_name;
104 if (m_print_level >= 4)
105 std::cout << " stack=" << platform::getStackTrace();
106 }
107 std::cout << "\n";
108 }
109 if (m_use_memory_pool)
110 _removeHint(current_info.baseAddress(), current_size, args);
111 AllocatedMemoryInfo a = allocate(args, new_size);
112 // TODO: supprimer les Hint après le deallocate car la zone mémoire peut être réutilisée.
113 m_direct_sub_allocator->doMemoryCopy(a.baseAddress(), current_info.baseAddress(), current_size);
114 deallocate(args, current_info);
115 return a;
116}
117
118//! Initialisation pour la mémoire UVM
119void AcceleratorMemoryAllocatorBase::
120_doInitializeUVM(bool default_use_memory_pool)
121{
122 bool do_page_allocate = true;
123 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_CUDA_UM_PAGE_ALLOC", true))
124 do_page_allocate = (v.value() != 0);
125 Int64 page_size = platform::getPageSize();
126 m_block_wrapper.initialize(page_size, do_page_allocate);
127
128 bool use_memory_pool = default_use_memory_pool;
129 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ACCELERATOR_MEMORY_POOL", true))
130 use_memory_pool = (v.value() & static_cast<int>(MemoryPoolFlags::UVM)) != 0;
131 _setUseMemoryPool(use_memory_pool);
132}
133
134//! Initialisation pour la mémoire HostPinned
135void AcceleratorMemoryAllocatorBase::
136_doInitializeHostPinned(bool default_use_memory_pool)
137{
138 bool use_memory_pool = default_use_memory_pool;
139 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ACCELERATOR_MEMORY_POOL", true))
140 use_memory_pool = (v.value() & static_cast<int>(MemoryPoolFlags::HostPinned)) != 0;
141 _setUseMemoryPool(use_memory_pool);
142 m_block_wrapper.initialize(128, use_memory_pool);
143}
144
145//! Initialisation pour la mémoire Device
146void AcceleratorMemoryAllocatorBase::
147_doInitializeDevice(bool default_use_memory_pool)
148{
149 bool use_memory_pool = default_use_memory_pool;
150 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ACCELERATOR_MEMORY_POOL", true))
151 use_memory_pool = (v.value() & static_cast<int>(MemoryPoolFlags::Device)) != 0;
152 _setUseMemoryPool(use_memory_pool);
153 m_block_wrapper.initialize(128, use_memory_pool);
154}
155
156// IMPORTANT: doit être appelé avant toute allocation et ne plus être modifié ensuite.
157void AcceleratorMemoryAllocatorBase::
158_setUseMemoryPool(bool is_used)
159{
160 IMemoryPoolAllocator* mem_pool = &m_memory_pool;
161 IMemoryPoolAllocator* direct = m_direct_sub_allocator.get();
162 m_sub_allocator = (is_used) ? mem_pool : direct;
163 m_use_memory_pool = is_used;
164 if (is_used) {
165 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_ACCELERATOR_MEMORY_POOL_MAX_BLOCK_SIZE", true)) {
166 if (v.value() < 0)
167 ARCCORE_FATAL("Invalid value '{0}' for memory pool max block size");
168 size_t block_size = static_cast<size_t>(v.value());
169 m_memory_pool.setMaxCachedBlockSize(block_size);
170 }
171 }
172}
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
176
177} // namespace Arcane::Accelerator
178
179 /*---------------------------------------------------------------------------*/
180 /*---------------------------------------------------------------------------*/
Espace de nom pour l'utilisation des accélérateurs.