Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ArcaneLoadBalanceModule.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/* ArcaneLoadBalanceModule.cc (C) 2000-2010 */
9/* */
10/* Load balancing module. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15
16#include "arcane/core/EntryPoint.h"
17#include "arcane/core/ISubDomain.h"
18#include "arcane/core/IParallelMng.h"
19#include "arcane/core/ModuleFactory.h"
20#include "arcane/core/IMeshPartitioner.h"
21#include "arcane/core/ServiceUtils.h"
22#include "arcane/core/CommonVariables.h"
23#include "arcane/core/ITimeStats.h"
24#include "arcane/core/ITimeLoopMng.h"
25#include "arcane/core/ITimeHistoryMng.h"
26#include "arcane/core/IMesh.h"
27#include "arcane/core/IMeshModifier.h"
28#include "arcane/core/ItemPrinter.h"
29#include "arcane/core/IItemFamily.h"
30
31#include "arcane/std/ArcaneLoadBalance_axl.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane
37{
38
39#define OLD_LOADBALANCE
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
47class ArcaneLoadBalanceModule
48: public ArcaneArcaneLoadBalanceObject
49{
50 public:
51
52 ArcaneLoadBalanceModule(const ModuleBuildInfo& mb);
53 ~ArcaneLoadBalanceModule();
54
55 public:
56
57 virtual VersionInfo versionInfo() const { return VersionInfo(1, 0, 0); }
58
59 public:
60
61 void checkLoadBalance();
62 void loadBalanceInit();
63
64 private:
65
66 VariableScalarReal m_elapsed_computation_time;
71#ifdef OLD_LOADBALANCE
72 Integer m_nb_weight;
73 UniqueArray<float> m_cells_weight;
74#endif // OLD_LOADBALANCE
75
76 private:
77
78 void _checkInit();
79 Real _computeImbalance();
80#ifdef OLD_LOADBALANCE
81 void _computeWeights(RealConstArrayView compute_times, Real max_compute_time);
82#endif // OLD_LOADBALANCE
83};
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88ARCANE_REGISTER_MODULE_ARCANELOADBALANCE(ArcaneLoadBalanceModule);
89
90/*---------------------------------------------------------------------------*/
91/*---------------------------------------------------------------------------*/
92
93ArcaneLoadBalanceModule::
94ArcaneLoadBalanceModule(const ModuleBuildInfo& mb)
96, m_elapsed_computation_time(VariableBuildInfo(this, "ArcaneLoadBalanceElapsedComputationTime",
97 IVariable::PNoDump | IVariable::PNoRestore))
98, m_computation_time(0.0)
99#ifdef OLD_LOADBALANCE
100, m_nb_weight(2)
101#endif // OLD_LOADBALANCE
102{
103}
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108ArcaneLoadBalanceModule::
109~ArcaneLoadBalanceModule()
110{
111}
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115
116void ArcaneLoadBalanceModule::
117loadBalanceInit()
118{
119 m_elapsed_computation_time = 0;
120 _checkInit();
121}
122
123/*---------------------------------------------------------------------------*/
124/*---------------------------------------------------------------------------*/
125
126void ArcaneLoadBalanceModule::
127_checkInit()
128{
129 if (options()->period() == 0 || !options()->active()) {
130 info() << "Load balance deactivated.";
131 return;
132 }
133
134 if (!subDomain()->parallelMng()->isParallel()) {
135 info() << "Load balance required but inactive during serial execution";
136 return;
137 }
138
139 info() << "Load balance active with maximum unbalance: "
140 << options()->maxImbalance();
141 // Indicates to the mesh that it can evolve
142 defaultMesh()->modifier()->setDynamic(true);
143}
144
145/*---------------------------------------------------------------------------*/
146/*---------------------------------------------------------------------------*/
147
150{
151 ISubDomain* sd = subDomain();
152 Integer global_iteration = sd->commonVariables().globalIteration();
153 int period = options()->period();
154 if (period == 0)
155 return;
156 if (global_iteration == 0)
157 return;
158 if ((global_iteration % period) != 0)
159 return;
160
161 Real imbalance = _computeImbalance();
162
163 if (!options()->active())
164 return;
165 if (imbalance < options()->maxImbalance())
166 return;
167 Real min_cpu_time = options()->minCpuTime();
168 if (min_cpu_time != 0 || m_computation_time < min_cpu_time)
169 return;
170
172 info() << "Program a mesh repartitioning";
173#ifdef OLD_LOADBALANCE
174 IMeshPartitioner* p = options()->partitioner();
175 _computeWeights(p->computationTimes(), p->maximumComputationTime());
176 p->setCellsWeight(m_cells_weight, m_nb_weight);
177#endif // OLD_LOADBALANCE
179}
180
181/*---------------------------------------------------------------------------*/
182/*---------------------------------------------------------------------------*/
183
184#ifdef OLD_LOADBALANCE
189_computeWeights(RealConstArrayView compute_times, Real max_compute_time)
190{
191 ISubDomain* sd = subDomain();
192 IMesh* mesh = this->mesh();
193 IParallelMng* pm = sd->parallelMng();
194 Int32 nb_sub_domain = pm->commSize();
195 CellGroup own_cells = mesh->ownCells();
196 IntegerUniqueArray global_nb_own_cell(nb_sub_domain);
197 Integer nb_own_cell = own_cells.size();
198 Integer nb_weight = m_nb_weight;
199
200 pm->allGather(IntegerConstArrayView(1, &nb_own_cell), global_nb_own_cell);
201 //Integer total_nb_cell = 0;
202
203 // compute_times[0] contains the global time (without tracking)
204 // compute_times[1] contains the tracking time
205 //Real max_compute_time = maximumComputationTime();
206 //RealConstArrayView compute_times = computationTimes();
207 bool has_compute_time = compute_times.size() != 0;
208 bool has_cell_time = compute_times.size() == 2;
209 if (math::isZero(max_compute_time))
210 max_compute_time = 1.0;
211 Real compute_times0 = 1.0;
212 Real compute_times1 = 0.0;
213 if (has_compute_time) {
214 compute_times0 = compute_times[0];
215 if (has_cell_time)
216 compute_times1 = compute_times[1];
217 }
218
219 bool dump_info = true;
220
221 Real time_ratio = compute_times0 / max_compute_time;
222 Real time_ratio2 = compute_times1 / max_compute_time;
223
224 if (dump_info) {
225 info() << " MAX_COMPUTE=" << max_compute_time;
226 info() << " COMPUTE 0=" << compute_times0;
227 info() << " COMPUTE 1=" << compute_times1;
228 info() << " TIME RATIO 0=" << time_ratio;
229 info() << " TIME RATIO 2=" << time_ratio2;
230 }
231 Real proportional_time = compute_times0 / (nb_own_cell + 1);
232
233 if (dump_info) {
234 info() << " PROPORTIONAL TIME=" << proportional_time;
235 }
236
237 Real max_weight = 0.0;
238 IItemFamily* cell_family = mesh->cellFamily();
239 m_cells_weight.resize(cell_family->maxLocalId() * nb_weight);
240 ENUMERATE_CELL (iitem, own_cells) {
241 const Cell& cell = *iitem;
242 Real v0 = proportional_time;
243 Real w = (v0);
244 if (dump_info && iitem.index() < 10) {
245 info() << "Weight " << ItemPrinter(cell)
246 << " v0=" << v0
247 << " w=" << w;
248 }
249 // For testing if we have a second weight, multiply it by i+1;
250 for (Integer i = 0; i < nb_weight; ++i) {
251 m_cells_weight[(nb_weight * iitem->localId()) + i] = (float)(w * ((Real)(i + 1)));
252 }
253 if (w > max_weight)
254 max_weight = w;
255 }
256
257 Real total_max_weight = pm->reduce(Parallel::ReduceMax, max_weight);
258 if (math::isZero(total_max_weight))
259 total_max_weight = 1.0;
260
261 if (dump_info) {
262 info() << " TOTAL MAX WEIGHT=" << total_max_weight;
263 }
264
265 ENUMERATE_CELL (iitem, own_cells) {
266 for (Integer i = 0; i < nb_weight; ++i) {
267 Integer idx = (nb_weight * iitem->localId()) + i;
268 m_cells_weight[idx] = (float)(m_cells_weight[idx] / total_max_weight);
269 }
270 }
271}
272#endif // OLD_LOADBALANCE
273
274/*---------------------------------------------------------------------------*/
275/*---------------------------------------------------------------------------*/
276
277Real ArcaneLoadBalanceModule::
278_computeImbalance()
279{
280 //TODO: make the method compatible with return-back
281 ITimeStats* time_stats = subDomain()->timeStats();
283
284 // Elapsed time since the start of execution
285 Real elapsed_computation_time = time_stats->elapsedTime(TP_Computation);
286 Real computation_time = elapsed_computation_time - m_elapsed_computation_time();
287
288 m_elapsed_computation_time = elapsed_computation_time;
289
290 if (options()->statistics()) {
291 // Optional:
292 // Retrieves the computation time of each subdomain to output the history.
293 // TODO: in this case, the standard reduce for min and max is unused -> delete it
294 Integer nb_sub_domain = pm->commSize();
295 RealUniqueArray compute_times(nb_sub_domain);
296 Real my_time = computation_time;
297 RealConstArrayView my_time_a(1, &my_time);
298 pm->allGather(my_time_a, compute_times);
300 thm->addValue("SubDomainComputeTime", compute_times);
301 }
302
303 Real reduce_times[2];
304 reduce_times[0] = computation_time;
305 reduce_times[1] = -computation_time;
306 // All replicas must have the same time information to start the partitioning
307 // (even if only one replica performs the partitioning in the end, the request
308 // operation must be collective)
310 Real min_computation_time = reduce_times[0];
311 Real max_computation_time = -reduce_times[1];
312 if (math::isZero(max_computation_time))
313 max_computation_time = 1.;
314 if (math::isZero(min_computation_time))
315 min_computation_time = 1.;
316 RealUniqueArray computation_times(1);
317 computation_times[0] = computation_time;
318
319 m_computation_time += max_computation_time;
320
321 Real ratio = computation_time / max_computation_time;
322 Real imbalance = (max_computation_time - min_computation_time) / min_computation_time;
323 info() << "Computing time used (" << pm->commRank() << ") :"
324 << " nb_owncell=" << ownCells().size()
325 << " current=" << computation_time
326 << " min=" << min_computation_time
327 << " max=" << max_computation_time
328 << " ratio=" << ratio
329 << " imbalance=" << imbalance
330 << " full-compute=" << m_computation_time;
331
332 IMeshPartitioner* p = options()->partitioner();
333 p->setMaximumComputationTime(max_computation_time);
334 p->setComputationTimes(computation_times);
335 p->setImbalance(imbalance);
336 p->setMaxImbalance(options()->maxImbalance());
337 return imbalance;
338}
339
340/*---------------------------------------------------------------------------*/
341/*---------------------------------------------------------------------------*/
342
343} // namespace Arcane
344
345/*---------------------------------------------------------------------------*/
346/*---------------------------------------------------------------------------*/
#define ENUMERATE_CELL(name, group)
Generic enumerator for a cell group.
ISubDomain * subDomain() const override
Sub-domain associated with the module.
IMesh * defaultMesh() const override
Default mesh for this module.
IParallelMng * parallelMng() const override
Message passing parallelism manager.
Generation de la classe de base du Module.
CaseOptionsArcaneLoadBalance * options() const
Options du jeu de données du module.
void _computeWeights(RealConstArrayView compute_times, Real max_compute_time)
Calculates the weight of each mesh cell and stores it in m_cells_weight.
Real m_computation_time
Computation time since the last balancing Note: this value must be synchronized.
virtual VersionInfo versionInfo() const
Module version.
Cell of a mesh.
Definition Item.h:1300
Int32 globalIteration() const
Current iteration number.
constexpr Integer size() const noexcept
Number of elements in the array.
Interface of an entity family.
Definition IItemFamily.h:83
virtual Int32 maxLocalId() const =0
virtual void setDynamic(bool v)=0
Sets the property indicating whether the mesh can evolve.
Interface of a mesh partitioner.
virtual ARCANE_DEPRECATED_116 void setCellsWeight(ArrayView< float > weights, Integer nb_weight)=0
Allows defining the weights of objects to be partitioned: ILoadBalanceMng must now be used.
virtual IMeshModifier * modifier()=0
Associated modifier interface.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Performs an all-gather operation across all processors. This is a collective operation....
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
Interface of the subdomain manager.
Definition ISubDomain.h:75
virtual const CommonVariables & commonVariables() const =0
Information on standard variables.
virtual ITimeStats * timeStats() const =0
Execution time statistics.
virtual IParallelMng * parallelMng()=0
Returns the parallelism manager.
virtual ITimeLoopMng * timeLoopMng()=0
Returns the time loop manager.
virtual ITimeHistoryMng * timeHistoryMng()=0
Returns the history manager.
virtual IParallelMng * allReplicaParallelMng() const =0
Returns the parallelism manager for all replicas.
Class managing a history of values.
virtual void addValue(const String &name, Real value, bool end_time=true, bool is_local=false)=0
Adds the value value to the history name.
virtual void registerActionMeshPartition(IMeshPartitionerBase *mesh_partitioner)=0
Schedules a mesh partitioning using the partition tool mesh_partitioner.
Interface managing execution time statistics.
Definition ITimeStats.h:44
virtual Real elapsedTime(eTimePhase phase)=0
Real elapsed time for phase phase.
Interface of a variable.
Definition IVariable.h:40
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
CellGroup ownCells() const
Returns the group containing all cells specific to this domain.
Information for building a module.
TraceMessage info() const
Flow for an information message.
1D data vector with value semantics (STL style).
Parameters necessary for building a variable.
Information about a version.
Definition VersionInfo.h:47
ItemGroupT< Cell > CellGroup
Group of cells.
Definition ItemTypes.h:184
VariableRefScalarT< Real > VariableScalarReal
Scalar variable of real type.
@ ReduceMin
Minimum of values.
@ ReduceMax
Maximum of values.
bool isZero(const BuiltInProxy< _Type > &a)
Tests if a value is exactly equal to zero.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Int32 Integer
Type representing an integer.
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
Definition UtilsTypes.h:349
double Real
Type representing a real number.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
Definition UtilsTypes.h:347
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
Definition UtilsTypes.h:486
ArrayView< Real > RealArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:459
std::int32_t Int32
Signed integer type of 32 bits.
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:488