Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
ConcurrencyUtils.h
Aller à la documentation de ce fichier.
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/* ConcurrencyUtils.h (C) 2000-2024 */
9/* */
10/* Classes gérant la concurrence (tâches, boucles parallèles, ...) */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCANE_UTILS_CONCURRENCYUTILS_H
13#define ARCANE_UTILS_CONCURRENCYUTILS_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16
18#include "arcane/utils/RangeFunctor.h"
19#include "arcane/utils/FatalErrorException.h"
20#include "arcane/utils/ForLoopTraceInfo.h"
21#include "arcane/utils/ParallelLoopOptions.h"
22
23#include <optional>
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
28namespace Arcane
29{
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33/*
34 * TODO:
35 * - Vérifier les fuites memoires
36 * - BIEN INDIQUER QU'IL NE FAUT PLUS UTILISER UNE TACHE APRES LE WAIT!!!
37 * - Regarder mecanisme pour les exceptions.
38 * - Surcharger les For et Foreach sans specifier le block_size
39 */
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43/*!
44 * \brief Contexte d'éxecution d'une tâche.
45 * \ingroup Concurrency
46 */
47class ARCANE_UTILS_EXPORT TaskContext
48{
49 public:
50 explicit TaskContext(ITask* atask) : m_task(atask) {}
51 public:
52 //! Tâche courante.
53 ITask* task() const { return m_task; }
54 private:
55 ITask* m_task;
56};
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60/*!
61 * \internal
62 * \brief Interface d'un fonctor pour une tâche.
63 * \ingroup Concurrency
64 */
65class ARCANE_UTILS_EXPORT ITaskFunctor
66{
67 public:
68 virtual ~ITaskFunctor() = default;
69 protected:
70 ITaskFunctor(const ITaskFunctor&) = default;
71 ITaskFunctor() = default;
72 public:
73 //! Exécute la méthode associé
74 virtual void executeFunctor(const TaskContext& tc) =0;
75 virtual ITaskFunctor* clone(void* buffer,Integer size) =0;
76};
77
78/*---------------------------------------------------------------------------*/
79/*---------------------------------------------------------------------------*/
80/*!
81 * \internal
82 * \brief Fonctor sans argument pour une tâche.
83 * \ingroup Concurrency
84 */
85template<typename InstanceType>
87: public ITaskFunctor
88{
89 public:
90 typedef void (InstanceType::*FunctorType)();
91 public:
92 TaskFunctor(InstanceType* instance,FunctorType func)
93 : m_instance(instance), m_function(func)
94 {
95 }
96 TaskFunctor(const TaskFunctor& rhs) = default;
97 TaskFunctor& operator=(const TaskFunctor& rhs) = delete;
98 public:
99 //! Exécute la méthode associé
100 void executeFunctor(const TaskContext& /*tc*/) override
101 {
102 (m_instance->*m_function)();
103 }
104 ITaskFunctor* clone(void* buffer,Integer size) override
105 {
106 if (sizeof(*this)>(size_t)size)
107 ARCANE_FATAL("INTERNAL: task functor buffer is too small");
108 return new (buffer) TaskFunctor<InstanceType>(*this);
109 }
110 private:
111 InstanceType* m_instance;
112 FunctorType m_function;
113};
114
115/*---------------------------------------------------------------------------*/
116/*---------------------------------------------------------------------------*/
117/*!
118 * \internal
119 * \brief Fonctor pour une tâche prenant un TaskContext en argument.
120 * \ingroup Concurrency
121 */
122template<typename InstanceType>
124: public ITaskFunctor
125{
126 public:
127 typedef void (InstanceType::*FunctorType)(const TaskContext& tc);
128 public:
129 TaskFunctorWithContext(InstanceType* instance,FunctorType func)
130 : ITaskFunctor(), m_instance(instance), m_function(func)
131 {
132 }
133 public:
134 //! Exécute la méthode associé
135 void executeFunctor(const TaskContext& tc) override
136 {
137 (m_instance->*m_function)(tc);
138 }
139 ITaskFunctor* clone(void* buffer,Integer size) override
140 {
141 if (sizeof(*this)>(size_t)size)
142 ARCANE_FATAL("INTERNAL: task functor buffer is too small");
143 return new (buffer) TaskFunctorWithContext<InstanceType>(*this);
144 }
145 private:
146 InstanceType* m_instance;
147 FunctorType m_function;
148};
149
150/*---------------------------------------------------------------------------*/
151/*---------------------------------------------------------------------------*/
152/*!
153 * \ingroup Concurrency
154 * \brief Interface d'une tâche concourante.
155 *
156 * Les tâches sont créées via TaskFactory.
157 */
158class ARCANE_UTILS_EXPORT ITask
159{
160 friend class TaskFactory;
161
162 public:
163
164 virtual ~ITask(){}
165
166 public:
167 /*!
168 * \brief Lance la tâche et bloque jusqu'à ce qu'elle se termine.
169 *
170 * Après appel à cette fonction, la tâche est détruite et ne doit
171 * plus être utilisée.
172 */
173 virtual void launchAndWait() =0;
174 /*!
175 * \brief Lance les tâches filles \a tasks et bloque
176 * jusqu'à ce qu'elles se terminent.
177 */
178 virtual void launchAndWait(ConstArrayView<ITask*> tasks) =0;
179
180 protected:
181
182 virtual ITask* _createChildTask(ITaskFunctor* functor) =0;
183};
184
185/*---------------------------------------------------------------------------*/
186/*---------------------------------------------------------------------------*/
187/*!
188 * \internal
189 * \brief Implémentation d'une fabrique de tâches.
190 *
191 * \ingroup Concurrency
192 *
193 * Cette classe est interne à Arcane. Pour gérer les tâches, il
194 * faut utiliser la classe TaskFactory.
195 */
196class ARCANE_UTILS_EXPORT ITaskImplementation
197{
198 public:
199 virtual ~ITaskImplementation(){}
200 public:
201 /*!
202 * \internal.
203 * Initialise l'implémentation avec au maximum \a nb_thread.
204 * Si \a nb_thread vaut 0, l'implémentation peut choisir
205 * le nombre de thread automatiquement.
206 * Cette méthode est interne à Arcane et ne doit être appelée
207 * que lors de l'initialisation de l'exécution.
208 */
209 virtual void initialize(Int32 nb_thread) =0;
210 /*!
211 * \internal.
212 * Termine l'utilisation de l'implémentation.
213 * Cette méthode doit être appelée en fin de calcul uniquement.
214 */
215 virtual void terminate() =0;
216 /*!
217 * \brief Créé une tâche racine.
218 * L'implémentation doit recopier la valeur de \a f qui est soit
219 * un TaskFunctor, soit un TaskFunctorWithContext.
220 */
222
223 //! Exécute le fonctor \a f en concurrence.
224 virtual void executeParallelFor(Integer begin,Integer size,const ParallelLoopOptions& options,IRangeFunctor* f) =0;
225
226 //! Exécute le fonctor \a f en concurrence.
227 virtual void executeParallelFor(Integer begin,Integer size,Integer block_size,IRangeFunctor* f) =0;
228
229 //! Exécute le fonctor \a f en concurrence.
230 virtual void executeParallelFor(Integer begin,Integer size,IRangeFunctor* f) =0;
231
232 //! Exécute la boucle \a loop_info en concurrence.
233 virtual void executeParallelFor(const ParallelFor1DLoopInfo& loop_info) =0;
234
235 //! Exécute une boucle 1D en concurrence
236 virtual void executeParallelFor(const ComplexForLoopRanges<1>& loop_ranges,
237 const ParallelLoopOptions& options,
238 IMDRangeFunctor<1>* functor) =0;
239 //! Exécute une boucle 2D en concurrence
240 virtual void executeParallelFor(const ComplexForLoopRanges<2>& loop_ranges,
241 const ParallelLoopOptions& options,
242 IMDRangeFunctor<2>* functor) =0;
243 //! Exécute une boucle 3D en concurrence
244 virtual void executeParallelFor(const ComplexForLoopRanges<3>& loop_ranges,
245 const ParallelLoopOptions& options,
246 IMDRangeFunctor<3>* functor) =0;
247 //! Exécute une boucle 4D en concurrence
248 virtual void executeParallelFor(const ComplexForLoopRanges<4>& loop_ranges,
249 const ParallelLoopOptions& options,
250 IMDRangeFunctor<4>* functor) =0;
251
252 //! Indique si l'implémentation est active.
253 virtual bool isActive() const =0;
254
255 //! Nombre de threads utilisés au maximum pour gérer les tâches.
256 virtual Int32 nbAllowedThread() const =0;
257
258 //! Implémentation de TaskFactory::currentTaskThreadIndex()
259 virtual Int32 currentTaskThreadIndex() const =0;
260
261 //! Implémentation de TaskFactory::currentTaskIndex()
262 virtual Int32 currentTaskIndex() const =0;
263
264 //! Affiche les informations sur le runtime utilisé
265 virtual void printInfos(std::ostream& o) const =0;
266};
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270/*!
271 * \brief Fabrique pour les tâches.
272 * \ingroup Concurrency
273 */
274class ARCANE_UTILS_EXPORT TaskFactory
275{
276 private:
277 TaskFactory();
278 public:
279 public:
280
281 /*!
282 * \brief Créé une tâche.
283 * Lors de l'exécution, la tâche appellera la méthode \a function via
284 * l'instance \a instance.
285 */
286 template<typename InstanceType> static ITask*
287 createTask(InstanceType* instance,void (InstanceType::*function)(const TaskContext& tc))
288 {
289 TaskFunctorWithContext<InstanceType> functor(instance,function);
290 return m_impl->createRootTask(&functor);
291 }
292
293 /*!
294 * \brief Créé une tâche.
295 * Lors de l'exécution, la tâche appellera la méthode \a function via
296 * l'instance \a instance.
297 */
298 template<typename InstanceType> static ITask*
299 createTask(InstanceType* instance,void (InstanceType::*function)())
300 {
301 TaskFunctor<InstanceType> functor(instance,function);
302 return m_impl->createRootTask(&functor);
303 }
304
305 /*!
306 * \brief Créé une tâche fille.
307 *
308 * Lors de l'exécution, la tâche appellera la méthode \a function via
309 * l'instance \a instance.
310 */
311 template<typename InstanceType> static ITask*
312 createChildTask(ITask* parent_task,InstanceType* instance,void (InstanceType::*function)(const TaskContext& tc))
313 {
314 ARCANE_CHECK_POINTER(parent_task);
315 TaskFunctorWithContext<InstanceType> functor(instance,function);
316 return parent_task->_createChildTask(&functor);
317 }
318
319 /*!
320 * \brief Créé une tâche fille.
321 *
322 * Lors de l'exécution, la tâche appellera la méthode \a function via
323 * l'instance \a instance.
324 */
325 template<typename InstanceType> static ITask*
326 createChildTask(ITask* parent_task,InstanceType* instance,void (InstanceType::*function)())
327 {
328 ARCANE_CHECK_POINTER(parent_task);
329 TaskFunctor<InstanceType> functor(instance,function);
330 return parent_task->_createChildTask(&functor);
331 }
332
333 //! Exécute le fonctor \a f en concurrence.
334 static void executeParallelFor(Integer begin,Integer size,const ParallelLoopOptions& options,IRangeFunctor* f)
335 {
336 m_impl->executeParallelFor(begin,size,options,f);
337 }
338
339 //! Exécute le fonctor \a f en concurrence.
340 static void executeParallelFor(Integer begin,Integer size,Integer block_size,IRangeFunctor* f)
341 {
342 m_impl->executeParallelFor(begin,size,block_size,f);
343 }
344
345 //! Exécute le fonctor \a f en concurrence.
346 static void executeParallelFor(Integer begin,Integer size,IRangeFunctor* f)
347 {
348 m_impl->executeParallelFor(begin,size,f);
349 }
350
351 //! Exécute la boucle \a loop_info en concurrence.
352 static void executeParallelFor(const ParallelFor1DLoopInfo& loop_info)
353 {
354 m_impl->executeParallelFor(loop_info);
355 }
356
357 //! Exécute une boucle simple
358 static void executeParallelFor(const ComplexForLoopRanges<1>& loop_ranges,
359 const ParallelLoopOptions& options,
360 IMDRangeFunctor<1>* functor)
361 {
362 m_impl->executeParallelFor(loop_ranges,options,functor);
363 }
364
365 //! Exécute une boucle 2D
366 static void executeParallelFor(const ComplexForLoopRanges<2>& loop_ranges,
367 const ParallelLoopOptions& options,
368 IMDRangeFunctor<2>* functor)
369 {
370 m_impl->executeParallelFor(loop_ranges,options,functor);
371 }
372
373 //! Exécute une boucle 3D
374 static void executeParallelFor(const ComplexForLoopRanges<3>& loop_ranges,
375 const ParallelLoopOptions& options,
376 IMDRangeFunctor<3>* functor)
377 {
378 m_impl->executeParallelFor(loop_ranges,options,functor);
379 }
380
381 //! Exécute une boucle 4D
382 static void executeParallelFor(const ComplexForLoopRanges<4>& loop_ranges,
383 const ParallelLoopOptions& options,
384 IMDRangeFunctor<4>* functor)
385 {
386 m_impl->executeParallelFor(loop_ranges,options,functor);
387 }
388
389 //! Nombre de threads utilisés au maximum pour gérer les tâches.
390 static Int32 nbAllowedThread()
391 {
392 return m_impl->nbAllowedThread();
393 }
394
395 /*!
396 * \brief Indice (entre 0 et nbAllowedThread()-1) du thread exécutant la tâche actuelle.
397 *
398 * Pour des raisons de performance, il est préférable d'appeler cette méthode
399 * le moins possible. L'idéal est de ne le faire qu'au début de l'exécution de la tâche
400 * et ensuite d'utiliser la valeur retournée.
401 */
403 {
404 return m_impl->currentTaskThreadIndex();
405 }
406
407 /*!
408 * \brief Indice (entre 0 et nbAllowedThread()-1) de la tâche actuelle.
409 *
410 * Cet indice est le même que currentTaskThreadIndex() sauf dans le cas
411 * où on se trouve dans un executeParallelFor() avec un partitionnement
412 * déterministe (ParallelLoopOptions::Partitioner::Deterministic).
413 * Dans ce dernier cas, le numéro de la tâche est assigné de manière
414 * déterministe qui ne dépend que du nombre de threads alloués pour la
415 * tâche et de ParallelLoopOptions::grainSize().
416 *
417 * Si le thread courant n'exécute pas une tâche associé à cette implémentation,
418 * retourne (-1).
419 */
420 static Int32 currentTaskIndex()
421 {
422 return m_impl->currentTaskIndex();
423 }
424
425 public:
426
427 //! Positionne les valeurs par défaut d'exécution d'une boucle parallèle
429 {
430 m_default_loop_options = v;
431 }
432
433 //! Valeurs par défaut d'exécution d'une boucle parallèle
435 {
436 return m_default_loop_options;
437 }
438
439 public:
440
441 /*!
442 * \brief Indique si les tâches sont actives.
443 * Les tâches sont actives si une implémentation est disponible et si le nombre
444 * de threads demandé est strictement supérieur à 1.
445 */
446 static bool isActive()
447 {
448 return m_impl->isActive();
449 }
450
451 /*!
452 * \brief Affiche les informations sur l'implémentation.
453 *
454 * Les informations sont par exemple le numéro de version ou le nom
455 * de l'implémentation.
456 */
457 static void printInfos(std::ostream& o)
458 {
459 return m_impl->printInfos(o);
460 }
461
462 /*!
463 * \brief Observable appelé lors de la création d'un thread pour une tâche.
464 *
465 * \warning L'instance de l'observable est créée lors du premier appel
466 * à cette méthode. Elle n'est donc pas thread-safe. De même,
467 * la modification de l'observable (ajout/suppression d'observateur)
468 * n'est pas thread-safe.
469 */
470 static IObservable* createThreadObservable();
471
472 /*!
473 * \brief Observable appelé lors de la destruction d'un thread pour une tâche.
474 *
475 * \warning L'instance de l'observable est créée lors du premier appel
476 * à cette méthode. Elle n'est donc pas thread-safe. De même,
477 * la modification de l'observable (ajout/suppression d'observateur)
478 * n'est pas thread-safe.
479 */
480 static IObservable* destroyThreadObservable();
481
482 /*!
483 * \internal
484 * \brief Indique qu'on n'utilisera plus les threads.
485 * Cette méthode ne doit pas être appelée lorsque des tâches sont actives.
486 */
487 static void terminate();
488
489 public:
490
491 //! Positionne le niveau de verbosité (0 pour pas d'affichage qui est le défaut)
492 static void setVerboseLevel(Integer v) { m_verbose_level = v; }
493
494 //! Niveau de verbosité
495 static Integer verboseLevel() { return m_verbose_level; }
496
497 public:
498
499 //! \internal
500 static void _internalSetImplementation(ITaskImplementation* task_impl);
501
502 private:
503
504 static ITaskImplementation* m_impl;
505 static IObservable* m_created_thread_observable;
506 static IObservable* m_destroyed_thread_observable;
507 static Int32 m_verbose_level;
508 static ParallelLoopOptions m_default_loop_options;
509};
510
511/*---------------------------------------------------------------------------*/
512/*---------------------------------------------------------------------------*/
513/*!
514 * \brief Informations d'exécution d'une boucle.
515 *
516 * Cette classe permet de gérer les informations d'exécutions communes à toutes
517 * les boucles.
518 */
519class ARCANE_UTILS_EXPORT ForLoopRunInfo
520{
521 public:
522
524
525 public:
526
527 ForLoopRunInfo() = default;
528 explicit ForLoopRunInfo(const ParallelLoopOptions& options)
529 : m_options(options) {}
530 ForLoopRunInfo(const ParallelLoopOptions& options,const ForLoopTraceInfo& trace_info)
531 : m_options(options), m_trace_info(trace_info) {}
532 explicit ForLoopRunInfo(const ForLoopTraceInfo& trace_info)
533 : m_trace_info(trace_info) {}
534
535 public:
536
537 std::optional<ParallelLoopOptions> options() const { return m_options; }
538 ThatClass& addOptions(const ParallelLoopOptions& v) { m_options = v; return (*this); }
539 const ForLoopTraceInfo& traceInfo() const { return m_trace_info; }
540 ThatClass& addTraceInfo(const ForLoopTraceInfo& v) { m_trace_info = v; return (*this); }
541
542 /*!
543 * \brief Positionne le pointeur conservant les statistiques d'exécution.
544 *
545 * Ce pointeur \a v doit rester valide durant toute l'exécution de la boucle.
546 */
547 void setExecStat(ForLoopOneExecStat* v) { m_exec_stat = v; }
548
549 //! Pointeur contenant les statistiques d'exécution.
550 ForLoopOneExecStat* execStat() const { return m_exec_stat; }
551
552 protected:
553
554 std::optional<ParallelLoopOptions> m_options;
555 ForLoopTraceInfo m_trace_info;
556 ForLoopOneExecStat* m_exec_stat = nullptr;
557};
558
559/*---------------------------------------------------------------------------*/
560/*---------------------------------------------------------------------------*/
561/*!
562 * \brief Caractéristiques d'un boucle 1D multi-thread.
563 *
564 * Cette classe permet de spécifier les options d'une boucle à paralléliser
565 * en mode multi-thread.
566 */
567class ARCANE_UTILS_EXPORT ParallelFor1DLoopInfo
568{
569 public:
570
572
573 public:
574
575 ParallelFor1DLoopInfo(Int32 begin,Int32 size,IRangeFunctor* functor)
576 : m_begin(begin), m_size(size), m_functor(functor) {}
577 ParallelFor1DLoopInfo(Int32 begin,Int32 size,IRangeFunctor* functor,const ForLoopRunInfo& run_info)
578 : m_run_info(run_info), m_begin(begin), m_size(size), m_functor(functor) {}
579 ParallelFor1DLoopInfo(Int32 begin,Int32 size, Int32 block_size,IRangeFunctor* functor)
580 : m_begin(begin), m_size(size), m_functor(functor)
581 {
582 ParallelLoopOptions opts(TaskFactory::defaultParallelLoopOptions());
583 opts.setGrainSize(block_size);
584 m_run_info.addOptions(opts);
585 }
586
587 public:
588
589 Int32 beginIndex() const { return m_begin; }
590 Int32 size() const { return m_size; }
591 IRangeFunctor* functor() const { return m_functor; }
592 ForLoopRunInfo& runInfo() { return m_run_info; }
593 const ForLoopRunInfo& runInfo() const { return m_run_info; }
594
595 private:
596
597 ForLoopRunInfo m_run_info;
598 Int32 m_begin = 0;
599 Int32 m_size = 0;
600 IRangeFunctor* m_functor = nullptr;
601};
602
603/*---------------------------------------------------------------------------*/
604/*---------------------------------------------------------------------------*/
605/*!
606 * \brief Applique en concurrence la fonction lambda \a lambda_function
607 * sur l'intervalle d'itération donné par \a loop_ranges.
608 */
609template<int RankValue,typename LambdaType,typename... ReducerArgs> inline void
611 const ParallelLoopOptions& options,
612 const LambdaType& lambda_function,
613 const ReducerArgs&... reducer_args)
614{
615 // Modif Arcane 3.7.9 (septembre 2022)
616 // Effectue une copie pour privatiser au thread courant les valeurs de la lambda.
617 // Cela est nécessaire pour que objets comme les reducers soient bien pris
618 // en compte.
619 // TODO: regarder si on pourrait faire la copie uniquement une fois par thread
620 // si cette copie devient couteuse.
621 // NOTE: A partir de la version 3.12.15 (avril 2024), avec la nouvelle version
622 // des réducteurs (Reduce2), cette privatisation n'est plus utile. Une fois
623 // qu'on aura supprimer les anciennes classes gérant les réductions (Reduce),
624 // on pourra supprimer cette privatisation
625 auto xfunc = [&lambda_function,reducer_args...] (const ComplexForLoopRanges<RankValue>& sub_bounds)
626 {
627 using Type = typename std::remove_reference<LambdaType>::type;
628 Type private_lambda(lambda_function);
629 arcaneSequentialFor(sub_bounds,private_lambda,reducer_args...);
630 };
631 LambdaMDRangeFunctor<RankValue,decltype(xfunc)> ipf(xfunc);
632 TaskFactory::executeParallelFor(loop_ranges,options,&ipf);
633}
634
635/*---------------------------------------------------------------------------*/
636/*---------------------------------------------------------------------------*/
637/*!
638 * \brief Applique en concurrence la fonction lambda \a lambda_function
639 * sur l'intervalle d'itération donné par \a loop_ranges.
640 */
641template <int RankValue, typename LambdaType, typename... ReducerArgs> inline void
643 const ParallelLoopOptions& options,
644 const LambdaType& lambda_function,
645 const ReducerArgs&... reducer_args)
646{
647 ComplexForLoopRanges<RankValue> complex_loop_ranges{ loop_ranges };
648 arcaneParallelFor(complex_loop_ranges, options, lambda_function, reducer_args...);
649}
650
651/*---------------------------------------------------------------------------*/
652/*---------------------------------------------------------------------------*/
653/*!
654 * \brief Applique en concurrence la fonction lambda \a lambda_function
655 * sur l'intervalle d'itération donné par \a loop_ranges.
656 */
657template<int RankValue,typename LambdaType> inline void
659 const LambdaType& lambda_function)
660{
661 ParallelLoopOptions options;
662 arcaneParallelFor(loop_ranges,options,lambda_function);
663}
664
665/*---------------------------------------------------------------------------*/
666/*---------------------------------------------------------------------------*/
667/*!
668 * \brief Applique en concurrence la fonction lambda \a lambda_function
669 * sur l'intervalle d'itération donné par \a loop_ranges.
670 */
671template<int RankValue,typename LambdaType> inline void
673 const LambdaType& lambda_function)
674{
675 ParallelLoopOptions options;
676 ComplexForLoopRanges<RankValue> complex_loop_ranges{loop_ranges};
677 arcaneParallelFor(complex_loop_ranges,options,lambda_function);
678}
679
680/*---------------------------------------------------------------------------*/
681/*---------------------------------------------------------------------------*/
682
683} // End namespace Arcane
684
685/*---------------------------------------------------------------------------*/
686/*---------------------------------------------------------------------------*/
687
688#endif
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Déclarations des types utilisés dans Arcane.
Informations d'exécution d'une boucle.
ForLoopOneExecStat * execStat() const
Pointeur contenant les statistiques d'exécution.
void setExecStat(ForLoopOneExecStat *v)
Positionne le pointeur conservant les statistiques d'exécution.
Informations de trace pour une boucle 'for'.
Interface d'un fonctor sur un interval d'itération multi-dimensionnel de dimension RankValue.
Interface d'un observable.
Interface d'un fonctor sur un interval d'itération.
virtual void executeFunctor(const TaskContext &tc)=0
Exécute la méthode associé
virtual void executeParallelFor(Integer begin, Integer size, const ParallelLoopOptions &options, IRangeFunctor *f)=0
Exécute le fonctor f en concurrence.
virtual void executeParallelFor(Integer begin, Integer size, IRangeFunctor *f)=0
Exécute le fonctor f en concurrence.
virtual void executeParallelFor(const ParallelFor1DLoopInfo &loop_info)=0
Exécute la boucle loop_info en concurrence.
virtual Int32 nbAllowedThread() const =0
Nombre de threads utilisés au maximum pour gérer les tâches.
virtual void executeParallelFor(Integer begin, Integer size, Integer block_size, IRangeFunctor *f)=0
Exécute le fonctor f en concurrence.
virtual ITask * createRootTask(ITaskFunctor *f)=0
Créé une tâche racine. L'implémentation doit recopier la valeur de f qui est soit un TaskFunctor,...
virtual Int32 currentTaskIndex() const =0
Implémentation de TaskFactory::currentTaskIndex()
virtual void executeParallelFor(const ComplexForLoopRanges< 4 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 4 > *functor)=0
Exécute une boucle 4D en concurrence.
virtual bool isActive() const =0
Indique si l'implémentation est active.
virtual void executeParallelFor(const ComplexForLoopRanges< 1 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 1 > *functor)=0
Exécute une boucle 1D en concurrence.
virtual void executeParallelFor(const ComplexForLoopRanges< 2 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 2 > *functor)=0
Exécute une boucle 2D en concurrence.
virtual void printInfos(std::ostream &o) const =0
Affiche les informations sur le runtime utilisé
virtual Int32 currentTaskThreadIndex() const =0
Implémentation de TaskFactory::currentTaskThreadIndex()
virtual void executeParallelFor(const ComplexForLoopRanges< 3 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 3 > *functor)=0
Exécute une boucle 3D en concurrence.
Interface d'une tâche concourante.
virtual void launchAndWait()=0
Lance la tâche et bloque jusqu'à ce qu'elle se termine.
virtual void launchAndWait(ConstArrayView< ITask * > tasks)=0
Lance les tâches filles tasks et bloque jusqu'à ce qu'elles se terminent.
Fonctor sur un interval d'itération instancié via une lambda fonction.
Caractéristiques d'un boucle 1D multi-thread.
Options d'exécution d'une boucle parallèle en multi-thread.
void setGrainSize(Integer v)
Positionne la taille (approximative) d'un intervalle d'itération.
Interval d'itération simple.
Contexte d'éxecution d'une tâche.
ITask * task() const
Tâche courante.
Fabrique pour les tâches.
static Int32 currentTaskIndex()
Indice (entre 0 et nbAllowedThread()-1) de la tâche actuelle.
static void executeParallelFor(const ParallelFor1DLoopInfo &loop_info)
Exécute la boucle loop_info en concurrence.
static void setVerboseLevel(Integer v)
Positionne le niveau de verbosité (0 pour pas d'affichage qui est le défaut)
static Int32 nbAllowedThread()
Nombre de threads utilisés au maximum pour gérer les tâches.
static void executeParallelFor(Integer begin, Integer size, IRangeFunctor *f)
Exécute le fonctor f en concurrence.
static ITask * createTask(InstanceType *instance, void(InstanceType::*function)())
Créé une tâche. Lors de l'exécution, la tâche appellera la méthode function via l'instance instance.
static const ParallelLoopOptions & defaultParallelLoopOptions()
Valeurs par défaut d'exécution d'une boucle parallèle.
static void executeParallelFor(const ComplexForLoopRanges< 1 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 1 > *functor)
Exécute une boucle simple.
static Integer verboseLevel()
Niveau de verbosité
static void executeParallelFor(const ComplexForLoopRanges< 4 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 4 > *functor)
Exécute une boucle 4D.
static void executeParallelFor(const ComplexForLoopRanges< 2 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 2 > *functor)
Exécute une boucle 2D.
static void setDefaultParallelLoopOptions(const ParallelLoopOptions &v)
Positionne les valeurs par défaut d'exécution d'une boucle parallèle.
static void executeParallelFor(Integer begin, Integer size, const ParallelLoopOptions &options, IRangeFunctor *f)
Exécute le fonctor f en concurrence.
static void executeParallelFor(Integer begin, Integer size, Integer block_size, IRangeFunctor *f)
Exécute le fonctor f en concurrence.
static void executeParallelFor(const ComplexForLoopRanges< 3 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 3 > *functor)
Exécute une boucle 3D.
static ITask * createChildTask(ITask *parent_task, InstanceType *instance, void(InstanceType::*function)(const TaskContext &tc))
Créé une tâche fille.
static Int32 currentTaskThreadIndex()
Indice (entre 0 et nbAllowedThread()-1) du thread exécutant la tâche actuelle.
static ITask * createChildTask(ITask *parent_task, InstanceType *instance, void(InstanceType::*function)())
Créé une tâche fille.
static bool isActive()
Indique si les tâches sont actives. Les tâches sont actives si une implémentation est disponible et s...
static ITask * createTask(InstanceType *instance, void(InstanceType::*function)(const TaskContext &tc))
Créé une tâche. Lors de l'exécution, la tâche appellera la méthode function via l'instance instance.
static void printInfos(std::ostream &o)
Affiche les informations sur l'implémentation.
void executeFunctor(const TaskContext &tc) override
Exécute la méthode associé
void executeFunctor(const TaskContext &) override
Exécute la méthode associé
Vue constante d'un tableau de type T.
void arcaneParallelFor(Integer i0, Integer size, InstanceType *itype, void(InstanceType::*lambda_function)(Integer i0, Integer size))
Applique en concurrence la fonction lambda lambda_function sur l'intervalle d'itération [i0,...
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
void arcaneSequentialFor(LoopBoundType< 1, IndexType > bounds, const Lambda &func, ReducerArgs... reducer_args)
Applique le fonctor func sur une boucle 1D.