Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
Int64AllToAll.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/* Int64AllToAll.cc (C) 2000-2026 */
9/* */
10/* Variable all-to-all of Int64, in rounds past what MPI counts. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/mesh/internal/Int64AllToAll.h"
15
16#include "arcane/utils/CheckedConvert.h"
17
18#include "arcane/core/IParallelMng.h"
19#include "arcane/core/IParallelNonBlockingCollective.h"
20
21#include <algorithm>
22#include <cstdint>
23
24/*---------------------------------------------------------------------------*/
25/*---------------------------------------------------------------------------*/
26
27namespace Arcane::mesh
28{
29
30/*---------------------------------------------------------------------------*/
31/*---------------------------------------------------------------------------*/
38_nbRound(Int64 g_max, Int32 nb_rank)
39{
40 const Int64 room = static_cast<Int64>(INT32_MAX) - nb_rank;
41 return std::max<Int64>(1, (g_max + room - 1) / room);
42}
43
44/*---------------------------------------------------------------------------*/
45/*---------------------------------------------------------------------------*/
46
49{
50 const Int32 nb_rank = pm->commSize();
51 recv_count.resize(nb_rank);
52 pm->allToAll(send_count, recv_count, 1);
53 Int64 total_send = 0;
54 Int64 total_recv = 0;
55 for (Int32 r = 0; r < nb_rank; ++r) {
56 total_send += send_count[r];
57 total_recv += recv_count[r];
58 }
59 return _nbRound(pm->reduce(Parallel::ReduceMax, std::max(total_send, total_recv)), nb_rank);
60}
61
62/*---------------------------------------------------------------------------*/
63/*---------------------------------------------------------------------------*/
64
67 ConstArrayView<Int64> recv_count, Int64 nb_round)
68{
69 m_pm = pm;
70 const Int32 nb_rank = pm->commSize();
71 m_recv_index.resize(nb_rank + 1);
72 m_recv_index[0] = 0;
73 for (Int32 r = 0; r < nb_rank; ++r)
74 m_recv_index[r + 1] = m_recv_index[r] + recv_count[r];
75 m_recv.resize(m_recv_index[nb_rank]);
76 UniqueArray<Int64> send_index(nb_rank + 1);
77 send_index[0] = 0;
78 for (Int32 r = 0; r < nb_rank; ++r)
79 send_index[r + 1] = send_index[r] + send_count[r];
80
81 m_send_count.resize(nb_rank);
82 m_send_index.resize(nb_rank);
83 m_recv_count.resize(nb_rank);
84 m_recv_index32.resize(nb_rank);
86 if (nb_round == 1) {
87 for (Int32 r = 0; r < nb_rank; ++r) {
88 m_send_count[r] = CheckedConvert::toInt32(send_count[r]);
89 m_send_index[r] = CheckedConvert::toInt32(send_index[r]);
90 m_recv_count[r] = CheckedConvert::toInt32(recv_count[r]);
91 m_recv_index32[r] = CheckedConvert::toInt32(m_recv_index[r]);
92 }
93 if (nbc) {
94 m_request = nbc->allToAllVariable(send, m_send_count, m_send_index, m_recv, m_recv_count, m_recv_index32);
95 m_is_pending = true;
96 }
97 else
98 pm->allToAllVariable(send, m_send_count, m_send_index, m_recv, m_recv_count, m_recv_index32);
99 return;
100 }
101
102 // Round k carries [count * k / nb_round, count * (k+1) / nb_round) of every
103 // message; both sides compute the same cut from the same count.
106 for (Int64 k = 0; k < nb_round; ++k) {
107 Int32 s = 0;
108 Int32 t = 0;
109 for (Int32 r = 0; r < nb_rank; ++r) {
110 const Int64 slo = send_count[r] * k / nb_round;
111 const Int64 shi = send_count[r] * (k + 1) / nb_round;
112 m_send_count[r] = CheckedConvert::toInt32(shi - slo);
113 m_send_index[r] = s;
114 s += m_send_count[r];
115 const Int64 rlo = recv_count[r] * k / nb_round;
116 const Int64 rhi = recv_count[r] * (k + 1) / nb_round;
117 m_recv_count[r] = CheckedConvert::toInt32(rhi - rlo);
118 m_recv_index32[r] = t;
119 t += m_recv_count[r];
120 }
121 sbuf.resize(s);
122 for (Int32 r = 0; r < nb_rank; ++r) {
123 const Int64 slo = send_index[r] + send_count[r] * k / nb_round;
124 for (Int32 z = 0; z < m_send_count[r]; ++z)
125 sbuf[m_send_index[r] + z] = send.data()[slo + z];
126 }
127 rbuf.resize(t);
128 pm->allToAllVariable(sbuf, m_send_count, m_send_index, rbuf, m_recv_count, m_recv_index32);
129 for (Int32 r = 0; r < nb_rank; ++r) {
130 const Int64 rlo = m_recv_index[r] + recv_count[r] * k / nb_round;
131 for (Int32 z = 0; z < m_recv_count[r]; ++z)
132 m_recv[rlo + z] = rbuf[m_recv_index32[r] + z];
133 }
134 }
135}
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
141wait()
142{
143 if (m_is_pending)
144 m_pm->waitAllRequests(ArrayView<Parallel::Request>(1, &m_request));
145 m_is_pending = false;
146}
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
152from(Int32 rank) const
153{
154 return m_recv.constSpan().subSpan(m_recv_index[rank], m_recv_index[rank + 1] - m_recv_index[rank]);
155}
156
157/*---------------------------------------------------------------------------*/
158/*---------------------------------------------------------------------------*/
159
160} // namespace Arcane::mesh
161
162/*---------------------------------------------------------------------------*/
163/*---------------------------------------------------------------------------*/
Modifiable view of an array of type T.
Base class for 1D data vectors.
void resize(Int64 s)
Changes the number of elements in the array to s.
Constant view of an array of type T.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
Interface of the parallelism manager for a subdomain.
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual IParallelNonBlockingCollective * nonBlockingCollective() const =0
Interface for non-blocking collective operations.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
Interface for non-blocking collective parallel operations.
View of an array of elements of type T.
Definition Span.h:633
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:734
1D data vector with value semantics (STL style).
void start(IParallelMng *pm, ConstArrayView< Int64 > send, ConstArrayView< Int64 > send_count, ConstArrayView< Int64 > recv_count, Int64 nb_round)
Posts the exchange of send, send_count[r] Int64 for rank r.
static Int64 _nbRound(Int64 g_max, Int32 nb_rank)
static Int64 exchangeCounts(IParallelMng *pm, ConstArrayView< Int64 > send_count, Array< Int64 > &recv_count)
Exchanges the counts, per rank, of what an exchange will bring.
void wait()
Completes the exchange.
Span< const Int64 > from(Int32 rank) const
What rank sent.
@ ReduceMax
Maximum of values.
std::int64_t Int64
Signed integer type of 64 bits.
std::int32_t Int32
Signed integer type of 32 bits.