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"
22#include "arccore/common/internal/MemoryResourceMng.h"
24#include "arcane/parallel/thread/SharedMemoryMessageQueue.h"
25#include "arcane/parallel/thread/IAsyncQueue.h"
27#include "arcane/core/ISerializeMessage.h"
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();\
60 const ISerializer* send_serializer = send_info.serializer();
61 ISerializer* receive_serializer = receive_info.serializer();
62 if (receive_serializer){
64 ARCANE_FATAL(
"No send serializer for receive serializer");
65 receive_serializer->
copy(send_serializer);
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);
83void SharedMemoryMessageRequest::
88 m_is_destroyed =
true;
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()
117class RequestAsyncQueue
121 : m_async_queue(IAsyncQueue::createQueue()){}
124 delete m_async_queue;
129 m_async_queue->push(v);
166 SubQueue(SharedMemoryMessageQueue* master_queue,
MessageRank rank);
171 void setTraceMng(
ITraceMng* tm) { m_trace_mng = tm; }
172 ITraceMng* traceMng()
const {
return m_trace_mng; }
175 void waitRequestAvailable();
176 void checkRequestAvailable();
180 void setName(
const String& name) { m_name = name; }
181 const String& name()
const {
return m_name; }
192 SharedMemoryMessageQueue* m_master_queue =
nullptr;
199 bool m_is_debug =
false;
200 bool m_is_allow_null_rank_for_any_source =
true;
212 void _testOrWaitRequestAvailable(
bool is_blocking);
224SharedMemoryMessageQueue::SubQueue::
225SubQueue(SharedMemoryMessageQueue* master_queue,
MessageRank rank)
226: m_master_queue(master_queue)
230 m_is_allow_null_rank_for_any_source = v.value() != 0;
231 m_name = String::format(
"queue{0}", rank);
233 m_is_debug = (v.value() != 0);
257 SubQueue* queue = m_master_queue->_getSubQueue(orig);
265SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
266addReceive(Int64 request_id,
const PointToPointMessageInfo& message,ReceiveBufferInfo buf)
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());
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();
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];
293 ARCANE_FATAL(
"Can not find matching send request from MessageId");
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);
301 ARCANE_THROW(NotSupportedException,
"Invalid 'MessageInfo'");
303 m_recv_requests.add(tmr);
310SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
311addSend(
Int64 request_id,
const PointToPointMessageInfo& message,SendBufferInfo buf)
313 MessageTag tag = message.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());
327void SharedMemoryMessageQueue::SubQueue::
328_checkRequestDone(SharedMemoryMessageRequest* tmr)
351 _removeRequest(tmr,m_recv_requests);
353 _removeRequest(tmr,m_done_requests);
360void SharedMemoryMessageQueue::SubQueue::
361_testOrWaitRequestAvailable(
bool is_blocking)
365 sq = m_async_message_queue.pop();
368 sq = m_async_message_queue.tryPop();
370 if (sq->orig() == m_rank) {
371 m_done_requests.add(sq);
374 m_send_requests.add(sq);
382void SharedMemoryMessageQueue::SubQueue::
383waitRequestAvailable()
386 _testOrWaitRequestAvailable(
true);
392void SharedMemoryMessageQueue::SubQueue::
393checkRequestAvailable()
395 _testOrWaitRequestAvailable(
false);
401void SharedMemoryMessageQueue::SubQueue::
402wait(SharedMemoryMessageRequest* tmr)
404 if (tmr->queue()!=
this)
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());
409 while (!tmr->isDone()) {
410 _checkRequestDone(tmr);
414 waitRequestAvailable();
418 _cleanupRequestIfDone(tmr);
424void SharedMemoryMessageQueue::SubQueue::
425testRequest(SharedMemoryMessageRequest* tmr)
427 if (tmr->queue()!=
this)
430 _checkRequestDone(tmr);
431 _cleanupRequestIfDone(tmr);
437void SharedMemoryMessageQueue::SubQueue::
438_removeRequest(SharedMemoryMessageRequest* tmr,Array<SharedMemoryMessageRequest*>& requests)
441 for (
Integer i = 0, n = requests.size(); i < n; ++i) {
442 SharedMemoryMessageRequest* tmr2 = requests[i];
454bool SharedMemoryMessageQueue::SubQueue::
455_checkSendDone(SharedMemoryMessageRequest* tmr_send)
457 for( SharedMemoryMessageRequest* tmr : m_done_requests ){
459 tmr_send->setDone(
true);
481SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
482_getMatchingSendRequest(MessageRank recv_dest,MessageRank recv_orig,MessageTag tag)
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,
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);
509bool SharedMemoryMessageQueue::SubQueue::
510_checkRecvDone(SharedMemoryMessageRequest* tmr_recv)
514 auto* tmr_send = tmr_recv->matchingSendRequest();
516 tmr_send = _getMatchingSendRequest(tmr_recv->dest(),tmr_recv->orig(),tmr_recv->tag());
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);
531void SharedMemoryMessageQueue::SubQueue::
532waitSome(ArrayView<Request> requests,ArrayView<bool> requests_done,
533 bool is_non_blocking)
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) {
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())
547 SharedMemoryMessageRequest* tmr = requests[i];
550 this->testRequest(tmr);
552 one_request_done =
true;
553 requests_done[i] =
true;
555 if (requests[i].hasSubRequest())
556 ARCANE_THROW(NotImplementedException,
"handling of sub requests");
559 has_valid_request =
true;
562 if (one_request_done)
568 if (!has_valid_request)
575 TRACE_DEBUG(
"** WAIT REQUEST AVAILABLE rank={0}",m_rank);
576 waitRequestAvailable();
583MP::MessageId SharedMemoryMessageQueue::SubQueue::
584probe(
const MP::PointToPointMessageInfo& message)
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())
592 if (!message.isRankTag())
593 ARCCORE_FATAL(
"Invalid message_info: message.isRankTag() is false");
595 MessageRank rank = message.destinationRank();
596 MessageTag tag = message.tag();
597 bool is_blocking = message.isBlocking();
607 _testOrWaitRequestAvailable(is_blocking);
608 auto* req = _getMatchingSendRequest(rank, m_rank, tag);
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());
625MP::MessageSourceInfo SharedMemoryMessageQueue::SubQueue::
626legacyProbe(
const MP::PointToPointMessageInfo& message)
631 MP::MessageId message_id = probe(message);
632 if (message_id.isValid())
633 return message_id.sourceInfo();
643SharedMemoryMessageQueue::
644~SharedMemoryMessageQueue()
653void SharedMemoryMessageQueue::
656 m_atomic_request_id = 1;
657 m_nb_thread = 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));
668SharedMemoryMessageQueue::SubQueue* SharedMemoryMessageQueue::
669_getSourceSubQueue(
const MP::PointToPointMessageInfo& message)
671 MessageRank orig = message.emiterRank();
673 ARCANE_THROW(ArgumentException,
"null message.sourceRank()");
674 return _getSubQueue(orig);
680SharedMemoryMessageQueue::SubQueue* SharedMemoryMessageQueue::
681_getDestinationSubQueue(
const MP::PointToPointMessageInfo& message)
683 MessageRank dest = message.destinationRank();
685 ARCANE_THROW(ArgumentException,
"null message.destinationRank()");
686 return _getSubQueue(dest);
692void SharedMemoryMessageQueue::
693waitAll(
Int32 calling_rank, ArrayView<Request> requests)
695 Integer nb_request = requests.size();
698 UniqueArray<SharedMemoryMessageRequest*> sorted_requests(nb_request);
699 for (
Integer i = 0; i < nb_request; ++i) {
700 sorted_requests[i] = requests[i];
702 std::sort(std::begin(sorted_requests),std::end(sorted_requests),
703 SharedMemoryMessageRequest::SortFunctor(m_nb_thread));
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);
711 auto own_queue = _getSubQueue(MessageRank(calling_rank));
714 for (
Integer i = 0; i < nb_request; ++i) {
715 SharedMemoryMessageRequest* tmr = sorted_requests[i];
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);
725 else if (method == 1) {
727 while (nb_done != nb_request) {
728 for (
Integer i = 0; i < nb_request; ++i) {
729 SharedMemoryMessageRequest* tmr = sorted_requests[i];
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);
738 sorted_requests[i] =
nullptr;
741 if (nb_done == nb_request)
744 if (nb_done != nb_request) {
745 own_queue->waitRequestAvailable();
749 for (
Integer i = 0; i < nb_request; ++i) {
750 if (requests[i].hasSubRequest())
751 ARCANE_THROW(NotImplementedException,
"handling of sub requests");
759void SharedMemoryMessageQueue::
760waitSome(
Int32 rank,ArrayView<Parallel::Request> requests,
761 ArrayView<bool> requests_done,
bool is_non_blocking)
763 requests_done.fill(
false);
764 auto sub_queue = _getSubQueue(MessageRank(rank));
765 sub_queue->waitSome(requests,requests_done,is_non_blocking);
771auto SharedMemoryMessageQueue::
772addReceive(
const PointToPointMessageInfo& message,ReceiveBufferInfo buf) -> Request
774 auto* sq = _getSourceSubQueue(message);
775 return _request(sq->addReceive(_getNextRequestId(),message,buf));
781auto SharedMemoryMessageQueue::
782addSend(
const PointToPointMessageInfo& message,SendBufferInfo buf) -> Request
784 auto* sq = _getDestinationSubQueue(message);
785 return _request(sq->addSend(_getNextRequestId(),message,buf));
791auto SharedMemoryMessageQueue::
792probe(
const MP::PointToPointMessageInfo& message) -> MessageId
794 auto* sq = _getSourceSubQueue(message);
795 return sq->probe(message);
801auto SharedMemoryMessageQueue::
802legacyProbe(
const MP::PointToPointMessageInfo& message) -> MessageSourceInfo
804 auto* sq = _getSourceSubQueue(message);
805 return sq->legacyProbe(message);
811void SharedMemoryMessageQueue::
812setTraceMng(
Int32 rank,ITraceMng* tm)
814 _getSubQueue(MessageRank(rank))->setTraceMng(tm);
820auto SharedMemoryMessageQueue::
821_request(SharedMemoryMessageRequest* tmr) -> Request
823 return Request(0,
this,tmr);
829const String& SharedMemoryMessageRequest::
832 return m_queue->name();
#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.
Interface d'un sérialiseur.
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.
Informations pour envoyer/recevoir un message point à point.
Informations des buffers de réception.
Informations des buffers d'envoie.
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.
Message entre SharedMemoryMessageQueue.
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.