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(); \
59 const ISerializer* send_serializer = send_info.serializer();
60 ISerializer* receive_serializer = receive_info.serializer();
61 if (receive_serializer) {
63 ARCANE_FATAL(
"No send serializer for receive serializer");
64 receive_serializer->
copy(send_serializer);
68 ByteConstSpan send_span = send_info.memoryBuffer();
69 ByteSpan receive_span = receive_info.memoryBuffer();
70 Int64 send_size = send_span.size();
71 Int64 receive_size = receive_span.size();
72 if (send_size > receive_size)
73 ARCANE_FATAL(
"Not enough memory for receiving message receive={0} send={1}",
74 receive_size, send_size);
82void SharedMemoryMessageRequest::
87 m_is_destroyed =
true;
98 o <<
"(id=" << v.id() <<
" queue=" << v.queueName()
99 <<
" orig=" << v.orig() <<
" dest=" << v.dest()
100 <<
" tag=" << v.tag() <<
" is_recv?=" << v.isRecv()
101 <<
" is_done=?" << v.isDone()
102 <<
" send_size=" << v.m_send_buffer_info.memoryBuffer().size()
103 <<
" receive_size=" << v.m_receive_buffer_info.memoryBuffer().size()
115class RequestAsyncQueue
120 : m_async_queue(IAsyncQueue::createQueue())
124 delete m_async_queue;
131 m_async_queue->push(v);
168 SubQueue(SharedMemoryMessageQueue* master_queue,
MessageRank rank);
173 void setTraceMng(
ITraceMng* tm) { m_trace_mng = tm; }
174 ITraceMng* traceMng()
const {
return m_trace_mng; }
177 void waitRequestAvailable();
178 void checkRequestAvailable();
182 void setName(
const String& name) { m_name = name; }
183 const String& name()
const {
return m_name; }
194 SharedMemoryMessageQueue* m_master_queue =
nullptr;
201 bool m_is_debug =
false;
202 bool m_is_allow_null_rank_for_any_source =
true;
214 void _testOrWaitRequestAvailable(
bool is_blocking);
226SharedMemoryMessageQueue::SubQueue::
227SubQueue(SharedMemoryMessageQueue* master_queue,
MessageRank rank)
228: m_master_queue(master_queue)
232 m_is_allow_null_rank_for_any_source = v.value() != 0;
233 m_name = String::format(
"queue{0}", rank);
235 m_is_debug = (v.value() != 0);
259 SubQueue* queue = m_master_queue->_getSubQueue(orig);
267SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
268addReceive(Int64 request_id,
const PointToPointMessageInfo& message, ReceiveBufferInfo buf)
270 SharedMemoryMessageRequest* tmr =
nullptr;
271 if (message.isRankTag()) {
272 MessageTag tag = message.tag();
273 MessageRank dest = message.destinationRank();
274 tmr = _createReceiveRequest(request_id, dest, tag, buf);
275 TRACE_DEBUG(
"** ADD RECV queue={0} id={1} ORIG={2} DEST={3} tmr={4} size={5} serializer={6}",
276 m_name, request_id, m_rank, dest, tag, *tmr, buf.memoryBuffer().size(), buf.serializer());
278 else if (message.isMessageId()) {
279 MessageId message_id = message.messageId();
280 MessageId::SourceInfo si = message_id.sourceInfo();
281 MessageRank dest = si.rank();
282 MessageTag tag = si.tag();
287 Int64 req_id = (size_t)message_id;
288 SharedMemoryMessageRequest* send_request =
nullptr;
289 for (
Integer i = 0, n = m_send_requests.size(); i < n; ++i)
290 if (m_send_requests[i]->
id() == req_id) {
291 send_request = m_send_requests[i];
295 ARCANE_FATAL(
"Can not find matching send request from MessageId");
297 tmr = _createReceiveRequest(request_id, dest, tag, buf);
298 TRACE_DEBUG(
"** ADD RECV FromMessageId queue={0} req_id={1} ORIG={2} DEST={3} tmr={4} size={5} serializer={6}",
299 m_name, request_id, m_rank, dest, *tmr, buf.memoryBuffer().size(), buf.serializer());
300 tmr->setMatchingSendRequest(send_request);
303 ARCANE_THROW(NotSupportedException,
"Invalid 'MessageInfo'");
305 m_recv_requests.add(tmr);
312SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
313addSend(
Int64 request_id,
const PointToPointMessageInfo& message, SendBufferInfo buf)
315 MessageTag tag = message.tag();
318 MessageRank orig = message.emiterRank();
319 auto* tmr = _createSendRequest(request_id, orig, tag, buf);
320 m_async_message_queue.push(tmr);
321 TRACE_DEBUG(
"** ADD SEND queue={0} ORIG={1} DEST={2} tag={3} size={4} tmr={5} serializer={6}",
322 m_name, orig, m_rank, tag, buf.memoryBuffer().size(), *tmr, buf.serializer());
329void SharedMemoryMessageQueue::SubQueue::
330_checkRequestDone(SharedMemoryMessageRequest* tmr)
354 _removeRequest(tmr, m_recv_requests);
356 _removeRequest(tmr, m_done_requests);
363void SharedMemoryMessageQueue::SubQueue::
364_testOrWaitRequestAvailable(
bool is_blocking)
368 sq = m_async_message_queue.pop();
371 sq = m_async_message_queue.tryPop();
373 if (sq->orig() == m_rank) {
374 m_done_requests.add(sq);
377 m_send_requests.add(sq);
385void SharedMemoryMessageQueue::SubQueue::
386waitRequestAvailable()
389 _testOrWaitRequestAvailable(
true);
395void SharedMemoryMessageQueue::SubQueue::
396checkRequestAvailable()
398 _testOrWaitRequestAvailable(
false);
404void SharedMemoryMessageQueue::SubQueue::
405wait(SharedMemoryMessageRequest* tmr)
407 if (tmr->queue() !=
this)
409 TRACE_DEBUG(
"**** WAIT FOR_MESSAGE queue={0} tmr={1} nb_send={2} nb_done={3}",
410 m_name, *tmr, m_rank, m_send_requests.size(), m_done_requests.size());
412 while (!tmr->isDone()) {
413 _checkRequestDone(tmr);
415 if (!tmr->isDone()) {
417 waitRequestAvailable();
421 _cleanupRequestIfDone(tmr);
427void SharedMemoryMessageQueue::SubQueue::
428testRequest(SharedMemoryMessageRequest* tmr)
430 if (tmr->queue() !=
this)
433 _checkRequestDone(tmr);
434 _cleanupRequestIfDone(tmr);
440void SharedMemoryMessageQueue::SubQueue::
441_removeRequest(SharedMemoryMessageRequest* tmr, Array<SharedMemoryMessageRequest*>& requests)
444 for (
Integer i = 0, n = requests.size(); i < n; ++i) {
445 SharedMemoryMessageRequest* tmr2 = requests[i];
457bool SharedMemoryMessageQueue::SubQueue::
458_checkSendDone(SharedMemoryMessageRequest* tmr_send)
460 for (SharedMemoryMessageRequest* tmr : m_done_requests) {
461 if (tmr == tmr_send) {
462 tmr_send->setDone(
true);
483SharedMemoryMessageRequest* SharedMemoryMessageQueue::SubQueue::
484_getMatchingSendRequest(MessageRank recv_dest, MessageRank recv_orig, MessageTag tag)
486 bool is_any_tag = tag.isNull();
487 bool is_any_dest = recv_dest.isNull() || recv_dest.isAnySource();
488 if (recv_dest.isNull() && !m_is_allow_null_rank_for_any_source)
489 ARCANE_FATAL(
"Can not use probe() with null rank. Use MessageRank::anySourceRank() instead");
490 for (
Integer j = 0, n = m_send_requests.size(); j < n; ++j) {
491 SharedMemoryMessageRequest* tmr_send = m_send_requests[j];
492 TRACE_DEBUG(
"CHECK RECV DONE queue={0} tmr_send={1} recv_dest={2}"
493 " recv_orig={3} request={4}/{5}",
494 m_name, *tmr_send, recv_dest, recv_orig,
496 if (recv_orig == tmr_send->dest()) {
497 bool is_rank_ok = (recv_dest == tmr_send->orig()) || (is_any_dest && m_rank == recv_orig);
498 bool is_tag_ok = (is_any_tag || tmr_send->tag() == tag);
499 if (is_rank_ok && is_tag_ok) {
500 TRACE_DEBUG(
"CHECK RECV DONE found: queue={0} tmr_send={1}", m_name, *tmr_send);
511bool SharedMemoryMessageQueue::SubQueue::
512_checkRecvDone(SharedMemoryMessageRequest* tmr_recv)
516 auto* tmr_send = tmr_recv->matchingSendRequest();
518 tmr_send = _getMatchingSendRequest(tmr_recv->dest(), tmr_recv->orig(), tmr_recv->tag());
520 tmr_recv->setSource(tmr_send->orig());
521 tmr_recv->copyFromSender(tmr_send);
522 tmr_recv->setDone(
true);
523 tmr_send->queue()->m_async_message_queue.push(tmr_send);
524 _removeRequest(tmr_send, m_send_requests);
533void SharedMemoryMessageQueue::SubQueue::
534waitSome(ArrayView<Request> requests, ArrayView<bool> requests_done,
535 bool is_non_blocking)
537 Integer nb_request = requests.size();
538 requests_done.fill(
false);
539 bool one_request_done =
false;
540 TRACE_DEBUG(
"** WAIT SOME REQUEST queue={0} rank={1} nb_request={2}\n", m_name, m_rank, nb_request);
541 while (!one_request_done) {
543 checkRequestAvailable();
544 bool has_valid_request =
false;
545 for (
Integer i = 0; i < nb_request; ++i) {
546 Request request = requests[i];
547 if (!request.isValid())
549 SharedMemoryMessageRequest* tmr = requests[i];
552 this->testRequest(tmr);
554 one_request_done =
true;
555 requests_done[i] =
true;
557 if (requests[i].hasSubRequest())
558 ARCANE_THROW(NotImplementedException,
"handling of sub requests");
561 has_valid_request =
true;
564 if (one_request_done)
569 if (!has_valid_request)
576 TRACE_DEBUG(
"** WAIT REQUEST AVAILABLE rank={0}", m_rank);
577 waitRequestAvailable();
584MP::MessageId SharedMemoryMessageQueue::SubQueue::
585probe(
const MP::PointToPointMessageInfo& message)
587 TRACE_DEBUG(
"Probe rank={0} nb_send={1} nb_receive={2} queue={3} is_valid={4}",
588 m_rank, m_send_requests.size(), m_recv_requests.size(),
this, message.isValid());
589 if (!message.isValid())
593 if (!message.isRankTag())
594 ARCCORE_FATAL(
"Invalid message_info: message.isRankTag() is false");
596 MessageRank rank = message.destinationRank();
597 MessageTag tag = message.tag();
598 bool is_blocking = message.isBlocking();
600 ARCANE_THROW(NotImplementedException,
"blocking probe");
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 for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ARCCORE_FATAL(...)
Macro throwing a FatalErrorException.
Modifiable view of an array of type T.
Base class for 1D data vectors.
Constant view on a contiguous memory region containing fixed-size elements.
Template class for converting a type.
virtual void copy(const ISerializer *from)=0
Copies the data from from into this instance.
static void genericCopy(ConstMemoryView from, MutableMemoryView to)
Generic copy using platform::getDataMemoryRessourceMng().
Asynchronous queue allowing the exchange of information between threads.
Information for sending/receiving a point-to-point message.
Receive buffer information.
File for messages from a rank in shared memory.
void _cleanupRequestIfDone(SharedMemoryMessageRequest *tmr)
Cleans up the request tmr if it is finished.
Message within SharedMemoryMessageQueue.
SharedMemoryMessageRequest(SubQueue *queue, Int64 request_id, MessageRank orig, MessageRank dest, MessageTag tag, ReceiveBufferInfo buf)
Create a send request.
void copyFromSender(SharedMemoryMessageRequest *sender)
Copies the sender message information into the receive message.
Mutable view on a contiguous memory region containing fixed-size elements.
Unicode character string.
1D data vector with value semantics (STL style).
Declarations of types and methods used by message exchange mechanisms.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
std::int32_t Int32
Signed integer type of 32 bits.