Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
GatherGroup.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/* GatherGroup.cc (C) 2000-2026 */
9/* */
10/* Class allowing the management of data groupings on the one or more */
11/* writing subdomains. */
12/*---------------------------------------------------------------------------*/
13/*---------------------------------------------------------------------------*/
14
15#include "arcane/core/internal/GatherGroup.h"
16
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/Array2.h"
19
20#include "arcane/core/IParallelMng.h"
21#include "arcane/core/internal/IParallelMngInternal.h"
22
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26namespace Arcane
27{
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
33GatherGroup(GatherGroupInfo* gather_group_info)
34: m_gather_group_info(ARCANE_CHECK_POINTER(gather_group_info))
35{
36 ARCANE_FATAL_IF(!gather_group_info->isComputed(), "GatherGroupInfo is not computed");
37}
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
43GatherGroup() = default;
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48GatherGroup::
49~GatherGroup() = default;
50
51/*---------------------------------------------------------------------------*/
52/*---------------------------------------------------------------------------*/
53
56{
57 ARCANE_CHECK_POINTER(m_gather_group_info);
58 IParallelMng* pm = m_gather_group_info->m_parallel_mng;
59 // True if Thread or Hybrid or MPI without MPI-IO
60 // False if Sequential or MPI + MPI-IO.
61 return pm->commSize() != 1 && (pm->isThreadImplementation() || !m_gather_group_info->m_use_collective_io);
62}
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
69{
70 ARCANE_CHECK_POINTER(m_gather_group_info);
71 IParallelMng* pm = m_gather_group_info->m_parallel_mng;
72
73 // If sequential or MPI + MPI-IO.
74 if ((pm->commSize() == 1) || (!pm->isThreadImplementation() && m_gather_group_info->m_use_collective_io)) {
75 out.copy(in);
76 return;
77 }
78
79 const Int32 writer = m_gather_group_info->m_writer;
80
81 if (writer != pm->commRank()) {
82 pm->send(in.constSmallView(), writer);
83 return;
84 }
85
86 out.copy(in);
87
88 const Int32 nb_sender = m_gather_group_info->m_nb_sender_to_writer;
89
90 SmallSpan<const Int32> nb_elem_recved = m_gather_group_info->m_nb_elem_recv.smallSpan();
91
92 UniqueArray<Parallel::Request> requests(nb_sender - 1);
93
94 Int64 old_size = in.size();
95 for (Int32 i = 0; i < nb_sender - 1; ++i) {
96 const Int32 rank = i + writer + 1;
97 const Int64 sizeof_recved = nb_elem_recved[i] * sizeof_elem;
98
99 ArrayView<Byte> recv_elem = out.subSpan(old_size, sizeof_recved).smallView();
100 requests[i] = pm->recv(recv_elem, rank, false);
101
102 old_size += sizeof_recved;
103 }
104 pm->waitAllRequests(requests);
105}
106
107/*---------------------------------------------------------------------------*/
108/*---------------------------------------------------------------------------*/
109
111setGatherGroupInfo(GatherGroupInfo* gather_group_info)
112{
113 ARCANE_CHECK_POINTER(gather_group_info);
114 ARCANE_FATAL_IF(!gather_group_info->isComputed(), "GatherGroupInfo is not computed");
115 m_gather_group_info = gather_group_info;
116}
117
118/*---------------------------------------------------------------------------*/
119/*---------------------------------------------------------------------------*/
120
121/*---------------------------------------------------------------------------*/
122/*---------------------------------------------------------------------------*/
123
125GatherGroupInfo(IParallelMng* parallel_mng, bool use_collective_io)
126: m_parallel_mng(parallel_mng)
127, m_use_collective_io(use_collective_io)
128{}
129
130/*---------------------------------------------------------------------------*/
131/*---------------------------------------------------------------------------*/
132
133GatherGroupInfo::
134~GatherGroupInfo() = default;
135
136/*---------------------------------------------------------------------------*/
137/*---------------------------------------------------------------------------*/
138
140computeSize(Int32 nb_elem_in)
141{
142 if (m_is_computed)
143 return;
144 m_is_computed = true;
145
146 if (m_use_collective_io) {
147 m_writer = m_parallel_mng->_internalApi()->masterParallelIORank();
148 m_nb_sender_to_writer = m_parallel_mng->_internalApi()->nbSendersToMasterParallelIO();
149 }
150 else {
151 m_writer = m_parallel_mng->masterIORank();
152 m_nb_sender_to_writer = m_parallel_mng->commSize();
153 }
154
155 // If sequential or MPI + MPI-IO.
156 if ((m_parallel_mng->commSize() == 1) || (!m_parallel_mng->isThreadImplementation() && m_use_collective_io)) {
157 m_nb_elem_output = nb_elem_in;
158 m_nb_writer_global = m_parallel_mng->commSize();
159 return;
160 }
161
162 if (m_writer != m_parallel_mng->commRank()) {
163 m_parallel_mng->send({ 1, &nb_elem_in }, m_writer);
164 m_nb_elem_output = 0;
165 }
166 else {
167 m_nb_elem_recv.resizeNoInit(m_nb_sender_to_writer - 1);
168
169 {
170 UniqueArray<Parallel::Request> requests(m_nb_sender_to_writer - 1);
171 for (Int32 i = 0; i < m_nb_sender_to_writer - 1; ++i) {
172 const Int32 rank = i + m_writer + 1;
173 requests[i] = m_parallel_mng->recv({ 1, &m_nb_elem_recv[i] }, rank, false);
174 }
175 m_parallel_mng->waitAllRequests(requests);
176 }
177
178 m_nb_elem_output = nb_elem_in;
179 for (const Int32 size : m_nb_elem_recv) {
180 m_nb_elem_output += size;
181 }
182 }
183
184 m_nb_writer_global = m_parallel_mng->reduce(MessagePassing::ReduceSum, (m_writer == m_parallel_mng->commRank()));
185}
186
187/*---------------------------------------------------------------------------*/
188/*---------------------------------------------------------------------------*/
189
192{
193 return m_nb_elem_recv.smallSpan();
194}
195
196/*---------------------------------------------------------------------------*/
197/*---------------------------------------------------------------------------*/
198
199} // End namespace Arcane
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL_IF(const,...)
Macro throwing a FatalErrorException if cond is true.
#define ARCANE_CHECK_POINTER(ptr)
Macro returning the pointer ptr if it is not null or throwing an exception if it is null.
Modifiable view of an array of type T.
Class allowing the calculation and storage of grouping information.
void computeSize(Int32 nb_elem_in) override
Method allowing the calculation of grouping information.
GatherGroupInfo(IParallelMng *parallel_mng, bool use_collective_io)
Constructor.
SmallSpan< Int32 > nbElemRecvGatherToMasterIO() override
Method allowing knowledge of the number of elements that each third-party subdomain will send to us.
bool isComputed() override
Method allowing determination of whether the method computeSize() has already been called.
GatherGroup()
Constructor. For the object to be usable, it is necessary to call setGatherGroupInfo().
bool isNeedGather() override
Method allowing determination of whether the grouping needs to be performed or if the data can be wri...
void gatherToMasterIO(Int64 sizeof_elem, Span< const Byte > in, Span< Byte > out) override
Method allowing the grouping of data from multiple subdomains onto one or more subdomains.
void setGatherGroupInfo(GatherGroupInfo *gather_group_info)
Method allowing the definition of grouping information.
Interface of the parallelism manager for a subdomain.
virtual bool isThreadImplementation() const =0
Indicates if the implementation uses threads.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Blocks while waiting for the rvalues requests to complete.
View of an array of elements of type T.
Definition Span.h:805
__host__ __device__ void copy(const U &copy_array)
Copies the array copy_array into the instance.
Definition Span.h:477
constexpr ConstArrayView< value_type > constSmallView() const
Constant view of this view.
Definition Span.h:401
constexpr __host__ __device__ SizeType size() const noexcept
Returns the size of the array.
Definition Span.h:327
View of an array of elements of type T.
Definition Span.h:635
constexpr __host__ __device__ Span< T, DynExtent > subSpan(Int64 abegin, Int64 asize) const
Sub-view starting from element abegin and containing asize elements.
Definition Span.h:736
1D data vector with value semantics (STL style).
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
std::int64_t Int64
Signed integer type of 64 bits.
std::int32_t Int32
Signed integer type of 32 bits.