Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
RunQueueImpl.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/* RunQueueImpl.cc (C) 2000-2024 */
9/* */
10/* Gestion d'une file d'exécution sur accélérateur. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/accelerator/core/internal/RunQueueImpl.h"
15
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/MemoryUtils.h"
18
19#include "arcane/accelerator/core/internal/IRunnerRuntime.h"
20#include "arcane/accelerator/core/internal/IRunQueueStream.h"
21#include "arcane/accelerator/core/internal/RunCommandImpl.h"
22#include "arcane/accelerator/core/internal/RunnerImpl.h"
23#include "arcane/accelerator/core/internal/IRunQueueEventImpl.h"
24#include "arcane/accelerator/core/Runner.h"
25#include "arcane/accelerator/core/RunQueueBuildInfo.h"
26#include "arcane/accelerator/core/DeviceId.h"
27#include "arcane/accelerator/core/RunQueueEvent.h"
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
32namespace Arcane::Accelerator::impl
33{
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38RunQueueImpl::
39RunQueueImpl(RunnerImpl* runner_impl, Int32 id, const RunQueueBuildInfo& bi)
40: m_runner_impl(runner_impl)
41, m_execution_policy(runner_impl->executionPolicy())
42, m_runtime(runner_impl->runtime())
43, m_queue_stream(m_runtime->createStream(bi))
44, m_id(id)
45{
46}
47
48/*---------------------------------------------------------------------------*/
49/*---------------------------------------------------------------------------*/
50
51RunQueueImpl::
52~RunQueueImpl()
53{
54 while (!m_run_command_pool.empty()) {
55 RunCommand::_internalDestroyImpl(m_run_command_pool.top());
56 m_run_command_pool.pop();
57 }
58 delete m_queue_stream;
59}
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67void RunQueueImpl::
68_release()
69{
70 // S'il reste des commandes en cours d'exécution au moment de libérer
71 // la file d'exécution il faut attendre pour éviter des fuites mémoire car
72 // les commandes ne seront pas désallouées.
73 // TODO: Regarder s'il ne faudrait pas plutôt indiquer cela à l'utilisateur
74 // ou faire une erreur fatale.
75 if (!m_active_run_command_list.empty()) {
76 if (!_internalStream()->_barrierNoException()) {
77 _internalFreeRunningCommands();
78 }
79 else
80 std::cerr << "WARNING: Error in internal accelerator barrier\n";
81 }
82 if (_isInPool())
83 m_runner_impl->_internalPutRunQueueImplInPool(this);
84 else {
85 delete this;
86 }
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
91
92void RunQueueImpl::
93_setDefaultMemoryRessource()
94{
95 m_memory_ressource = eMemoryRessource::Host;
96 if (isAcceleratorPolicy(m_execution_policy))
97 m_memory_ressource = eMemoryRessource::UnifiedMemory;
98}
99
100/*---------------------------------------------------------------------------*/
101/*---------------------------------------------------------------------------*/
102
103MemoryAllocationOptions RunQueueImpl::
104allocationOptions() const
105{
106 MemoryAllocationOptions opt = MemoryUtils::getAllocationOptions(m_memory_ressource);
107 Int16 device_id = static_cast<Int16>(m_runner_impl->deviceId().asInt32());
108 opt.setDevice(device_id);
109 return opt;
110}
111
112/*---------------------------------------------------------------------------*/
113/*---------------------------------------------------------------------------*/
114
115bool RunQueueImpl::
116isAutoPrefetchCommand() const
117{
118 return m_runner_impl->isAutoPrefetchCommand();
119}
120
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
124void RunQueueImpl::
125copyMemory(const MemoryCopyArgs& args) const
126{
127 _internalStream()->copyMemory(args);
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133void RunQueueImpl::
134prefetchMemory(const MemoryPrefetchArgs& args) const
135{
136 _internalStream()->prefetchMemory(args);
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141
142void RunQueueImpl::
143recordEvent(RunQueueEvent& event)
144{
145 auto* p = event._internalEventImpl();
146 return p->recordQueue(_internalStream());
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
152void RunQueueImpl::
153waitEvent(RunQueueEvent& event)
154{
155 auto* p = event._internalEventImpl();
156 return p->waitForEvent(_internalStream());
157}
158
159/*---------------------------------------------------------------------------*/
160/*---------------------------------------------------------------------------*/
161
162RunQueueImpl* RunQueueImpl::
163create(RunnerImpl* r)
164{
165 return _reset(r->_internalCreateOrGetRunQueueImpl());
166}
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
171RunQueueImpl* RunQueueImpl::
172create(RunnerImpl* r, const RunQueueBuildInfo& bi)
173{
174 return _reset(r->_internalCreateOrGetRunQueueImpl(bi));
175}
176
177/*---------------------------------------------------------------------------*/
178/*---------------------------------------------------------------------------*/
179
180RunCommandImpl* RunQueueImpl::
181_internalCreateOrGetRunCommandImpl()
182{
183 auto& pool = m_run_command_pool;
184 RunCommandImpl* p = nullptr;
185
186 // TODO: rendre thread-safe
187 if (!pool.empty()) {
188 p = pool.top();
189 pool.pop();
190 }
191 else {
192 p = RunCommand::_internalCreateImpl(this);
193 }
194 m_active_run_command_list.add(p);
195 return p;
196}
197
198/*---------------------------------------------------------------------------*/
199/*---------------------------------------------------------------------------*/
200/*!
201 * \brief Libère les commandes en cours d'exécution.
202 *
203 * Cette méthode est en général appelée après une barrière ce qui garantit
204 * que les commandes asynchrones sont terminées.
205 */
206void RunQueueImpl::
207_internalFreeRunningCommands()
208{
209 for (RunCommandImpl* p : m_active_run_command_list) {
210 p->notifyEndExecuteKernel();
211 m_run_command_pool.push(p);
212 }
213 m_active_run_command_list.clear();
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218/*!
219 * \brief Bloque jusqu'à ce que toutes les commandes soient terminées.
220 */
221void RunQueueImpl::
222_internalBarrier()
223{
224 _internalStream()->barrier();
225 _internalFreeRunningCommands();
226}
227
228/*---------------------------------------------------------------------------*/
229/*---------------------------------------------------------------------------*/
230/*!
231 * \brief Réinitialise l'implémentation
232 *
233 * Cette méthode est appelée lorsqu'on va initialiser une RunQueue avec
234 * cette instance. Il faut dans ce cas réinitialiser les valeurs de l'instance
235 * qui dépendent de l'état actuel.
236 */
237RunQueueImpl* RunQueueImpl::
238_reset(RunQueueImpl* p)
239{
240 p->m_is_async = false;
241 p->_setDefaultMemoryRessource();
242 return p;
243}
244
245/*---------------------------------------------------------------------------*/
246/*---------------------------------------------------------------------------*/
247
248} // namespace Arcane::Accelerator::impl
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indique si exec_policy correspond à un accélérateur.