Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ConcurrencyUtils.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 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.cc (C) 2000-2021 */
9/* */
10/* Classes gérant la concurrence (tâches, boucles parallèles, ...) */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
15
16#include "arcane/utils/TraceInfo.h"
17#include "arcane/utils/Observable.h"
18
19/*---------------------------------------------------------------------------*/
20/*---------------------------------------------------------------------------*/
21
22namespace Arcane
23{
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
29: public ITask
30{
31 public:
33 public:
34 static const int FUNCTOR_CLASS_SIZE = sizeof(TaskType);
35 public:
37 : m_functor(f)
38 {
39 // \a f doit être une instance de TaskFunctor<SerialTask>.
40 // on recopie dans un buffer pré-dimensionné pour éviter
41 // d'avoir à faire une allocation sur le tas via le new
42 // classique. On utilise donc le new avec placement.
43
44 m_functor = f->clone(functor_buf,FUNCTOR_CLASS_SIZE);
45 }
46 public:
47 void launchAndWait() override
48 {
49 if (m_functor){
50 ITaskFunctor* tmp_f = m_functor;
51 m_functor = nullptr;
53 tmp_f->executeFunctor(task_context);
54 delete this;
55 }
56 }
58 {
59 for( Integer i=0,n=tasks.size(); i<n; ++i )
60 tasks[i]->launchAndWait();
61 }
62 ITask* _createChildTask(ITaskFunctor* functor) override
63 {
64 return new SerialTask(functor);
65 }
66 private:
67 ITaskFunctor* m_functor;
68 char functor_buf[FUNCTOR_CLASS_SIZE];
69};
70
71/*---------------------------------------------------------------------------*/
72/*---------------------------------------------------------------------------*/
73
76{
77 public:
78 static NullTaskImplementation singleton;
79 public:
80 void initialize([[maybe_unused]] Int32 nb_thread) override
81 {
82 }
83 void terminate() override
84 {
85 }
87 {
88 return new SerialTask(f);
89 }
90 void executeParallelFor(Integer begin,Integer size,[[maybe_unused]] Integer block_size,IRangeFunctor* f) override
91 {
92 f->executeFunctor(begin,size);
93 }
94 void executeParallelFor(Integer begin,Integer size,[[maybe_unused]] const ParallelLoopOptions& options,IRangeFunctor* f) override
95 {
96 f->executeFunctor(begin,size);
97 }
98 void executeParallelFor(Integer begin,Integer size,IRangeFunctor* f) override
99 {
100 f->executeFunctor(begin,size);
101 }
103 {
104 loop_info.functor()->executeFunctor(loop_info.beginIndex(),loop_info.size());
105 }
107 [[maybe_unused]] const ParallelLoopOptions& options,
108 IMDRangeFunctor<1>* functor) override
109 {
110 functor->executeFunctor(loop_ranges);
111 }
113 [[maybe_unused]] const ParallelLoopOptions& options,
114 IMDRangeFunctor<2>* functor) override
115 {
116 functor->executeFunctor(loop_ranges);
117 }
119 [[maybe_unused]] const ParallelLoopOptions& options,
120 IMDRangeFunctor<3>* functor) override
121 {
122 functor->executeFunctor(loop_ranges);
123 }
125 [[maybe_unused]] const ParallelLoopOptions& options,
126 IMDRangeFunctor<4>* functor) override
127 {
128 functor->executeFunctor(loop_ranges);
129 }
130 bool isActive() const override
131 {
132 return false;
133 }
134 Int32 nbAllowedThread() const override
135 {
136 return 1;
137 }
138 Int32 currentTaskThreadIndex() const override
139 {
140 return 0;
141 }
142 Int32 currentTaskIndex() const override
143 {
144 return 0;
145 }
146
147 void printInfos(std::ostream& o) const final
148 {
149 o << "NullTaskImplementation";
150 }
151};
152
153/*---------------------------------------------------------------------------*/
154/*---------------------------------------------------------------------------*/
155
156NullTaskImplementation NullTaskImplementation::singleton;
157ITaskImplementation* TaskFactory::m_impl = &NullTaskImplementation::singleton;
158IObservable* TaskFactory::m_created_thread_observable = 0;
159IObservable* TaskFactory::m_destroyed_thread_observable = 0;
160Int32 TaskFactory::m_verbose_level = 0;
161ParallelLoopOptions TaskFactory::m_default_loop_options;
162
163/*---------------------------------------------------------------------------*/
164/*---------------------------------------------------------------------------*/
165
168{
169 if (m_impl && m_impl!=&NullTaskImplementation::singleton)
170 ARCANE_FATAL("TaskFactory already has an implementation");
171 m_impl = task_impl;
172}
173
174/*---------------------------------------------------------------------------*/
175/*---------------------------------------------------------------------------*/
176
179{
180 if (!m_created_thread_observable)
181 m_created_thread_observable = new Observable();
182 return m_created_thread_observable;
183}
184
185/*---------------------------------------------------------------------------*/
186/*---------------------------------------------------------------------------*/
187
190{
191 if (!m_destroyed_thread_observable)
192 m_destroyed_thread_observable = new Observable();
193 return m_destroyed_thread_observable;
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
200terminate()
201{
202 // C'est celui qui a positionné l'implémentation qui gère sa destruction.
203 if (m_impl==&NullTaskImplementation::singleton)
204 return;
205 if (m_impl)
206 m_impl->terminate();
207 m_impl = &NullTaskImplementation::singleton;
208}
209
210/*---------------------------------------------------------------------------*/
211/*---------------------------------------------------------------------------*/
212
213} // End namespace Arcane
214
215/*---------------------------------------------------------------------------*/
216/*---------------------------------------------------------------------------*/
217
226/*---------------------------------------------------------------------------*/
227/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classes, Types et macros pour gérer la concurrence.
Interface d'un observable.
Interface d'un fonctor sur un interval d'itération.
virtual void executeFunctor(Integer begin, Integer size)=0
Exécute la méthode associée.
Interface d'un fonctor pour une tâche.
Implémentation d'une fabrique de tâches.
Interface d'une tâche concourante.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
void executeParallelFor(const ComplexForLoopRanges< 1 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 1 > *functor) override
Exécute une boucle 1D en concurrence.
void executeParallelFor(const ComplexForLoopRanges< 3 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 3 > *functor) override
Exécute une boucle 3D en concurrence.
void printInfos(std::ostream &o) const final
Affiche les informations sur le runtime utilisé
Int32 currentTaskIndex() const override
Implémentation de TaskFactory::currentTaskIndex()
void executeParallelFor(const ComplexForLoopRanges< 4 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 4 > *functor) override
Exécute une boucle 4D en concurrence.
Int32 nbAllowedThread() const override
Nombre de threads utilisés au maximum pour gérer les tâches.
void executeParallelFor(Integer begin, Integer size, IRangeFunctor *f) override
Exécute le fonctor f en concurrence.
void executeParallelFor(const ComplexForLoopRanges< 2 > &loop_ranges, const ParallelLoopOptions &options, IMDRangeFunctor< 2 > *functor) override
Exécute une boucle 2D en concurrence.
void executeParallelFor(const ParallelFor1DLoopInfo &loop_info) override
Exécute la boucle loop_info en concurrence.
ITask * createRootTask(ITaskFunctor *f) override
Créé une tâche racine. L'implémentation doit recopier la valeur de f qui est soit un TaskFunctor,...
bool isActive() const override
Indique si l'implémentation est active.
void executeParallelFor(Integer begin, Integer size, Integer block_size, IRangeFunctor *f) override
Exécute le fonctor f en concurrence.
Int32 currentTaskThreadIndex() const override
Implémentation de TaskFactory::currentTaskThreadIndex()
void executeParallelFor(Integer begin, Integer size, const ParallelLoopOptions &options, IRangeFunctor *f) override
Exécute le fonctor f en concurrence.
void initialize(Int32 nb_thread) override
Classe de base d'un observable.
Caractéristiques d'un boucle 1D multi-thread.
Options d'exécution d'une boucle parallèle en multi-thread.
void launchAndWait() override
Lance la tâche et bloque jusqu'à ce qu'elle se termine.
void launchAndWait(ConstArrayView< ITask * > tasks) override
Lance les tâches filles tasks et bloque jusqu'à ce qu'elles se terminent.
Contexte d'éxecution d'une tâche.
static IObservable * destroyThreadObservable()
Observable appelé lors de la destruction d'un thread pour une tâche.
static void terminate()
Indique qu'on n'utilisera plus les threads. Cette méthode ne doit pas être appelée lorsque des tâches...
static IObservable * createThreadObservable()
Observable appelé lors de la création d'un thread pour une tâche.
static void _internalSetImplementation(ITaskImplementation *task_impl)
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-