Arcane  4.2.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
SharedMemoryMessageQueue.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/* SharedMemoryMessageQueue.cc (C) 2000-2026 */
9/* */
10/* Implémentation d'une file de messages en mémoire partagée. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/FatalErrorException.h"
15#include "arcane/utils/NotImplementedException.h"
16#include "arcane/utils/NotSupportedException.h"
17#include "arcane/utils/ArgumentException.h"
18#include "arcane/utils/ITraceMng.h"
19#include "arcane/utils/ValueConvert.h"
20#include "arcane/utils/SmallArray.h"
21
22#include "arccore/common/internal/MemoryResourceMng.h"
23
24#include "arcane/parallel/thread/SharedMemoryMessageQueue.h"
25#include "arcane/parallel/thread/IAsyncQueue.h"
26
27#include "arcane/core/ISerializeMessage.h"
28
29// Macro pour afficher des messages pour debug
30#define TRACE_DEBUG(format_str,...) \
31 if (m_is_debug && m_trace_mng){ \
32 m_trace_mng->info() << String::format(format_str,__VA_ARGS__); \
33 m_trace_mng->flush();\
34 }
35
36/*---------------------------------------------------------------------------*/
37/*---------------------------------------------------------------------------*/
38
40{
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
56{
57 SendBufferInfo send_info = sender->sendBufferInfo();
58 ReceiveBufferInfo receive_info = this->receiveBufferInfo();
59
60 const ISerializer* send_serializer = send_info.serializer();
61 ISerializer* receive_serializer = receive_info.serializer();
62 if (receive_serializer){
63 if (!send_serializer)
64 ARCANE_FATAL("No send serializer for receive serializer");
65 receive_serializer->copy(send_serializer);
66 return;
67 }
68
69 ByteConstSpan send_span = send_info.memoryBuffer();
70 ByteSpan receive_span = receive_info.memoryBuffer();
71 Int64 send_size = send_span.size();
72 Int64 receive_size = receive_span.size();
73 if (send_size > receive_size)
74 ARCANE_FATAL("Not enough memory for receiving message receive={0} send={1}",
75 receive_size,send_size);
76
78}
79
80/*---------------------------------------------------------------------------*/
81/*---------------------------------------------------------------------------*/
82
83void SharedMemoryMessageRequest::
84destroy()
85{
86 if (m_is_destroyed)
87 ARCANE_FATAL("Request already destroyed");
88 m_is_destroyed = true;
89 // Commenter pour debug.
90 delete this;
91}
92
93/*---------------------------------------------------------------------------*/
94/*---------------------------------------------------------------------------*/
95
96std::ostream&
97operator<<(std::ostream& o, const SharedMemoryMessageRequest& v)
98{
99 o << "(id=" << v.id() << " queue=" << v.queueName()
100 << " orig=" << v.orig() << " dest=" << v.dest()
101 << " tag=" << v.tag() << " is_recv?=" << v.isRecv()
102 << " is_done=?" << v.isDone()
103 << " send_size=" << v.m_send_buffer_info.memoryBuffer().size()
104 << " receive_size=" << v.m_receive_buffer_info.memoryBuffer().size()
105 << ")";
106 return o;
107}
108
109/*---------------------------------------------------------------------------*/
110/*---------------------------------------------------------------------------*/
117class RequestAsyncQueue
118{
119 public:
120 RequestAsyncQueue()
121 : m_async_queue(IAsyncQueue::createQueue()){}
122 ~RequestAsyncQueue()
123 {
124 delete m_async_queue;
125 }
126 public:
127 void push(SharedMemoryMessageRequest* v)
128 {
129 m_async_queue->push(v);
130 }
132 {
133 return static_cast<SharedMemoryMessageRequest*>(m_async_queue->pop());
134 }
136 {
137 return static_cast<SharedMemoryMessageRequest*>(m_async_queue->tryPop());
138 }
139 private:
140
141 IAsyncQueue* m_async_queue = nullptr;
142};
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147/*---------------------------------------------------------------------------*/
148/*---------------------------------------------------------------------------*/
161{
162 static MessageTag SERIALIZER_TAG() { return MessageTag(125); }
163
164 public:
165
166 SubQueue(SharedMemoryMessageQueue* master_queue,MessageRank rank);
167
168 public:
169
170 MessageRank rank() const { return m_rank; }
171 void setTraceMng(ITraceMng* tm) { m_trace_mng = tm; }
172 ITraceMng* traceMng() const { return m_trace_mng; }
173 void wait(SharedMemoryMessageRequest* tmr);
174 void testRequest(SharedMemoryMessageRequest* tmr);
175 void waitRequestAvailable();
176 void checkRequestAvailable();
177 void waitSome(ArrayView<Request> requests,ArrayView<bool> requests_done,bool is_non_blocking);
178 MessageId probe(const PointToPointMessageInfo& message);
179 MessageSourceInfo legacyProbe(const PointToPointMessageInfo& message);
180 void setName(const String& name) { m_name = name; }
181 const String& name() const { return m_name; }
182
183 public:
184
186 addReceive(Int64 request_id,const PointToPointMessageInfo& message,ReceiveBufferInfo buf);
188 addSend(Int64 request_id,const PointToPointMessageInfo& message,SendBufferInfo buf);
189
190 private:
191
192 SharedMemoryMessageQueue* m_master_queue = nullptr;
193 MessageRank m_rank;
197 RequestAsyncQueue m_async_message_queue;
198 ITraceMng* m_trace_mng = nullptr;
199 bool m_is_debug = false;
200 bool m_is_allow_null_rank_for_any_source = true;
201 String m_name;
202
203 private:
204
205 void _removeRequest(SharedMemoryMessageRequest* tmr,Array<SharedMemoryMessageRequest*>& requests);
206 bool _checkSendDone(SharedMemoryMessageRequest* tmr_send);
207 bool _checkRecvDone(SharedMemoryMessageRequest* tmr_recv);
208 void _checkRequestDone(SharedMemoryMessageRequest* tmr);
211 _getMatchingSendRequest(MessageRank recv_dest,MessageRank recv_orig,MessageTag tag);
212 void _testOrWaitRequestAvailable(bool is_blocking);
214 _createReceiveRequest(Int64 request_id,MessageRank dest,MessageTag tag,
215 ReceiveBufferInfo receive_buffer);
217 _createSendRequest(Int64 request_id,MessageRank orig,MessageTag tag,
218 SendBufferInfo send_buffer);
219};
220
221/*---------------------------------------------------------------------------*/
222/*---------------------------------------------------------------------------*/
223
224SharedMemoryMessageQueue::SubQueue::
225SubQueue(SharedMemoryMessageQueue* master_queue,MessageRank rank)
226: m_master_queue(master_queue)
227, m_rank(rank)
228{
229 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCCORE_ALLOW_NULL_RANK_FOR_MPI_ANY_SOURCE", true))
230 m_is_allow_null_rank_for_any_source = v.value() != 0;
231 m_name = String::format("queue{0}", rank);
232 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_DEBUG_SHAREDMEMORY_MESSAGEPASSING", true))
233 m_is_debug = (v.value() != 0);
234}
235
236/*---------------------------------------------------------------------------*/
237/*---------------------------------------------------------------------------*/
238
239/*---------------------------------------------------------------------------*/
240/*---------------------------------------------------------------------------*/
241
242SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
243_createReceiveRequest(Int64 request_id,MessageRank dest,
244 MessageTag tag,ReceiveBufferInfo receive_buffer)
245{
246 auto* tmr = new SharedMemoryMessageRequest(this,request_id,m_rank,dest,tag,receive_buffer);
247 return tmr;
248}
249
250/*---------------------------------------------------------------------------*/
251/*---------------------------------------------------------------------------*/
252
253SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
254_createSendRequest(Int64 request_id,MessageRank orig,
255 MessageTag tag,SendBufferInfo send_buffer)
256{
257 SubQueue* queue = m_master_queue->_getSubQueue(orig);
258 auto* tmr = new SharedMemoryMessageRequest(queue,request_id,orig,m_rank,tag,send_buffer);
259 return tmr;
260}
261
262/*---------------------------------------------------------------------------*/
263/*---------------------------------------------------------------------------*/
264
265SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
266addReceive(Int64 request_id,const PointToPointMessageInfo& message,ReceiveBufferInfo buf)
267{
268 SharedMemoryMessageRequest* tmr = nullptr;
269 if (message.isRankTag()){
270 MessageTag tag = message.tag();
271 MessageRank dest = message.destinationRank();
272 tmr = _createReceiveRequest(request_id, dest, tag, buf);
273 TRACE_DEBUG("** ADD RECV queue={0} id={1} ORIG={2} DEST={3} tmr={4} size={5} serializer={6}",
274 m_name, request_id, m_rank, dest, tag, *tmr, buf.memoryBuffer().size(), buf.serializer());
275 }
276 else if (message.isMessageId()){
277 MessageId message_id = message.messageId();
278 MessageId::SourceInfo si = message_id.sourceInfo();
279 MessageRank dest = si.rank();
280 MessageTag tag = si.tag();
281
282 // On connait la requête 'send' qui matche celle ci. Il faut donc
283 // la positionner dès maintenant dans \a tmr pour être sur qu'on utilisera la bonne.
284 // Pour cela, cherche le send correspondant à l'id de notre requête
285 Int64 req_id = (size_t)message_id;
286 SharedMemoryMessageRequest* send_request = nullptr;
287 for( Integer i=0, n=m_send_requests.size(); i<n; ++i )
288 if (m_send_requests[i]->id()==req_id){
289 send_request = m_send_requests[i];
290 break;
291 }
292 if (!send_request)
293 ARCANE_FATAL("Can not find matching send request from MessageId");
294
295 tmr = _createReceiveRequest(request_id, dest, tag, buf);
296 TRACE_DEBUG("** ADD RECV FromMessageId queue={0} req_id={1} ORIG={2} DEST={3} tmr={4} size={5} serializer={6}",
297 m_name, request_id, m_rank, dest, *tmr, buf.memoryBuffer().size(), buf.serializer());
298 tmr->setMatchingSendRequest(send_request);
299 }
300 else
301 ARCANE_THROW(NotSupportedException,"Invalid 'MessageInfo'");
302
303 m_recv_requests.add(tmr);
304 return tmr;
305}
306
307/*---------------------------------------------------------------------------*/
308/*---------------------------------------------------------------------------*/
309
310SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
311addSend(Int64 request_id,const PointToPointMessageInfo& message,SendBufferInfo buf)
312{
313 MessageTag tag = message.tag();
314 if (tag.isNull())
315 ARCANE_THROW(ArgumentException,"null tag");
316 MessageRank orig = message.emiterRank();
317 auto* tmr = _createSendRequest(request_id,orig,tag,buf);
318 m_async_message_queue.push(tmr);
319 TRACE_DEBUG("** ADD SEND queue={0} ORIG={1} DEST={2} tag={3} size={4} tmr={5} serializer={6}",
320 m_name, orig, m_rank, tag, buf.memoryBuffer().size(), *tmr, buf.serializer());
321 return tmr;
322}
323
324/*---------------------------------------------------------------------------*/
325/*---------------------------------------------------------------------------*/
326
327void SharedMemoryMessageQueue::SubQueue::
328_checkRequestDone(SharedMemoryMessageRequest* tmr)
329{
330 if (tmr->isDone())
331 ARCANE_FATAL("Can not check already done request");
332
333 if (tmr->isRecv())
334 _checkRecvDone(tmr);
335 else
336 _checkSendDone(tmr);
337}
338
339/*---------------------------------------------------------------------------*/
340/*---------------------------------------------------------------------------*/
348{
349 if (tmr->isDone()){
350 if (tmr->isRecv())
351 _removeRequest(tmr,m_recv_requests);
352 else
353 _removeRequest(tmr,m_done_requests);
354 }
355}
356
357/*---------------------------------------------------------------------------*/
358/*---------------------------------------------------------------------------*/
359
360void SharedMemoryMessageQueue::SubQueue::
361_testOrWaitRequestAvailable(bool is_blocking)
362{
363 SharedMemoryMessageRequest* sq = nullptr;
364 if (is_blocking) {
365 sq = m_async_message_queue.pop();
366 }
367 else
368 sq = m_async_message_queue.tryPop();
369 if (sq) {
370 if (sq->orig() == m_rank) {
371 m_done_requests.add(sq);
372 }
373 else {
374 m_send_requests.add(sq);
375 }
376 }
377}
378
379/*---------------------------------------------------------------------------*/
380/*---------------------------------------------------------------------------*/
381
382void SharedMemoryMessageQueue::SubQueue::
383waitRequestAvailable()
384{
385 // Bloque tant qu'on n'a pas recu de message.
386 _testOrWaitRequestAvailable(true);
387}
388
389/*---------------------------------------------------------------------------*/
390/*---------------------------------------------------------------------------*/
391
392void SharedMemoryMessageQueue::SubQueue::
393checkRequestAvailable()
394{
395 _testOrWaitRequestAvailable(false);
396}
397
398/*---------------------------------------------------------------------------*/
399/*---------------------------------------------------------------------------*/
400
401void SharedMemoryMessageQueue::SubQueue::
402wait(SharedMemoryMessageRequest* tmr)
403{
404 if (tmr->queue()!=this)
405 ARCANE_FATAL("Bad queue");
406 TRACE_DEBUG("**** WAIT FOR_MESSAGE queue={0} tmr={1} nb_send={2} nb_done={3}",
407 m_name, *tmr, m_rank, m_send_requests.size(), m_done_requests.size());
408
409 while (!tmr->isDone()) {
410 _checkRequestDone(tmr);
411
412 if (!tmr->isDone()){
413 // Bloque tant qu'on n'a pas recu de message.
414 waitRequestAvailable();
415 }
416 }
417
418 _cleanupRequestIfDone(tmr);
419}
420
421/*---------------------------------------------------------------------------*/
422/*---------------------------------------------------------------------------*/
423
424void SharedMemoryMessageQueue::SubQueue::
425testRequest(SharedMemoryMessageRequest* tmr)
426{
427 if (tmr->queue()!=this)
428 ARCANE_FATAL("Bad queue");
429
430 _checkRequestDone(tmr);
431 _cleanupRequestIfDone(tmr);
432}
433
434/*---------------------------------------------------------------------------*/
435/*---------------------------------------------------------------------------*/
436
437void SharedMemoryMessageQueue::SubQueue::
438_removeRequest(SharedMemoryMessageRequest* tmr,Array<SharedMemoryMessageRequest*>& requests)
439{
440 // TODO traiter les requêtes invalides (tmr==nullptr);
441 for (Integer i = 0, n = requests.size(); i < n; ++i) {
442 SharedMemoryMessageRequest* tmr2 = requests[i];
443 if (tmr==tmr2){
444 requests.remove(i);
445 return;
446 }
447 }
448 ARCANE_FATAL("Can not remove request");
449}
450
451/*---------------------------------------------------------------------------*/
452/*---------------------------------------------------------------------------*/
453
454bool SharedMemoryMessageQueue::SubQueue::
455_checkSendDone(SharedMemoryMessageRequest* tmr_send)
456{
457 for( SharedMemoryMessageRequest* tmr : m_done_requests ){
458 if (tmr==tmr_send){
459 tmr_send->setDone(true);
460 return true;
461 }
462 }
463 return false;
464}
465
466/*---------------------------------------------------------------------------*/
467/*---------------------------------------------------------------------------*/
468/*
469 * \brief Vérifie qu'un message d'envoie correspond à la requête \a tmr_recv.
470 *
471 * Regarde si une requête dans la liste des messages envoyés correspond à
472 * \a tmr_recv. Cela est le cas si le couple origine/destination convient
473 * ou si la destination est A_NULL_RANK (ce qui correspond à MPI_ANY_SOURCE
474 * dans le cas MPI).
475 * Il est important de prendre les requêtes dans l'ordre d'arrivée pour se
476 * conformer à la norme MPI.
477 *
478 * \retval true si une requête correspondante a été trouvée.
479 * \retval false sinon.
480 */
481SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
482_getMatchingSendRequest(MessageRank recv_dest,MessageRank recv_orig,MessageTag tag)
483{
484 bool is_any_tag = tag.isNull();
485 bool is_any_dest = recv_dest.isNull() || recv_dest.isAnySource();
486 if (recv_dest.isNull() && !m_is_allow_null_rank_for_any_source)
487 ARCANE_FATAL("Can not use probe() with null rank. Use MessageRank::anySourceRank() instead");
488 for( Integer j=0, n=m_send_requests.size(); j<n; ++j ){
489 SharedMemoryMessageRequest* tmr_send = m_send_requests[j];
490 TRACE_DEBUG("CHECK RECV DONE queue={0} tmr_send={1} recv_dest={2}"
491 " recv_orig={3} request={4}/{5}",
492 m_name, *tmr_send, recv_dest, recv_orig,
493 j, n);
494 if (recv_orig == tmr_send->dest()) {
495 bool is_rank_ok = (recv_dest == tmr_send->orig()) || (is_any_dest && m_rank == recv_orig);
496 bool is_tag_ok = (is_any_tag || tmr_send->tag() == tag);
497 if (is_rank_ok && is_tag_ok) {
498 TRACE_DEBUG("CHECK RECV DONE found: queue={0} tmr_send={1}", m_name, *tmr_send);
499 return tmr_send;
500 }
501 }
502 }
503 return nullptr;
504}
505
506/*---------------------------------------------------------------------------*/
507/*---------------------------------------------------------------------------*/
508
509bool SharedMemoryMessageQueue::SubQueue::
510_checkRecvDone(SharedMemoryMessageRequest* tmr_recv)
511{
512 // Regarde si le send est déjà associé à notre requête. C'est le cas
513 // si on a utiliser un appel à probe().
514 auto* tmr_send = tmr_recv->matchingSendRequest();
515 if (!tmr_send)
516 tmr_send = _getMatchingSendRequest(tmr_recv->dest(),tmr_recv->orig(),tmr_recv->tag());
517 if (tmr_send){
518 tmr_recv->setSource(tmr_send->orig());
519 tmr_recv->copyFromSender(tmr_send);
520 tmr_recv->setDone(true);
521 tmr_send->queue()->m_async_message_queue.push(tmr_send);
522 _removeRequest(tmr_send,m_send_requests);
523 return true;
524 }
525 return false;
526}
527
528/*---------------------------------------------------------------------------*/
529/*---------------------------------------------------------------------------*/
530
531void SharedMemoryMessageQueue::SubQueue::
532waitSome(ArrayView<Request> requests,ArrayView<bool> requests_done,
533 bool is_non_blocking)
534{
535 Integer nb_request = requests.size();
536 requests_done.fill(false);
537 bool one_request_done = false;
538 TRACE_DEBUG("** WAIT SOME REQUEST queue={0} rank={1} nb_request={2}\n", m_name, m_rank, nb_request);
539 while (!one_request_done) {
540 if (is_non_blocking)
541 checkRequestAvailable();
542 bool has_valid_request = false;
543 for( Integer i=0; i<nb_request; ++i ){
544 Request request = requests[i];
545 if (!request.isValid())
546 continue;
547 SharedMemoryMessageRequest* tmr = requests[i];
548 if (!tmr)
549 continue;
550 this->testRequest(tmr);
551 if (tmr->isDone()){
552 one_request_done = true;
553 requests_done[i] = true;
554 tmr->destroy();
555 if (requests[i].hasSubRequest())
556 ARCANE_THROW(NotImplementedException,"handling of sub requests");
557 requests[i].reset();
558 }
559 has_valid_request = true;
560 }
561 // Si au moins une requête est terminée, sort de la boucle.
562 if (one_request_done)
563 break;
564 // Si ici, aucune requête n'a abouti. On bloque jusqu'à ce qu'il y ait
565 // un message dans la file sauf s'il n'y a aucune requête valide
566 // (Ceci est possible si toutes les requêtes de la liste sont des
567 // requêtes nulles).
568 if (!has_valid_request)
569 break;
570 // En mode non bloquant, on a déjà testé en début de boucle si
571 // une requête est disponible. Si on est ici on peut sortir directement
572 // sinon on va bloquer.
573 if (is_non_blocking)
574 break;
575 TRACE_DEBUG("** WAIT REQUEST AVAILABLE rank={0}",m_rank);
576 waitRequestAvailable();
577 }
578}
579
580/*---------------------------------------------------------------------------*/
581/*---------------------------------------------------------------------------*/
582
583MP::MessageId SharedMemoryMessageQueue::SubQueue::
584probe(const MP::PointToPointMessageInfo& message)
585{
586 TRACE_DEBUG("Probe rank={0} nb_send={1} nb_receive={2} queue={3} is_valid={4}",
587 m_rank,m_send_requests.size(),m_recv_requests.size(),this,message.isValid());
588 if (!message.isValid())
589 return MessageId();
590
591 // Il faut avoir initialisé le message avec un couple (rang/tag).
592 if (!message.isRankTag())
593 ARCCORE_FATAL("Invalid message_info: message.isRankTag() is false");
594
595 MessageRank rank = message.destinationRank();
596 MessageTag tag = message.tag();
597 bool is_blocking = message.isBlocking();
598 if (is_blocking)
599 ARCANE_THROW(NotImplementedException,"blocking probe");
600
601 // TODO: regarder pour mettre une sécurité anti-bouclage
602 // TODO: il faudrait vérifier que si on appelle deux fois cette
603 // méthode avec les mêmes informations on ne récupère pas le même message.
604 // Lorsque ce sera aussi le cas il faudra modifier legacyProbe() en
605 // conséquence.
606 for(;;){
607 _testOrWaitRequestAvailable(is_blocking);
608 auto* req = _getMatchingSendRequest(rank, m_rank, tag);
609 if (req) {
610 // TODO: Vérifier que la requête est bien avec un buffer et pas un 'ISerializer'.
611 Int64 send_size = req->sendBufferInfo().memoryBuffer().size();
612 MessageId::SourceInfo si(req->orig(),req->tag(),send_size);
613 return MessageId(si,(size_t)req->id());
614 }
615 if (!is_blocking)
616 // En non bloquant, sort de la boucle même si on n'a pas de requête.
617 break;
618 }
619 return {};
620}
621
622/*---------------------------------------------------------------------------*/
623/*---------------------------------------------------------------------------*/
624
625MP::MessageSourceInfo SharedMemoryMessageQueue::SubQueue::
626legacyProbe(const MP::PointToPointMessageInfo& message)
627{
628 // Fait un probe normal mais ne conserve pas l'information du message.
629 // NOTE: cela fonctionne car probe() peut retourner plusieurs fois le même
630 // message. Lorsque ce ne sera plus le cas il faudra modifier cela.
631 MP::MessageId message_id = probe(message);
632 if (message_id.isValid())
633 return message_id.sourceInfo();
634 return {};
635}
636
637/*---------------------------------------------------------------------------*/
638/*---------------------------------------------------------------------------*/
639
640/*---------------------------------------------------------------------------*/
641/*---------------------------------------------------------------------------*/
642
643SharedMemoryMessageQueue::
644~SharedMemoryMessageQueue()
645{
646 for( SubQueue* sq : m_sub_queues )
647 delete sq;
648}
649
650/*---------------------------------------------------------------------------*/
651/*---------------------------------------------------------------------------*/
652
653void SharedMemoryMessageQueue::
654init(Integer nb_thread)
655{
656 m_atomic_request_id = 1;
657 m_nb_thread = nb_thread;
658 Integer nb_queue = nb_thread;
659 m_sub_queues.resize(nb_queue);
660 for( Integer i=0; i<nb_queue; ++i ){
661 m_sub_queues[i] = new SubQueue(this,MessageRank(i));
662 }
663}
664
665/*---------------------------------------------------------------------------*/
666/*---------------------------------------------------------------------------*/
667
668SharedMemoryMessageQueue::SubQueue* SharedMemoryMessageQueue::
669_getSourceSubQueue(const MP::PointToPointMessageInfo& message)
670{
671 MessageRank orig = message.emiterRank();
672 if (orig.isNull())
673 ARCANE_THROW(ArgumentException,"null message.sourceRank()");
674 return _getSubQueue(orig);
675}
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
679
680SharedMemoryMessageQueue::SubQueue* SharedMemoryMessageQueue::
681_getDestinationSubQueue(const MP::PointToPointMessageInfo& message)
682{
683 MessageRank dest = message.destinationRank();
684 if (dest.isNull())
685 ARCANE_THROW(ArgumentException,"null message.destinationRank()");
686 return _getSubQueue(dest);
687}
688
689/*---------------------------------------------------------------------------*/
690/*---------------------------------------------------------------------------*/
691
692void SharedMemoryMessageQueue::
693waitAll(Int32 calling_rank, ArrayView<Request> requests)
694{
695 Integer nb_request = requests.size();
696 // Pour ne pas que cela bloque, il faut que les requêtes soient faites
697 // par ordre croissant des files, et les 'receive' D'ABORD !!
698 UniqueArray<SharedMemoryMessageRequest*> sorted_requests(nb_request);
699 for (Integer i = 0; i < nb_request; ++i) {
700 sorted_requests[i] = requests[i];
701 }
702 std::sort(std::begin(sorted_requests),std::end(sorted_requests),
703 SharedMemoryMessageRequest::SortFunctor(m_nb_thread));
704
705#if 0
706 for( Integer i=0; i<nb_request; ++i ){
707 SharedMemoryMessageRequest* tmr = sorted_requests[i];
708 cout << String::format("** WAIT FOR REQUEST tmr={0}\n",tmr);
709 }
710#endif
711 auto own_queue = _getSubQueue(MessageRank(calling_rank));
712 int method = 0;
713 if (method == 0) {
714 for (Integer i = 0; i < nb_request; ++i) {
715 SharedMemoryMessageRequest* tmr = sorted_requests[i];
716 if (tmr) {
717 SubQueue* sub_queue = tmr->queue();
718 if (own_queue != sub_queue)
719 ARCANE_FATAL("Bad queue onw={0} sub={1}", own_queue->name(), sub_queue->name());
720 sub_queue->wait(tmr);
721 tmr->destroy();
722 }
723 }
724 }
725 else if (method == 1) {
726 Int32 nb_done = 0;
727 while (nb_done != nb_request) {
728 for (Integer i = 0; i < nb_request; ++i) {
729 SharedMemoryMessageRequest* tmr = sorted_requests[i];
730 if (!tmr)
731 continue;
732 SubQueue* sub_queue = tmr->queue();
733 if (own_queue != sub_queue)
734 ARCANE_FATAL("Bad queue onw={0} sub={1}", own_queue->name(), sub_queue->name());
735 sub_queue->testRequest(tmr);
736 if (tmr->isDone()) {
737 tmr->destroy();
738 sorted_requests[i] = nullptr;
739 ++nb_done;
740 }
741 if (nb_done == nb_request)
742 break;
743 }
744 if (nb_done != nb_request) {
745 own_queue->waitRequestAvailable();
746 }
747 }
748 }
749 for (Integer i = 0; i < nb_request; ++i) {
750 if (requests[i].hasSubRequest())
751 ARCANE_THROW(NotImplementedException,"handling of sub requests");
752 requests[i].reset();
753 }
754}
755
756/*---------------------------------------------------------------------------*/
757/*---------------------------------------------------------------------------*/
758
759void SharedMemoryMessageQueue::
760waitSome(Int32 rank,ArrayView<Parallel::Request> requests,
761 ArrayView<bool> requests_done,bool is_non_blocking)
762{
763 requests_done.fill(false);
764 auto sub_queue = _getSubQueue(MessageRank(rank));
765 sub_queue->waitSome(requests,requests_done,is_non_blocking);
766}
767
768/*---------------------------------------------------------------------------*/
769/*---------------------------------------------------------------------------*/
770
771auto SharedMemoryMessageQueue::
772addReceive(const PointToPointMessageInfo& message,ReceiveBufferInfo buf) -> Request
773{
774 auto* sq = _getSourceSubQueue(message);
775 return _request(sq->addReceive(_getNextRequestId(),message,buf));
776}
777
778/*---------------------------------------------------------------------------*/
779/*---------------------------------------------------------------------------*/
780
781auto SharedMemoryMessageQueue::
782addSend(const PointToPointMessageInfo& message,SendBufferInfo buf) -> Request
783{
784 auto* sq = _getDestinationSubQueue(message);
785 return _request(sq->addSend(_getNextRequestId(),message,buf));
786}
787
788/*---------------------------------------------------------------------------*/
789/*---------------------------------------------------------------------------*/
790
791auto SharedMemoryMessageQueue::
792probe(const MP::PointToPointMessageInfo& message) -> MessageId
793{
794 auto* sq = _getSourceSubQueue(message);
795 return sq->probe(message);
796}
797
798/*---------------------------------------------------------------------------*/
799/*---------------------------------------------------------------------------*/
800
801auto SharedMemoryMessageQueue::
802legacyProbe(const MP::PointToPointMessageInfo& message) -> MessageSourceInfo
803{
804 auto* sq = _getSourceSubQueue(message);
805 return sq->legacyProbe(message);
806}
807
808/*---------------------------------------------------------------------------*/
809/*---------------------------------------------------------------------------*/
810
811void SharedMemoryMessageQueue::
812setTraceMng(Int32 rank,ITraceMng* tm)
813{
814 _getSubQueue(MessageRank(rank))->setTraceMng(tm);
815}
816
817/*---------------------------------------------------------------------------*/
818/*---------------------------------------------------------------------------*/
819
820auto SharedMemoryMessageQueue::
821_request(SharedMemoryMessageRequest* tmr) -> Request
822{
823 return Request(0,this,tmr);
824}
825
826/*---------------------------------------------------------------------------*/
827/*---------------------------------------------------------------------------*/
828
829const String& SharedMemoryMessageRequest::
830queueName() const
831{
832 return m_queue->name();
833}
834
835/*---------------------------------------------------------------------------*/
836/*---------------------------------------------------------------------------*/
837
838} // End namespace Arcane::MessagePassing
839
840/*---------------------------------------------------------------------------*/
841/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Vue modifiable d'un tableau d'un type T.
Tableau d'items de types quelconques.
Vue constante sur une zone mémoire contigue contenant des éléments de taille fixe.
Classe template pour convertir un type.
virtual void copy(const ISerializer *from)=0
Copie les données de from dans cette instance.
Interface du gestionnaire de traces.
static void genericCopy(ConstMemoryView from, MutableMemoryView to)
Copie générique utilisant platform::getDataMemoryRessourceMng().
File asynchrone permettant d'échanger des informations entre threads.
Definition IAsyncQueue.h:32
Informations pour envoyer/recevoir un message point à point.
Informations des buffers de réception.
File pour les messages d'un rang en mémoire partagée.
void _cleanupRequestIfDone(SharedMemoryMessageRequest *tmr)
Nettoyage de la requête tmr si elle est finie.
SharedMemoryMessageRequest(SubQueue *queue, Int64 request_id, MessageRank orig, MessageRank dest, MessageTag tag, ReceiveBufferInfo buf)
Créé une requête d'envoie.
void copyFromSender(SharedMemoryMessageRequest *sender)
Copie dans le message de réception les informations du message d'envoi.
Vue modifiable sur une zone mémoire contigue contenant des éléments de taille fixe.
Chaîne de caractères unicode.
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.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
std::int32_t Int32
Type entier signé sur 32 bits.