Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MessagePassingUtils.h
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/* MessagePassingUtils.h (C) 2000-2026 */
9/* */
10/* Diverses utilitaires pour gérer le passage de messages. */
11/*---------------------------------------------------------------------------*/
12#ifndef ARCCORE_ALINA_MESSAGEPASSINGUTILS_H
13#define ARCCORE_ALINA_MESSAGEPASSINGUTILS_H
14/*---------------------------------------------------------------------------*/
15/*---------------------------------------------------------------------------*/
16/*
17 * Ce fichier est basé sur le travail effectué sur la bibliothèque AMGCL (version mars 2026)
18 * qui peut être trouvée à https://github.com/ddemidov/amgcl.
19 *
20 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
21 * SPDX-License-Identifier: MIT
22 */
23/*---------------------------------------------------------------------------*/
24/*---------------------------------------------------------------------------*/
25
26#include "arccore/base/FixedArray.h"
27#include "arccore/common/Array.h"
28
29#include "arccore/message_passing_mpi/StandaloneMpiMessagePassingMng.h"
31#include "arccore/message_passing/PointToPointMessageInfo.h"
32
33#include "arccore/alina/ValueTypeInterface.h"
34#include "arccore/alina/AlinaUtils.h"
35
36#include <vector>
37#include <numeric>
38#include <complex>
39#include <type_traits>
40
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44namespace Arcane::Alina
45{
46
47/*---------------------------------------------------------------------------*/
48/*---------------------------------------------------------------------------*/
49
51struct mpi_init
52{
53 mpi_init(int* argc, char*** argv)
54 {
55 MPI_Init(argc, argv);
56 }
57
58 ~mpi_init()
59 {
60 MPI_Finalize();
61 }
62};
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
68struct mpi_init_thread
69{
70 mpi_init_thread(int* argc, char*** argv)
71 {
72 int _;
73 MPI_Init_thread(argc, argv, MPI_THREAD_MULTIPLE, &_);
74 }
75
76 ~mpi_init_thread()
77 {
78 MPI_Finalize();
79 }
80};
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
87struct mpi_communicator
88{
89 MPI_Comm comm = MPI_COMM_NULL;
90 int rank = 0;
91 int size = 0;
92 Ref<IMessagePassingMng> m_message_passing_mng;
93
94 mpi_communicator() = default;
95
96 explicit mpi_communicator(MPI_Comm comm)
97 : comm(comm)
98 {
99 MPI_Comm_rank(comm, &rank);
100 MPI_Comm_size(comm, &size);
102 };
103
104 operator MPI_Comm() const
105 {
106 return comm;
107 }
108
110 template <typename T>
111 std::vector<T> exclusive_sum(T n) const
112 {
113 // TODO: Utiliser scan.
114 std::vector<T> v(size + 1);
115 v[0] = 0;
116 T v0 = n;
117 ConstArrayView<T> v0_view(1, &v0);
118 ArrayView<T> out_view(static_cast<Int32>(v.size()), &v[1]);
119 mpAllGather(m_message_passing_mng.get(), v0_view, out_view);
120 std::partial_sum(v.begin(), v.end(), v.begin());
121 return v;
122 }
123
124 std::complex<long double> reduceSum(const std::complex<long double>& lval) const
125 {
126 return _reduceSumForComplex(lval);
127 }
128 std::complex<double> reduceSum(const std::complex<double>& lval) const
129 {
130 return _reduceSumForComplex(lval);
131 }
132 std::complex<float> reduceSum(const std::complex<float>& lval) const
133 {
134 return _reduceSumForComplex(lval);
135 }
136
137 template <typename T> T reduceSum(const T& lval) const
138 {
139 return mpAllReduce(m_message_passing_mng.get(), MessagePassing::eReduceType::ReduceSum, lval);
140 }
141
142 void waitAll(ArrayView<MessagePassing::Request> requests) const
143 {
144 mpWaitAll(m_message_passing_mng.get(), requests);
145 }
146 void wait(MessagePassing::Request request) const
147 {
148 ArrayView<MessagePassing::Request> requests(1, &request);
149 mpWaitAll(m_message_passing_mng.get(), requests);
150 }
151
161 template <class Condition, class Message>
162 void check(const Condition& cond, const Message& message)
163 {
164 int lc = static_cast<int>(cond);
165 int gc = _reduce(MPI_PROD, lc);
166
167 if (gc==0) {
168 IMessagePassingMng* pm = m_message_passing_mng.get();
169 UniqueArray<int> c(size);
170 if (rank == 0)
171 c.resize(size);
172 ConstArrayView<int> in_view(1, &lc);
173 mpGather(pm, in_view, c, 0);
174 if (rank == 0) {
175 std::cerr << "Failed assumption: " << message << std::endl;
176 std::cerr << "Offending processes:";
177 for (int i = 0; i < size; ++i)
178 if (!c[i])
179 std::cerr << " " << i;
180 std::cerr << std::endl;
181 }
182 mpBarrier(pm);
183 ARCCORE_FATAL("CheckError in MessagePassingUtils: {0}", message);
184 }
185 }
186
187 template <typename T> MessagePassing::Request
188 doIReceive(T* buf, int count, int source, int tag) const
189 {
190 using namespace Arcane::MessagePassing;
191 Span<T> s(buf, count);
192 Span<unsigned char> schar(reinterpret_cast<unsigned char*>(s.data()), s.sizeBytes());
193 PointToPointMessageInfo msg_info(MessageRank{ source }, MessageTag{ tag }, eBlockingType::NonBlocking);
194 return mpReceive(m_message_passing_mng.get(), schar, msg_info);
195 }
196
197 template <typename T> void
198 doReceive(T* buf, int count, int source, int tag) const
199 {
200 using namespace Arcane::MessagePassing;
201 Span<T> s(buf, count);
202 Span<unsigned char> schar(reinterpret_cast<unsigned char*>(s.data()), s.sizeBytes());
203 PointToPointMessageInfo msg_info(MessageRank{ source }, MessageTag{ tag }, eBlockingType::Blocking);
204 mpReceive(m_message_passing_mng.get(), schar, msg_info);
205 }
206
207 template <typename T> MessagePassing::Request
208 doISend(const T* buf, int count, int dest, int tag) const
209 {
210 using namespace Arcane::MessagePassing;
211 Span<const T> s(buf, count);
212 Span<const unsigned char> schar(reinterpret_cast<const unsigned char*>(s.data()), s.sizeBytes());
213 PointToPointMessageInfo msg_info(MessageRank{ dest }, MessageTag{ tag }, eBlockingType::NonBlocking);
214 return mpSend(m_message_passing_mng.get(), schar, msg_info);
215 }
216
217 template <typename T> void
218 doSend(const T* buf, int count, int dest, int tag) const
219 {
220 using namespace Arcane::MessagePassing;
221 Span<const T> s(buf, count);
222 Span<const unsigned char> schar(reinterpret_cast<const unsigned char*>(s.data()), s.sizeBytes());
223 PointToPointMessageInfo msg_info(MessageRank{ dest }, MessageTag{ tag }, eBlockingType::Blocking);
224 mpSend(m_message_passing_mng.get(), schar, msg_info);
225 }
226
227 private:
228
229 int _reduce(MPI_Op op, int lval) const
230 {
231 int gval = 0;
232
233 MPI_Allreduce((void*)&lval, &gval, 1, MPI_INT, op, comm);
234 return gval;
235 }
236
237 template <typename T> std::complex<T>
238 _reduceSumForComplex(const std::complex<T>& lval) const
239 {
240 // Spécialisation pour 'std::complex<float>' en tant que 2 flottants.
241 FixedArray<T, 2> values = { { lval.real(), lval.imag() } };
242 mpAllReduce(m_message_passing_mng.get(), MessagePassing::eReduceType::ReduceSum, values.view());
243 return std::complex<T>(values[0], values[1]);
244 }
245};
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250} // namespace Arcane::Alina
251
252/*---------------------------------------------------------------------------*/
253/*---------------------------------------------------------------------------*/
254
255#endif
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Liste des fonctions d'échange de message.
Vue modifiable d'un tableau d'un type T.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
Vue constante d'un tableau de type T.
constexpr __host__ __device__ ArrayView< T > view()
Vue modifiable sur le tableau.
Interface du gestionnaire des échanges de messages.
static Ref< IMessagePassingMng > createRef(MPI_Comm comm, bool clean_comm=false)
Créé un gestionnaire associé au communicateur comm.
Informations pour envoyer/recevoir un message point à point.
Requête d'un message.
Definition Request.h:77
InstanceType * get() const
Instance associée ou nullptr si aucune.
Référence à une instance.
Vue d'un tableau d'éléments de type T.
Definition Span.h:633
Vecteur 1D de données avec sémantique par valeur (style STL).
Déclarations des types et méthodes utilisés par les mécanismes d'échange de messages.
C void mpGather(IMessagePassingMng *pm, Span< const char > send_buf, Span< char > recv_buf, Int32 rank)
C char mpAllReduce(IMessagePassingMng *pm, eReduceType rt, char v)
void mpBarrier(IMessagePassingMng *pm)
Effectue une barrière.
Definition Messages.cc:248
void mpAllGather(IMessagePassingMng *pm, const ISerializer *send_serializer, ISerializer *receive_serialize)
Message allGather() pour une sérialisation.
Definition Messages.cc:308
void mpWaitAll(IMessagePassingMng *pm, ArrayView< Request > requests)
Bloque tant que les requêtes de requests ne sont pas terminées.
Definition Messages.cc:163
Request mpReceive(IMessagePassingMng *pm, ISerializer *values, const PointToPointMessageInfo &message)
Message de réception utilisant un ISerializer.
Definition Messages.cc:289
Request mpSend(IMessagePassingMng *pm, const ISerializer *values, const PointToPointMessageInfo &message)
Message d'envoi utilisant un ISerializer.
Definition Messages.cc:278
std::int32_t Int32
Type entier signé sur 32 bits.
void check(const Condition &cond, const Message &message)
Vérification de condition par communicateur.
std::vector< T > exclusive_sum(T n) const
Exclusive sum over mpi communicator.