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