Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
RunCommandImpl.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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/* RunCommandImpl.cc (C) 2000-2024 */
9/* */
10/* Implémentation de la gestion d'une commande sur accélérateur. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/accelerator/core/internal/RunCommandImpl.h"
15#include "arcane/accelerator/core/internal/AcceleratorCoreGlobalInternal.h"
16
17#include "arcane/utils/ForLoopTraceInfo.h"
19#include "arcane/utils/PlatformUtils.h"
20
21#include "arcane/accelerator/core/Runner.h"
22#include "arcane/accelerator/core/internal/IRunQueueEventImpl.h"
23#include "arcane/accelerator/core/internal/IRunQueueStream.h"
24#include "arcane/accelerator/core/internal/IRunnerRuntime.h"
25#include "arcane/accelerator/core/internal/RunQueueImpl.h"
26#include "arcane/accelerator/core/internal/ReduceMemoryImpl.h"
27#include "arcane/accelerator/core/internal/RunnerImpl.h"
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32namespace Arcane::Accelerator::impl
33{
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38/*---------------------------------------------------------------------------*/
39/*---------------------------------------------------------------------------*/
40
41RunCommandImpl::
42RunCommandImpl(RunQueueImpl* queue)
43: m_queue(queue)
44, m_use_accelerator(impl::isAcceleratorPolicy(queue->runner()->executionPolicy()))
45{
46 _init();
47}
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52RunCommandImpl::
53~RunCommandImpl()
54{
55 _freePools();
56 delete m_start_event;
57 delete m_stop_event;
58}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
63void RunCommandImpl::
64_freePools()
65{
66 while (!m_reduce_memory_pool.empty()) {
67 delete m_reduce_memory_pool.top();
68 m_reduce_memory_pool.pop();
69 }
70}
71
72/*---------------------------------------------------------------------------*/
73/*---------------------------------------------------------------------------*/
74
75IRunQueueEventImpl* RunCommandImpl::
76_createEvent()
77{
78 if (m_use_sequential_timer_event)
79 return getSequentialRunQueueRuntime()->createEventImplWithTimer();
80 return runner()->_createEventWithTimer();
81}
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
85
86void RunCommandImpl::
87_init()
88{
89 // N'utilise les timers accélérateur que si le profiling est activé.
90 // On fait cela pour éviter d'appeler les évènements accélérateurs car on
91 // ne connait pas encore leur influence sur les performances. Si elle est
92 // négligeable alors on pourra l'activer par défaut.
93
94 // TODO: il faudrait éventuellement avoir une instance séquentielle et
95 // une associée à runner() pour gérer le cas ou ProfilingRegistry::hasProfiling()
96 // change en cours d'exécution.
97 if (m_use_accelerator && !ProfilingRegistry::hasProfiling())
98 m_use_sequential_timer_event = true;
99
100 m_start_event = _createEvent();
101 m_stop_event = _createEvent();
102}
103
104/*---------------------------------------------------------------------------*/
105/*---------------------------------------------------------------------------*/
106
107RunCommandImpl* RunCommandImpl::
108create(RunQueueImpl* r)
109{
110 return r->_internalCreateOrGetRunCommandImpl();
111}
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115/*!
116 * \brief Notification du début d'exécution de la commande.
117 */
118void RunCommandImpl::
119notifyBeginLaunchKernel()
120{
121 IRunQueueStream* stream = internalStream();
122 stream->notifyBeginLaunchKernel(*this);
123 // TODO: utiliser la bonne stream en séquentiel
124 m_start_event->recordQueue(stream);
125 m_has_been_launched = true;
126 if (ProfilingRegistry::hasProfiling()) {
127 m_begin_time = platform::getRealTimeNS();
128 m_loop_one_exec_stat_ptr = &m_loop_one_exec_stat;
129 m_loop_one_exec_stat.setBeginTime(m_begin_time);
130 }
131}
132
133/*---------------------------------------------------------------------------*/
134/*---------------------------------------------------------------------------*/
135/*!
136 * \brief Notification de la fin de lancement de la commande.
137 *
138 * La commande continue à s'exécuter en tâche de fond.
139 */
140void RunCommandImpl::
141notifyEndLaunchKernel()
142{
143 IRunQueueStream* stream = internalStream();
144 // TODO: utiliser la bonne stream en séquentiel
145 m_stop_event->recordQueue(stream);
146 stream->notifyEndLaunchKernel(*this);
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151/*!
152 * \brief Notification du lancement d'un kernel SYCL.
153 *
154 * \a sycl_event_ptr est de type sycl::event* et contient
155 * l'évènement associé à la commande qui est retourné lors
156 * des appels à sycl::queue::submit().
157 */
158void RunCommandImpl::
159notifyLaunchKernelSyclEvent(void* sycl_event_ptr)
160{
161 IRunQueueStream* stream = internalStream();
162 stream->_setSyclLastCommandEvent(sycl_event_ptr);
163 // Il faut enregistrer à nouveau la file associée à l'évènement
164 // car lors de l'appel à notifyBeginLaunchKernel() il n'y avait pas
165 // encore l'évènement associé à cette file.
166 m_start_event->recordQueue(stream);
167}
168
169/*---------------------------------------------------------------------------*/
170/*---------------------------------------------------------------------------*/
171/*!
172 * \brief Notification de la fin d'exécution du noyau.
173 *
174 * Après cet appel, on est sur que la commande a fini de s'exécuter et on
175 * peut la recycler. En asynchrone, cette méthode est appelée lors de la
176 * synchronisation d'une file.
177 */
178void RunCommandImpl::
179notifyEndExecuteKernel()
180{
181 // Ne fait rien si la commande n'a pas été lancée.
182 if (!m_has_been_launched)
183 return;
184
185 Int64 diff_time_ns = m_stop_event->elapsedTime(m_start_event);
186
187 runner()->addTime((double)diff_time_ns / 1.0e9);
188
189 ForLoopOneExecStat* exec_info = m_loop_one_exec_stat_ptr;
190 if (exec_info) {
191 exec_info->setEndTime(m_begin_time + diff_time_ns);
192 //std::cout << "END_EXEC exec_info=" << m_loop_run_info.traceInfo().traceInfo() << "\n";
193 ForLoopTraceInfo flti(traceInfo(), kernelName());
194 ProfilingRegistry::_threadLocalForLoopInstance()->merge(*exec_info, flti);
195 }
196
197 _reset();
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202
203void RunCommandImpl::
204_reset()
205{
206 m_kernel_name = String();
207 m_trace_info = TraceInfo();
208 m_nb_thread_per_block = 0;
209 m_parallel_loop_options = TaskFactory::defaultParallelLoopOptions();
210 m_begin_time = 0;
211 m_loop_one_exec_stat.reset();
212 m_loop_one_exec_stat_ptr = nullptr;
213 m_has_been_launched = false;
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219IReduceMemoryImpl* RunCommandImpl::
220getOrCreateReduceMemoryImpl()
221{
222 ReduceMemoryImpl* p = _getOrCreateReduceMemoryImpl();
223 if (p) {
224 m_active_reduce_memory_list.insert(p);
225 }
226 return p;
227}
228
229/*---------------------------------------------------------------------------*/
230/*---------------------------------------------------------------------------*/
231
232void RunCommandImpl::
233releaseReduceMemoryImpl(ReduceMemoryImpl* p)
234{
235 auto x = m_active_reduce_memory_list.find(p);
236 if (x == m_active_reduce_memory_list.end())
237 ARCANE_FATAL("ReduceMemoryImpl in not in active list");
238 m_active_reduce_memory_list.erase(x);
239 m_reduce_memory_pool.push(p);
240}
241
242/*---------------------------------------------------------------------------*/
243/*---------------------------------------------------------------------------*/
244
245IRunQueueStream* RunCommandImpl::
246internalStream() const
247{
248 return m_queue->_internalStream();
249}
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
254RunnerImpl* RunCommandImpl::
255runner() const
256{
257 return m_queue->runner();
258}
259
260/*---------------------------------------------------------------------------*/
261/*---------------------------------------------------------------------------*/
262
263ReduceMemoryImpl* RunCommandImpl::
264_getOrCreateReduceMemoryImpl()
265{
266 // Pas besoin d'allouer de la mémoire spécifique si on n'est pas
267 // sur un accélérateur
268 if (!m_use_accelerator)
269 return nullptr;
270
271 auto& pool = m_reduce_memory_pool;
272
273 if (!pool.empty()) {
274 ReduceMemoryImpl* p = pool.top();
275 pool.pop();
276 return p;
277 }
278 return new ReduceMemoryImpl(this);
279}
280
281/*---------------------------------------------------------------------------*/
282/*---------------------------------------------------------------------------*/
283
284} // namespace Arcane::Accelerator::impl
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classes, Types et macros pour gérer la concurrence.
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indique si exec_policy correspond à un accélérateur.