Arcane  v4.1.5.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
RunCommandLaunchInfo.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/* RunCommandLaunchInfo.cc (C) 2000-2026 */
9/* */
10/* Informations pour l'exécution d'une 'RunCommand'. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/common/accelerator/RunCommandLaunchInfo.h"
15
16#include "arccore/base/FatalErrorException.h"
17#include "arccore/base/CheckedConvert.h"
18#include "arccore/base/ConcurrencyBase.h"
19
20#include "arccore/common/accelerator/KernelLaunchArgs.h"
21#include "arccore/common/accelerator/RunCommand.h"
22#include "arccore/common/accelerator/NativeStream.h"
23#include "arccore/common/accelerator/internal/RunQueueImpl.h"
24#include "arccore/common/accelerator/internal/IRunnerRuntime.h"
25#include "arccore/common/accelerator/internal/RunCommandImpl.h"
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30namespace Arcane::Accelerator::Impl
31{
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36void RunCommandLaunchInfo::
37_init()
38{
39 m_queue_impl = m_command._internalQueueImpl();
40 m_exec_policy = m_queue_impl->executionPolicy();
41 // Le calcul des informations de kernel n'est utile que sur accélérateur
42 if (isAcceleratorPolicy(m_exec_policy)) {
43 _computeInitialKernelLaunchArgs();
44 m_command._allocateReduceMemory(m_kernel_launch_args.nbBlockPerGrid());
45 // Si des réductions sont présentes, on force la barrière à la fin du kernel
46 m_is_forced_need_barrier = m_command.m_p->hasActiveReduction();
47 }
48}
49
50/*---------------------------------------------------------------------------*/
51/*---------------------------------------------------------------------------*/
52
53RunCommandLaunchInfo::
54RunCommandLaunchInfo(RunCommand& command, Int64 total_loop_size)
55: m_command(command)
56, m_total_loop_size(total_loop_size)
57{
58 _init();
59}
60
61/*---------------------------------------------------------------------------*/
62/*---------------------------------------------------------------------------*/
63
64RunCommandLaunchInfo::
65RunCommandLaunchInfo(RunCommand& command, Int64 total_loop_size, bool is_cooperative)
66: m_command(command)
67, m_is_cooperative_launch(is_cooperative)
68, m_total_loop_size(total_loop_size)
69{
70 _init();
71}
72
73/*---------------------------------------------------------------------------*/
74/*---------------------------------------------------------------------------*/
75
76RunCommandLaunchInfo::
77~RunCommandLaunchInfo() noexcept(false)
78{
79 // Notifie de la fin de lancement du noyau. Normalement, cela est déjà fait
80 // sauf s'il y a eu une exception pendant le lancement du noyau de calcul.
81 _doEndKernelLaunch();
82}
83
84/*---------------------------------------------------------------------------*/
85/*---------------------------------------------------------------------------*/
86
87void RunCommandLaunchInfo::
88beginExecute()
89{
90 if (m_has_exec_begun)
91 ARCCORE_FATAL("beginExecute() has already been called");
92 m_has_exec_begun = true;
93 m_command._internalNotifyBeginLaunchKernel();
94 if (m_exec_policy == eExecutionPolicy::Thread)
95 _computeLoopRunInfo();
96}
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100/*!
101 * \brief Notifie de la fin de lancement de la commande.
102 *
103 * A noter que si la commande est asynchrone, son exécution peut continuer
104 * après l'appel à cette méthode.
105 */
106void RunCommandLaunchInfo::
107endExecute()
108{
109 if (!m_has_exec_begun)
110 ARCCORE_FATAL("beginExecute() has to be called before endExecute()");
111 _doEndKernelLaunch();
112}
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
116
117void RunCommandLaunchInfo::
118_doEndKernelLaunch()
119{
120 if (m_is_notify_end_kernel_done)
121 return;
122 m_is_notify_end_kernel_done = true;
123 m_command._internalNotifyEndLaunchKernel();
124
125 Impl::RunQueueImpl* q = m_queue_impl;
126 if (!q->isAsync() || m_is_need_barrier || m_is_forced_need_barrier)
127 q->_internalBarrier();
128}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133NativeStream RunCommandLaunchInfo::
134_internalNativeStream()
135{
136 return m_command._internalNativeStream();
137}
138
139/*---------------------------------------------------------------------------*/
140/*---------------------------------------------------------------------------*/
141/*!
142 * \brief Calcule la valeur initiale de block/thread/grille du noyau
143 * en fonction de \a full_size.
144 */
145void RunCommandLaunchInfo::
146_computeInitialKernelLaunchArgs()
147{
148 int threads_per_block = m_command.nbThreadPerBlock();
149 if (threads_per_block<=0)
150 threads_per_block = 256;
151 Int64 big_b = (m_total_loop_size + threads_per_block - 1) / threads_per_block;
152 int blocks_per_grid = CheckedConvert::toInt32(big_b);
153 m_kernel_launch_args = KernelLaunchArgs(blocks_per_grid, threads_per_block);
154 m_kernel_launch_args.setSharedMemorySize(m_command._sharedMemory());
155 m_kernel_launch_args.setIsCooperative(m_is_cooperative_launch);
156}
157
158/*---------------------------------------------------------------------------*/
159/*---------------------------------------------------------------------------*/
160
161ParallelLoopOptions RunCommandLaunchInfo::
162computeParallelLoopOptions() const
163{
164 ParallelLoopOptions opt = m_command.parallelLoopOptions();
165 const bool use_dynamic_compute = true;
166 // Calcule une taille de grain par défaut si cela n'est pas renseigné dans
167 // les options. Par défaut on fait en sorte de faire un nombre d'itérations
168 // égale à 2 fois le nombre de threads utilisés.
169 if (use_dynamic_compute && opt.grainSize() == 0) {
170 Int32 nb_thread = opt.maxThread();
171 if (nb_thread <= 0)
173 if (nb_thread <= 0)
174 nb_thread = 1;
175 Int32 grain_size = static_cast<Int32>((double)m_total_loop_size / (nb_thread * 2.0));
176 opt.setGrainSize(grain_size);
177 }
178 return opt;
179}
180
181/*---------------------------------------------------------------------------*/
182/*---------------------------------------------------------------------------*/
183/*!
184 * \brief Calcule la valeur de m_loop_run_info.
185 *
186 * Cela n'est utile qu'en mode multi-thread.
187 */
188void RunCommandLaunchInfo::
189_computeLoopRunInfo()
190{
191 ForLoopTraceInfo lti(m_command.traceInfo(), m_command.kernelName());
192 m_loop_run_info = ForLoopRunInfo(computeParallelLoopOptions(), lti);
193 m_loop_run_info.setExecStat(m_command._internalCommandExecStat());
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198/*!
199 * \brief Détermine la configuration du kernel.
200 *
201 * La configuration est dépendante du runtime sous-jacent. Pour CUDA et ROCM,
202 * il s'agit d'un nombre de blocs et de thread.
203 *
204 * Il est possible de calculer dynamiquement les valeurs optimales pour
205 * maximiser l'occupation.
206 */
207KernelLaunchArgs RunCommandLaunchInfo::
208_computeKernelLaunchArgs(const void* func) const
209{
210 Impl::IRunnerRuntime* r = m_queue_impl->_internalRuntime();
211
212 return r->computeKernalLaunchArgs(m_kernel_launch_args, func,
213 totalLoopSize());
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
218
219void RunCommandLaunchInfo::
220_addSyclEvent(void* sycl_event_ptr)
221{
222 m_command._internalNotifyBeginLaunchKernelSyclEvent(sycl_event_ptr);
223}
224
225/*---------------------------------------------------------------------------*/
226/*---------------------------------------------------------------------------*/
227
228bool RunCommandLaunchInfo::
229_isUseCooperativeLaunch() const
230{
231 // Indique si on utilise cudaLaunchCooperativeKernel()
232 return m_is_cooperative_launch;
233}
234/*---------------------------------------------------------------------------*/
235/*---------------------------------------------------------------------------*/
236
237bool RunCommandLaunchInfo::
238_isUseCudaLaunchKernel() const
239{
240 // Indique si on utilise cudaLaunchKernel() au lieu de kernel<<<...>>>.
241 return true;
242}
243
244/*---------------------------------------------------------------------------*/
245/*---------------------------------------------------------------------------*/
246
247void RunCommandLaunchInfo::
248_setIsNeedBarrier(bool v)
249{
250 m_is_need_barrier = v;
251}
252
253/*---------------------------------------------------------------------------*/
254/*---------------------------------------------------------------------------*/
255
256} // End namespace Arcane::Accelerator
257
258/*---------------------------------------------------------------------------*/
259/*---------------------------------------------------------------------------*/
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
static Int32 maxAllowedThread()
Nombre maximum de threads autorisés pour le multi-threading.
Informations d'exécution d'une boucle.
Informations de trace pour une boucle 'for'.
Options d'exécution d'une boucle parallèle en multi-thread.
Integer grainSize() const
Taille d'un intervalle d'itération.
Int32 maxThread() const
Nombre maximal de threads autorisés.
void setGrainSize(Integer v)
Positionne la taille (approximative) d'un intervalle d'itération.
@ Thread
Politique d'exécution multi-thread.
bool isAcceleratorPolicy(eExecutionPolicy exec_policy)
Indique si exec_policy correspond à un accélérateur.
std::int64_t Int64
Type entier signé sur 64 bits.
std::int32_t Int32
Type entier signé sur 32 bits.