Arcane  v3.14.10.0
Documentation utilisateur
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:
32 typedef TaskFunctor<SerialTask> TaskType;
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;
52 TaskContext task_context(this);
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 }
102 void executeParallelFor(const ParallelFor1DLoopInfo& loop_info) override
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
166void TaskFactory::
167_internalSetImplementation(ITaskImplementation* task_impl)
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
199void TaskFactory::
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
218/*!
219 * \file ConcurrencyUtils.h
220
221 \brief Classes, Types et macros pour gérer la concurrence.
222
223 Pour plus de renseignements, se reporter à la page \ref arcanedoc_parallel_concurrency
224*/
225
226/*---------------------------------------------------------------------------*/
227/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classes, Types et macros pour gérer la concurrence.
Interface d'un fonctor sur un interval d'itération multi-dimensionnel de dimension RankValue.
virtual void executeFunctor(const ComplexForLoopRanges< RankValue > &loop_range)=0
Exécute la méthode associée.
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.
virtual void executeFunctor(const TaskContext &tc)=0
Exécute la méthode associé
Interface d'une tâche concourante.
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.
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 IObservable * createThreadObservable()
Observable appelé lors de la création d'un thread pour une tâche.
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-