Arcane  v3.16.0.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
MpiSerializeDispatcher.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 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/* MpiSerializeDispatcher.cc (C) 2000-2025 */
9/* */
10/* Gestion des messages de sérialisation avec MPI. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/message_passing_mpi/internal/MpiSerializeDispatcher.h"
15
16#include "arccore/message_passing_mpi/internal/MpiAdapter.h"
17#include "arccore/message_passing_mpi/MpiMessagePassingMng.h"
18#include "arccore/message_passing_mpi/internal/MpiLock.h"
19
20#include "arccore/message_passing/Request.h"
21#include "arccore/message_passing/SerializeMessageList.h"
22#include "arccore/message_passing/internal/SubRequestCompletionInfo.h"
23
24#include "arccore/serialize/BasicSerializer.h"
25
26#include "arccore/base/NotImplementedException.h"
27#include "arccore/base/FatalErrorException.h"
28#include "arccore/base/NotSupportedException.h"
29#include "arccore/base/ArgumentException.h"
30#include "arccore/base/PlatformUtils.h"
31#include "arccore/trace/ITraceMng.h"
32
33/*---------------------------------------------------------------------------*/
34/*---------------------------------------------------------------------------*/
35
36namespace Arcane::MessagePassing::Mpi
37{
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41/*!
42 * \internal
43 * \brief Wrappeur pour envoyer un tableau d'octets d'un sérialiseur.
44 *
45 * \a SpanType doit être un 'Byte' ou un 'const Byte'.
46 *
47 * Comme MPI utilise un 'int' pour le nombre d'éléments d'un message, on ne
48 * peut pas dépasser 2^31 octets pas message. Par contre, les versions 3.0+
49 * de MPI supportent des messages dont la longueur dépasse 2^31.
50 * On utilise donc un type dérivé MPI contenant N octets (avec N donné
51 * par SerializeBuffer::paddingSize()) et on indique à MPI que c'est ce type
52 * qu'on envoie. Le nombre d'éléments est donc divisé par N ce qui permet
53 * de tenir sur 'int' si la taille du message est inférieure à 2^31 * N octets
54 * (en février 2019, N=128 soit des messages de 256Go maximum).
55 *
56 * \note Pour que cela fonctionne, le tableau \a buffer doit avoir une
57 * mémoire allouée arrondie au multiple de N supérieur au nombre d'éléments
58 * mais normalement cela est garanti par le SerializeBuffer.
59 */
60template<typename SpanType>
61class SerializeByteConverter
62{
63 public:
64 SerializeByteConverter(Span<SpanType> buffer,MPI_Datatype byte_serializer_datatype)
65 : m_buffer(buffer), m_datatype(byte_serializer_datatype), m_final_size(-1)
66 {
67 Int64 size = buffer.size();
68 const Int64 align_size = BasicSerializer::paddingSize();
69 if ((size%align_size)!=0)
70 ARCCORE_FATAL("Buffer size '{0}' is not a multiple of '{1}' Invalid size",size,align_size);
71 m_final_size = size / align_size;
72 }
73 SpanType* data() { return m_buffer.data(); }
74 Int64 size() const { return m_final_size; }
75 Int64 messageSize() const { return m_buffer.size() * sizeof(Byte); }
76 Int64 elementSize() const { return BasicSerializer::paddingSize(); }
77 MPI_Datatype datatype() const { return m_datatype; }
78 private:
79 Span<SpanType> m_buffer;
80 MPI_Datatype m_datatype;
81 Int64 m_final_size;
82};
83
84/*---------------------------------------------------------------------------*/
85/*---------------------------------------------------------------------------*/
86/*!
87 * \brief Sous-requête d'envoi.
88 *
89 * Cette classe est utilisée lorsqu'un message de sérialisation est trop
90 * gros pour être envoyé en une seule fois. Dans ce cas, un deuxième message
91 * est envoyé. Ce deuxième message contient le message complet de sérialisation
92 * car le destinataire connait la taille complète du message et peut donc
93 * allouer la mémoire nécessaire.
94 */
96: public ISubRequest
97{
98 public:
99
100 SendSerializerSubRequest(MpiSerializeDispatcher* pm,BasicSerializer* buf,
101 MessageRank rank,MessageTag mpi_tag)
102 : m_dispatcher(pm), m_serialize_buffer(buf), m_rank(rank), m_mpi_tag(mpi_tag) {}
103
104 public:
105
106 Request executeOnCompletion(const SubRequestCompletionInfo&) override
107 {
108 if (!m_is_message_sent)
109 sendMessage();
110 return m_send_request;
111 }
112 public:
113 void sendMessage()
114 {
115 if (m_is_message_sent)
116 ARCCORE_FATAL("Message already sent");
117 bool do_print = m_dispatcher->m_is_trace_serializer;
118 if (do_print){
119 ITraceMng* tm = m_dispatcher->traceMng();
120 tm->info() << " SendSerializerSubRequest::sendMessage()"
121 << " rank=" << m_rank << " tag=" << m_mpi_tag;
122 }
123 Span<Byte> bytes = m_serialize_buffer->globalBuffer();
124 m_send_request = m_dispatcher->_sendSerializerBytes(bytes,m_rank,m_mpi_tag,false);
125 m_is_message_sent = true;
126 }
127 private:
128 MpiSerializeDispatcher* m_dispatcher;
129 BasicSerializer* m_serialize_buffer;
130 MessageRank m_rank;
131 MessageTag m_mpi_tag;
132 Request m_send_request;
133 bool m_is_message_sent = false;
134};
135
136/*---------------------------------------------------------------------------*/
137/*---------------------------------------------------------------------------*/
138
140: public ISubRequest
141{
142 public:
143
144 ReceiveSerializerSubRequest(MpiSerializeDispatcher* d,BasicSerializer* buf,
145 MessageTag mpi_tag, Integer action)
146 : m_dispatcher(d)
147 , m_serialize_buffer(buf)
148 , m_mpi_tag(mpi_tag)
149 , m_action(action)
150 {}
151
152 public:
153
154 Request executeOnCompletion(const SubRequestCompletionInfo& completion_info) override
155 {
156 MessageRank rank = completion_info.sourceRank();
157 bool is_trace = m_dispatcher->m_is_trace_serializer;
158 ITraceMng* tm = m_dispatcher->traceMng();
159 if (is_trace) {
160 tm->info() << " ReceiveSerializerSubRequest::executeOnCompletion()"
161 << " rank=" << rank << " wanted_tag=" << m_mpi_tag << " action=" << m_action;
162 }
163 if (m_action==1){
164 BasicSerializer* sbuf = m_serialize_buffer;
165 Int64 total_recv_size = sbuf->totalSize();
166
167 if (is_trace) {
168 tm->info() << " ReceiveSerializerSubRequest::executeOnCompletion() total_size=" << total_recv_size
169 << BasicSerializer::SizesPrinter(*m_serialize_buffer);
170 }
171 // Si le message est plus petit que le buffer, le désérialise simplement
172 if (total_recv_size<=m_dispatcher->m_serialize_buffer_size){
173 sbuf->setFromSizes();
174 return {};
175 }
176
177 sbuf->preallocate(total_recv_size);
178 auto bytes = sbuf->globalBuffer();
179
180 // La nouvelle requête doit utiliser le même rang source que celui de cette requête
181 // pour être certain qu'il n'y a pas d'incohérence.
182 Request r2 = m_dispatcher->_recvSerializerBytes(bytes, rank, m_mpi_tag, false);
183 ISubRequest* sr = new ReceiveSerializerSubRequest(m_dispatcher, m_serialize_buffer, m_mpi_tag, 2);
184 r2.setSubRequest(makeRef(sr));
185 return r2;
186 }
187 if (m_action==2){
188 m_serialize_buffer->setFromSizes();
189 }
190 return {};
191 }
192
193 private:
194
195 MpiSerializeDispatcher* m_dispatcher = nullptr;
196 BasicSerializer* m_serialize_buffer = nullptr;
197 MessageTag m_mpi_tag;
198 Int32 m_action = 0;
199};
200
201/*---------------------------------------------------------------------------*/
202/*---------------------------------------------------------------------------*/
203
204/*---------------------------------------------------------------------------*/
205/*---------------------------------------------------------------------------*/
206
207MpiSerializeDispatcher::
208MpiSerializeDispatcher(MpiAdapter* adapter, IMessagePassingMng* message_passing_mng)
209: m_adapter(adapter)
210, m_message_passing_mng(message_passing_mng)
211, m_trace(adapter->traceMng())
212, m_serialize_buffer_size(50000)
213//, m_serialize_buffer_size(20000000)
214, m_max_serialize_buffer_size(m_serialize_buffer_size)
215, m_byte_serializer_datatype(MPI_DATATYPE_NULL)
216{
217 _init();
218}
219
220/*---------------------------------------------------------------------------*/
221/*---------------------------------------------------------------------------*/
222
223MpiSerializeDispatcher::
224~MpiSerializeDispatcher()
225{
226 if (m_byte_serializer_datatype!=MPI_DATATYPE_NULL)
227 MPI_Type_free(&m_byte_serializer_datatype);
228}
229
230/*---------------------------------------------------------------------------*/
231/*---------------------------------------------------------------------------*/
232
233MessageTag MpiSerializeDispatcher::
234nextSerializeTag(MessageTag tag)
235{
236 return MessageTag(tag.value()+1);
237}
238
239/*---------------------------------------------------------------------------*/
240/*---------------------------------------------------------------------------*/
241
242void MpiSerializeDispatcher::
243_init()
244{
245 // Type pour la sérialisation en octet.
246 MPI_Datatype mpi_datatype;
247 MPI_Type_contiguous(BasicSerializer::paddingSize(),MPI_CHAR,&mpi_datatype);
248 MPI_Type_commit(&mpi_datatype);
249 m_byte_serializer_datatype = mpi_datatype;
250
251 if (!Platform::getEnvironmentVariable("ARCCORE_TRACE_MESSAGE_PASSING_SERIALIZE").empty())
252 m_is_trace_serializer = true;
253}
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
258Request MpiSerializeDispatcher::
259legacySendSerializer(ISerializer* values,const PointToPointMessageInfo& message)
260{
261 if (!message.isRankTag())
262 ARCCORE_FATAL("Only message.isRangTag()==true are allowed for legacy mode");
263
264 MessageRank rank = message.destinationRank();
265 MessageTag mpi_tag = message.tag();
266 bool is_blocking = message.isBlocking();
267
268 BasicSerializer* sbuf = _castSerializer(values);
269 ITraceMng* tm = m_trace;
270
271 Span<Byte> bytes = sbuf->globalBuffer();
272
273 Int64 total_size = sbuf->totalSize();
274 _checkBigMessage(total_size);
275
276 if (m_is_trace_serializer)
277 tm->info() << "legacySendSerializer(): sending to "
278 << " rank=" << rank << " bytes " << bytes.size()
279 << BasicSerializer::SizesPrinter(*sbuf)
280 << " tag=" << mpi_tag << " is_blocking=" << is_blocking;
281
282 // Si le message est plus petit que le buffer par défaut de sérialisation,
283 // envoie tout le message
284 if (total_size<=m_serialize_buffer_size){
285 if (m_is_trace_serializer)
286 tm->info() << "Small message size=" << bytes.size();
287 return _sendSerializerBytes(bytes,rank,mpi_tag,is_blocking);
288 }
289
290 {
291 // le message est trop grand pour tenir dans le buffer, envoie d'abord les tailles,
292 // puis le message sérialisé.
293 auto x = sbuf->copyAndGetSizesBuffer();
294 if (m_is_trace_serializer)
295 tm->info() << "Big message first size=" << x.size();
296 Request r = _sendSerializerBytes(x,rank,mpi_tag,is_blocking);
297 if (!is_blocking){
298 SerializeSubRequest* sub_request = new SerializeSubRequest();
299 sub_request->m_request = r;
300 //m_trace->info() << "** ADD SUB REQUEST r=" << r;
301 {
302 MpiLock::Section ls(m_adapter->mpiLock());
303 m_sub_requests.add(sub_request);
304 }
305 }
306 }
307
308 if (m_is_trace_serializer)
309 tm->info() << "Big message second size=" << bytes.size();
310 return _sendSerializerBytes(bytes,rank,nextSerializeTag(mpi_tag),is_blocking);
311}
312
313/*---------------------------------------------------------------------------*/
314/*---------------------------------------------------------------------------*/
315
316Request MpiSerializeDispatcher::
317_recvSerializerBytes(Span<Byte> bytes,MessageId message_id,bool is_blocking)
318{
319 SerializeByteConverter<Byte> sbc(bytes,m_byte_serializer_datatype);
320 MPI_Datatype dt = sbc.datatype();
321 if (m_is_trace_serializer)
322 m_trace->info() << "_recvSerializerBytes: size=" << bytes.size()
323 << " message_id=" << message_id << " is_blocking=" << is_blocking;
324 return m_adapter->directRecv(sbc.data(),sbc.size(),message_id,sbc.elementSize(),dt,is_blocking);
325}
326
327/*---------------------------------------------------------------------------*/
328/*---------------------------------------------------------------------------*/
329
330Request MpiSerializeDispatcher::
331_recvSerializerBytes(Span<Byte> bytes,MessageRank rank,MessageTag tag,bool is_blocking)
332{
333 SerializeByteConverter<Byte> sbc(bytes,m_byte_serializer_datatype);
334 MPI_Datatype dt = sbc.datatype();
335 if (m_is_trace_serializer)
336 m_trace->info() << "_recvSerializerBytes: size=" << bytes.size()
337 << " rank=" << rank << " tag=" << tag << " is_blocking=" << is_blocking;
338 Request r = m_adapter->directRecv(sbc.data(),sbc.size(),rank.value(),
339 sbc.elementSize(),dt,tag.value(),is_blocking);
340 if (m_is_trace_serializer)
341 m_trace->info() << "_recvSerializerBytes: request=" << r;
342 return r;
343}
344
345/*---------------------------------------------------------------------------*/
346/*---------------------------------------------------------------------------*/
347
348Request MpiSerializeDispatcher::
349_sendSerializerBytes(Span<const Byte> bytes,MessageRank rank,MessageTag tag,
350 bool is_blocking)
351{
352 SerializeByteConverter<const Byte> sbc(bytes,m_byte_serializer_datatype);
353 MPI_Datatype dt = sbc.datatype();
354 if (m_is_trace_serializer)
355 m_trace->info() << "_sendSerializerBytes: orig_size=" << bytes.size()
356 << " rank=" << rank << " tag=" << tag
357 << " second_size=" << sbc.size()
358 << " message_size=" << sbc.messageSize();
359 Request r = m_adapter->directSend(sbc.data(),sbc.size(),rank.value(),
360 sbc.elementSize(),dt,tag.value(),is_blocking);
361 if (m_is_trace_serializer)
362 m_trace->info() << "_sendSerializerBytes: request=" << r;
363 return r;
364}
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
369void MpiSerializeDispatcher::
370legacyReceiveSerializer(ISerializer* values,MessageRank rank,MessageTag mpi_tag)
371{
372 BasicSerializer* sbuf = _castSerializer(values);
373 ITraceMng* tm = m_trace;
374
375 if (m_is_trace_serializer)
376 tm->info() << "legacyReceiveSerializer() begin receive"
377 << " rank=" << rank << " tag=" << mpi_tag;
378 sbuf->preallocate(m_serialize_buffer_size);
379 Span<Byte> bytes = sbuf->globalBuffer();
380
381 _recvSerializerBytes(bytes,rank,mpi_tag,true);
382 Int64 total_recv_size = sbuf->totalSize();
383
384 if (m_is_trace_serializer)
385 tm->info() << "legacyReceiveSerializer total_size=" << total_recv_size
386 << " from=" << rank
387 << BasicSerializer::SizesPrinter(*sbuf);
388
389
390 // Si le message est plus petit que le buffer, le désérialise simplement
391 if (total_recv_size<=m_serialize_buffer_size){
392 sbuf->setFromSizes();
393 return;
394 }
395
396 if (m_is_trace_serializer)
397 tm->info() << "Receive overflow buffer: " << total_recv_size;
398 sbuf->preallocate(total_recv_size);
399 bytes = sbuf->globalBuffer();
400 _recvSerializerBytes(bytes,rank,nextSerializeTag(mpi_tag),true);
401 sbuf->setFromSizes();
402 if (m_is_trace_serializer)
403 tm->info() << "End receive overflow buffer: " << total_recv_size;
404}
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
409void MpiSerializeDispatcher::
410checkFinishedSubRequests()
411{
412 // Regarde si les sous-requêtes sont terminées pour les libérer
413 // Cela est uniquement utilisé avec le mode historique où on utilise
414 // la classe 'MpiSerializeMessageList'.
415 UniqueArray<SerializeSubRequest*> new_sub_requests;
416 for( Integer i=0, n=m_sub_requests.size(); i<n; ++i ){
417 SerializeSubRequest* ssr = m_sub_requests[i];
418 bool is_finished = m_adapter->testRequest(ssr->m_request);
419 if (!is_finished){
420 new_sub_requests.add(ssr);
421 }
422 else{
423 delete ssr;
424 }
425 }
426 m_sub_requests = new_sub_requests;
427}
428
429/*---------------------------------------------------------------------------*/
430/*---------------------------------------------------------------------------*/
431
432void MpiSerializeDispatcher::
433_checkBigMessage(Int64 message_size)
434{
435 if (message_size>m_max_serialize_buffer_size){
436 m_max_serialize_buffer_size = message_size;
437 m_trace->info() << "big buffer: " << message_size;
438 }
439}
440
441/*---------------------------------------------------------------------------*/
442/*---------------------------------------------------------------------------*/
443
444Request MpiSerializeDispatcher::
445sendSerializer(const ISerializer* s,const PointToPointMessageInfo& message)
446{
447 return sendSerializer(s,message,false);
448}
449
450/*---------------------------------------------------------------------------*/
451/*---------------------------------------------------------------------------*/
452
453Request MpiSerializeDispatcher::
454sendSerializer(const ISerializer* s,const PointToPointMessageInfo& message,
455 bool force_one_message)
456{
457 BasicSerializer* sbuf = _castSerializer(const_cast<ISerializer*>(s));
458
459 MessageRank rank = message.destinationRank();
460 MessageTag mpi_tag = message.tag();
461 bool is_blocking = message.isBlocking();
462
463 ITraceMng* tm = m_trace;
464
465 Span<const Byte> bytes = sbuf->globalBuffer();
466 Int64 total_size = sbuf->totalSize();
467 _checkBigMessage(total_size);
468
469 if (m_is_trace_serializer)
470 tm->info() << "sendSerializer(): sending to "
471 << " p2p_message=" << message
472 << " rank=" << rank << " bytes " << bytes.size()
473 << BasicSerializer::SizesPrinter(*sbuf)
474 << " tag=" << mpi_tag
475 << " total_size=" << total_size;
476
477
478 // Si le message est plus petit que le buffer par défaut de sérialisation
479 // ou qu'on choisit de n'envoyer qu'un seul message, envoie tout le message
480 if (total_size<=m_serialize_buffer_size || force_one_message){
481 if (m_is_trace_serializer)
482 tm->info() << "Small message size=" << bytes.size();
483 return _sendSerializerBytes(bytes,rank,mpi_tag,is_blocking);
484 }
485
486 // Sinon, envoie d'abord les tailles puis une autre requête qui
487 // va envoyer tout le message.
488 auto x = sbuf->copyAndGetSizesBuffer();
489 Request r1 = _sendSerializerBytes(x,rank,mpi_tag,is_blocking);
490 auto* x2 = new SendSerializerSubRequest(this,sbuf,rank,nextSerializeTag(mpi_tag));
491 // Envoi directement le message pour des raisons de performance.
492 x2->sendMessage();
493 r1.setSubRequest(makeRef<ISubRequest>(x2));
494 return r1;
495}
496
497/*---------------------------------------------------------------------------*/
498/*---------------------------------------------------------------------------*/
499
500Request MpiSerializeDispatcher::
501receiveSerializer(ISerializer* s,const PointToPointMessageInfo& message)
502{
503 BasicSerializer* sbuf = _castSerializer(s);
504 MessageRank rank = message.destinationRank();
505 MessageTag tag = message.tag();
506 bool is_blocking = message.isBlocking();
507
508 sbuf->preallocate(m_serialize_buffer_size);
509 Span<Byte> bytes = sbuf->globalBuffer();
510
511 Request r;
512 if (message.isRankTag())
513 r = _recvSerializerBytes(bytes,rank,tag,is_blocking);
514 else if (message.isMessageId())
515 r = _recvSerializerBytes(bytes,message.messageId(),is_blocking);
516 else
517 ARCCORE_THROW(NotSupportedException,"Only message.isRankTag() or message.isMessageId() is supported");
518 auto* sr = new ReceiveSerializerSubRequest(this, sbuf, nextSerializeTag(tag), 1);
519 r.setSubRequest(makeRef<ISubRequest>(sr));
520 return r;
521}
522
523/*---------------------------------------------------------------------------*/
524/*---------------------------------------------------------------------------*/
525
526void MpiSerializeDispatcher::
527broadcastSerializer(ISerializer* values,MessageRank rank)
528{
529 BasicSerializer* sbuf = _castSerializer(values);
530 ITraceMng* tm = m_trace;
531 MessageRank my_rank(m_adapter->commRank());
532 bool is_broadcaster = (rank==my_rank);
533
534 MPI_Datatype int64_datatype = MpiBuiltIn::datatype(Int64());
535 // Effectue l'envoie en deux phases. Envoie d'abord le nombre d'éléments
536 // puis envoie les éléments.
537 // TODO: il serait possible de le faire en une fois pour les messages
538 // ne dépassant pas une certaine taille.
539 if (is_broadcaster){
540 Int64 total_size = sbuf->totalSize();
541 Span<Byte> bytes = sbuf->globalBuffer();
542 _checkBigMessage(total_size);
543 ArrayView<Int64> total_size_buf(1,&total_size);
544 m_adapter->broadcast(total_size_buf.data(),total_size_buf.size(),rank.value(),int64_datatype);
545 if (m_is_trace_serializer)
546 tm->info() << "MpiSerializeDispatcher::broadcastSerializer(): sending "
547 << BasicSerializer::SizesPrinter(*sbuf);
548 SerializeByteConverter<Byte> sbc(bytes,m_byte_serializer_datatype);
549 m_adapter->broadcast(sbc.data(),sbc.size(),rank.value(),sbc.datatype());
550 }
551 else{
552 Int64 total_size = 0;
553 ArrayView<Int64> total_size_buf(1,&total_size);
554 m_adapter->broadcast(total_size_buf.data(),total_size_buf.size(),rank.value(),int64_datatype);
555 sbuf->preallocate(total_size);
556 Span<Byte> bytes = sbuf->globalBuffer();
557 SerializeByteConverter<Byte> sbc(bytes,m_byte_serializer_datatype);
558 m_adapter->broadcast(sbc.data(),sbc.size(),rank.value(),sbc.datatype());
559 sbuf->setFromSizes();
560 if (m_is_trace_serializer)
561 tm->info() << "MpiSerializeDispatcher::broadcastSerializer(): receiving from "
562 << " rank=" << rank << " bytes " << bytes.size()
563 << BasicSerializer::SizesPrinter(*sbuf);
564 }
565}
566
567/*---------------------------------------------------------------------------*/
568/*---------------------------------------------------------------------------*/
569
570BasicSerializer* MpiSerializeDispatcher::
571_castSerializer(ISerializer* serializer)
572{
573 BasicSerializer* sbuf = dynamic_cast<BasicSerializer*>(serializer);
574 if (!sbuf)
575 ARCCORE_THROW(ArgumentException,"Can not cast 'ISerializer' to 'BasicSerializer'");
576 return sbuf;
577}
578
579/*---------------------------------------------------------------------------*/
580/*---------------------------------------------------------------------------*/
581
582Ref<ISerializeMessageList> MpiSerializeDispatcher::
583createSerializeMessageListRef()
584{
585 ISerializeMessageList* x = new internal::SerializeMessageList(m_message_passing_mng);
586 return makeRef(x);
587}
588
589/*---------------------------------------------------------------------------*/
590/*---------------------------------------------------------------------------*/
591
592} // namespace Arccore::MessagePassing::Mpi
593
594/*---------------------------------------------------------------------------*/
595/*---------------------------------------------------------------------------*/
static ARCCORE_CONSTEXPR Integer paddingSize()
Taille du padding et de l'alignement.
Interface du gestionnaire de traces.
virtual TraceMessage info()=0
Flot pour un message d'information.
Interface du gestionnaire des échanges de messages.
Request executeOnCompletion(const SubRequestCompletionInfo &completion_info) override
Callback appelé lorsque la requête associée est terminée.
Request executeOnCompletion(const SubRequestCompletionInfo &) override
Callback appelé lorsque la requête associée est terminée.
Requête d'un message.
Definition Request.h:77
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:212
Vue d'un tableau d'éléments de type T.
Definition Span.h:513
ARCCORE_BASE_EXPORT String getEnvironmentVariable(const String &name)
Variable d'environnement du nom name.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
unsigned char Byte
Type d'un octet.
Definition BaseTypes.h:43
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.