Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
MultiReduce.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/* MultiReduce.cc (C) 2000-2013 */
9/* */
10/* Multiple reduction management. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ArcanePrecomp.h"
15#include "arcane/utils/TraceAccessor.h"
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/TraceInfo.h"
18#include "arcane/utils/String.h"
19#include "arcane/utils/PlatformUtils.h"
20
21#include "arcane/core/IParallelMng.h"
22
23#include "arcane/parallel/IMultiReduce.h"
24
25#include <map>
26#include <algorithm>
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37class PostProcessingMng;
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
43class MultiReduce
44: public TraceAccessor
45, public IMultiReduce
46{
47 public:
48
49 MultiReduce(IParallelMng* pm);
50 ~MultiReduce();
51
52 public:
53
54 virtual void execute();
55 virtual bool isStrict() const { return m_is_strict; }
56 virtual void setStrict(bool is_strict) { m_is_strict = is_strict; }
57
58 public:
59
61 {
62 ReduceSumOfRealHelperMap::const_iterator i = m_sum_helpers.find(name);
64 if (i == m_sum_helpers.end()) {
65 v = new ReduceSumOfRealHelper(m_is_strict);
66 m_sum_helpers.insert(std::make_pair(name, v));
67 }
68 else
69 v = i->second;
70 return v;
71 }
72
73 private:
74
75 typedef std::map<String, ReduceSumOfRealHelper*> ReduceSumOfRealHelperMap;
76
77 IParallelMng* m_parallel_mng;
78 bool m_is_strict;
79 ReduceSumOfRealHelperMap m_sum_helpers;
80
81 private:
82
83 void _execStrict(ReduceSumOfRealHelper* v);
84};
85
86/*---------------------------------------------------------------------------*/
87/*---------------------------------------------------------------------------*/
88
89IMultiReduce* IMultiReduce::
90create(IParallelMng* pm)
91{
92 return new MultiReduce(pm);
93}
94
95/*---------------------------------------------------------------------------*/
96/*---------------------------------------------------------------------------*/
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101MultiReduce::
102MultiReduce(IParallelMng* pm)
103: TraceAccessor(pm->traceMng())
104, m_parallel_mng(pm)
105, m_is_strict(false)
106{
107 if (!platform::getEnvironmentVariable("ARCANE_STRICT_REDUCE").null())
108 m_is_strict = true;
109}
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
114MultiReduce::
115~MultiReduce()
116{
117 ReduceSumOfRealHelperMap::const_iterator i = m_sum_helpers.begin();
118 for (; i != m_sum_helpers.end(); ++i)
119 delete i->second;
120 m_sum_helpers.clear();
121}
122
123/*---------------------------------------------------------------------------*/
124/*---------------------------------------------------------------------------*/
125
127execute()
128{
129 if (m_is_strict) {
130 ReduceSumOfRealHelperMap::const_iterator i = m_sum_helpers.begin();
131 for (; i != m_sum_helpers.end(); ++i)
132 _execStrict(i->second);
133 return;
134 }
135
136 // If we do not want a strict reduction, we store in an
137 // array all the sums to be reduced and we perform
138 // a single reduction on this array.
139
140 Integer nb_val = arcaneCheckArraySize(m_sum_helpers.size());
141 RealUniqueArray values(nb_val);
142
143 // Copy the sums to be reduced into the array values
144 {
145 Integer index = 0;
146 ReduceSumOfRealHelperMap::const_iterator i = m_sum_helpers.begin();
147 for (; i != m_sum_helpers.end(); ++i) {
148 // In this non-strict case, a single value in the array.
149 values[index] = i->second->values()[0];
150 ++index;
151 }
152 }
153
154 // Perform the reduction
155 m_parallel_mng->reduce(Parallel::ReduceSum, values);
156
157 {
158 Integer index = 0;
159 ReduceSumOfRealHelperMap::const_iterator i = m_sum_helpers.begin();
160 for (; i != m_sum_helpers.end(); ++i) {
161 // In this non-strict case, a single value in the array.
162 i->second->setReducedValue(values[index]);
163 ++index;
164 }
165 }
166}
167
168/*---------------------------------------------------------------------------*/
169/*---------------------------------------------------------------------------*/
170
171void MultiReduce::
172_execStrict(ReduceSumOfRealHelper* v)
173{
174 // We want a strict reduction that always gives the same results.
175 // For this, a proc (the 0) retrieves all accumulated values.
176 // They are then sorted and accumulated and then sent back to everyone.
177 RealUniqueArray all_values;
178 m_parallel_mng->gatherVariable(v->values(), all_values, 0);
179 //info() << "NB_VAL=" << all_values.size();
180 std::sort(std::begin(all_values), std::end(all_values));
181 Real sum = 0.0;
182 for (Integer i = 0, n = all_values.size(); i < n; ++i)
183 sum += all_values[i];
184 // TODO: it is possible to perform a single broadcast once the reductions
185 // of all the v's are completed
186 m_parallel_mng->broadcast(RealArrayView(1, &sum), 0);
187 v->setReducedValue(sum);
188}
189
190/*---------------------------------------------------------------------------*/
191/*---------------------------------------------------------------------------*/
192
193} // namespace Arcane
194
195/*---------------------------------------------------------------------------*/
196/*---------------------------------------------------------------------------*/
Integer size() const
Number of elements in the vector.
Management of multiple reductions.
Interface of the parallelism manager for a subdomain.
virtual void gatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf, Int32 rank)=0
Performs an all-gather operation across all processors.
virtual bool isStrict() const
Indicates if strict mode is used.
virtual ReduceSumOfRealHelper * getSumOfReal(const String &name)
Returns the name manager name. If a name manager name does not exist, it is created....
virtual void setStrict(bool is_strict)
Sets the strict mode.
virtual void execute()
Executes the reductions.
Class managing a reduction of a sum of values.
RealConstArrayView values() const
List of accumulated values.
void setReducedValue(Real v)
Positions the reduced value.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
String getEnvironmentVariable(const String &name)
Environment variable named name.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Integer arcaneCheckArraySize(unsigned long long size)
Checks that size can be converted into an 'Integer' to serve as the size of an array....
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.
ArrayView< Real > RealArrayView
C equivalent of a 1D array of reals.
Definition UtilsTypes.h:459