14#include "arccore/message_passing_mpi/internal/MpiAdapter.h"
16#include "arccore/trace/ITraceMng.h"
18#include "arccore/collections/Array.h"
20#include "arccore/message_passing/Request.h"
21#include "arccore/message_passing/IStat.h"
22#include "arccore/message_passing/internal/SubRequestCompletionInfo.h"
24#include "arccore/base/IStackTraceService.h"
25#include "arccore/base/TimeoutException.h"
26#include "arccore/base/String.h"
27#include "arccore/base/NotImplementedException.h"
28#include "arccore/base/PlatformUtils.h"
29#include "arccore/base/FatalErrorException.h"
30#include "arccore/base/TraceInfo.h"
32#include "arccore/message_passing_mpi/StandaloneMpiMessagePassingMng.h"
33#include "arccore/message_passing_mpi/internal/MpiLock.h"
34#include "arccore/message_passing_mpi/internal/NoMpiProfiling.h"
35#include "arccore/message_passing_mpi/internal/MpiRequest.h"
36#include "arccore/message_passing_mpi/internal/MpiMachineShMemWinBaseInternalCreator.h"
43namespace Arcane::MessagePassing::Mpi
59 typedef std::map<MPI_Request,RequestInfo>::iterator Iterator;
68 m_request_error_is_fatal =
true;
71 m_is_report_error_in_request =
false;
73 m_use_trace_full_stack =
true;
75 m_trace_mpirequest =
true;
78 void addRequest(MPI_Request request)
82 if (m_trace_mpirequest)
83 info() <<
"MpiAdapter: AddRequest r=" << request;
86 void addRequest(MPI_Request request,
const TraceInfo& ti)
90 if (m_trace_mpirequest)
91 info() <<
"MpiAdapter: AddRequest r=" << request;
94 void removeRequest(MPI_Request request)
98 if (m_trace_mpirequest)
99 info() <<
"MpiAdapter: RemoveRequest r=" << request;
102 void removeRequest(
Iterator request_iter)
106 if (request_iter==m_allocated_requests.end()){
107 if (m_trace_mpirequest)
108 info() <<
"MpiAdapter: RemoveRequestIter null iterator";
111 if (m_trace_mpirequest)
112 info() <<
"MpiAdapter: RemoveRequestIter r=" << request_iter->first;
113 m_allocated_requests.erase(request_iter);
119 return m_allocated_requests.end();
121 if (_isEmptyRequest(request))
122 return m_allocated_requests.end();
123 auto ireq = m_allocated_requests.find(request);
124 if (ireq==m_allocated_requests.end()){
125 if (m_is_report_error_in_request || m_request_error_is_fatal){
126 error() <<
"MpiAdapter::testRequest() request not referenced "
127 <<
" id=" << request;
128 _checkFatalInRequest();
139 if (request==MPI_REQUEST_NULL){
140 if (m_is_report_error_in_request || m_request_error_is_fatal){
141 error() <<
"MpiAdapter::_addRequest() trying to add null request";
142 _checkFatalInRequest();
146 if (_isEmptyRequest(request))
148 ++m_total_added_request;
150 auto i = m_allocated_requests.find(request);
151 if (i!=m_allocated_requests.end()){
152 if (m_is_report_error_in_request || m_request_error_is_fatal){
153 error() <<
"MpiAdapter::_addRequest() request already referenced "
154 <<
" id=" << request;
155 _checkFatalInRequest();
160 rinfo.m_trace = trace_info;
161 if (m_use_trace_full_stack)
163 m_allocated_requests.insert(std::make_pair(request,rinfo));
172 if (request==MPI_REQUEST_NULL){
173 if (m_is_report_error_in_request || m_request_error_is_fatal){
174 error() <<
"MpiAdapter::_removeRequest() null request (" << MPI_REQUEST_NULL <<
")";
175 _checkFatalInRequest();
179 if (_isEmptyRequest(request))
181 auto i = m_allocated_requests.find(request);
182 if (i==m_allocated_requests.end()){
183 if (m_is_report_error_in_request || m_request_error_is_fatal){
184 error() <<
"MpiAdapter::_removeRequest() request not referenced "
185 <<
" id=" << request;
186 _checkFatalInRequest();
190 m_allocated_requests.erase(i);
193 void _checkFatalInRequest()
195 if (m_request_error_is_fatal)
198 Int64 nbRequest()
const {
return m_allocated_requests.size(); }
199 Int64 totalAddedRequest()
const {
return m_total_added_request; }
200 void printRequests()
const
202 info() <<
"PRINT REQUESTS\n";
203 for(
auto& x : m_allocated_requests ){
204 info() <<
"Request id=" << x.first <<
" trace=" << x.second.m_trace
205 <<
" stack=" << x.second.m_stack_trace;
208 void setEmptyRequests(MPI_Request r1,MPI_Request r2)
210 m_empty_request1 = r1;
211 m_empty_request2 = r2;
214 bool m_request_error_is_fatal =
false;
215 bool m_is_report_error_in_request =
true;
216 bool m_trace_mpirequest =
false;
220 std::map<MPI_Request,RequestInfo> m_allocated_requests;
221 bool m_use_trace_full_stack =
false;
222 MPI_Request m_empty_request1 = MPI_REQUEST_NULL;
223 MPI_Request m_empty_request2 = MPI_REQUEST_NULL;
224 Int64 m_total_added_request = 0;
227 bool _isEmptyRequest(MPI_Request r)
const
229 return (r==m_empty_request1 || r==m_empty_request2);
233#define ARCCORE_ADD_REQUEST(request)\
234 m_request_set->addRequest(request,A_FUNCINFO);
241int _checkSize(
Int64 i64_size)
243 if (i64_size>INT32_MAX)
244 ARCCORE_FATAL(
"Can not convert '{0}' to type integer",i64_size);
245 return (
int)i64_size;
257, m_mpi_lock(mpi_lock)
263, m_empty_request2(MPI_REQUEST_NULL)
271 if (s ==
"1" || s ==
"TRUE")
272 m_is_allow_null_rank_for_any_source =
true;
273 if (s ==
"0" || s ==
"FALSE")
274 m_is_allow_null_rank_for_any_source =
false;
295 MPI_Irecv(m_recv_buffer_for_empty_request, 1, MPI_CHAR, MPI_PROC_NULL,
305 m_send_buffer_for_empty_request2[0] = 0;
306 MPI_Isend(m_send_buffer_for_empty_request2, 1, MPI_CHAR, m_comm_rank,
309 MPI_Recv(m_recv_buffer_for_empty_request2, 1, MPI_CHAR, m_comm_rank,
323 if (m_empty_request2 != MPI_REQUEST_NULL)
324 MPI_Request_free(&m_empty_request2);
326 delete m_request_set;
345 Int64 nb_request = m_request_set->nbRequest();
350 warning() <<
" Pending mpi requests size=" << nb_request;
351 m_request_set->printRequests();
352 _checkFatalInRequest();
362 _checkHasNoRequests();
372 m_request_set->m_request_error_is_fatal = v;
375isRequestErrorAreFatal()
const
377 return m_request_set->m_request_error_is_fatal;
383 m_request_set->m_is_report_error_in_request = v;
386isPrintRequestError()
const
388 return m_request_set->m_is_report_error_in_request;
394 m_request_set->m_no_check_request = !v;
398isCheckRequest()
const
407toMPISize(
Int64 count)
409 return _checkSize(count);
416_trace(
const char* function)
423 info() <<
"MPI_TRACE: " << function;
431broadcast(
void* buf,
Int64 nb_elem,
Int32 root,MPI_Datatype datatype)
433 int _nb_elem = _checkSize(nb_elem);
434 _trace(MpiInfo(eMpiName::Bcast).name().localstr());
435 double begin_time = MPI_Wtime();
437 info() <<
"MPI_TRACE: MPI broadcast: before"
439 <<
" nb_elem=" << nb_elem
441 <<
" datatype=" << datatype;
443 m_mpi_prof->broadcast(buf, _nb_elem, datatype, root,
m_communicator);
444 double end_time = MPI_Wtime();
445 double sr_time = (end_time-begin_time);
447 m_stat->add(MpiInfo(eMpiName::Bcast).name(),sr_time,0);
454nonBlockingBroadcast(
void* buf,
Int64 nb_elem,
Int32 root,MPI_Datatype datatype)
456 MPI_Request mpi_request = MPI_REQUEST_NULL;
458 int _nb_elem = _checkSize(nb_elem);
459 _trace(
" MPI_Bcast");
460 double begin_time = MPI_Wtime();
461 ret = MPI_Ibcast(buf,_nb_elem,datatype,root,
m_communicator,&mpi_request);
462 double end_time = MPI_Wtime();
463 double sr_time = (end_time-begin_time);
465 m_stat->add(
"IBroadcast",sr_time,0);
466 ARCCORE_ADD_REQUEST(mpi_request);
474gather(
const void* send_buf,
void* recv_buf,
Int64 nb_elem,
Int32 root,MPI_Datatype datatype)
476 void* _sbuf =
const_cast<void*
>(send_buf);
477 int _nb_elem = _checkSize(nb_elem);
478 int _root =
static_cast<int>(root);
479 _trace(MpiInfo(eMpiName::Gather).name().localstr());
480 double begin_time = MPI_Wtime();
481 m_mpi_prof->gather(_sbuf, _nb_elem, datatype, recv_buf, _nb_elem, datatype, _root,
m_communicator);
482 double end_time = MPI_Wtime();
483 double sr_time = (end_time-begin_time);
485 m_stat->add(MpiInfo(eMpiName::Gather).name(),sr_time,0);
492nonBlockingGather(
const void* send_buf,
void* recv_buf,
493 Int64 nb_elem,
Int32 root,MPI_Datatype datatype)
495 MPI_Request mpi_request = MPI_REQUEST_NULL;
497 void* _sbuf =
const_cast<void*
>(send_buf);
498 int _nb_elem = _checkSize(nb_elem);
499 int _root =
static_cast<int>(root);
500 _trace(
"MPI_Igather");
501 double begin_time = MPI_Wtime();
502 ret = MPI_Igather(_sbuf,_nb_elem,datatype,recv_buf,_nb_elem,datatype,_root,
504 double end_time = MPI_Wtime();
505 double sr_time = (end_time-begin_time);
507 m_stat->add(
"IGather",sr_time,0);
508 ARCCORE_ADD_REQUEST(mpi_request);
516allGather(
const void* send_buf,
void* recv_buf,
517 Int64 nb_elem,MPI_Datatype datatype)
519 void* _sbuf =
const_cast<void*
>(send_buf);
520 int _nb_elem = _checkSize(nb_elem);
521 _trace(MpiInfo(eMpiName::Allgather).name().localstr());
522 double begin_time = MPI_Wtime();
523 m_mpi_prof->allGather(_sbuf, _nb_elem, datatype, recv_buf, _nb_elem, datatype,
m_communicator);
524 double end_time = MPI_Wtime();
525 double sr_time = (end_time-begin_time);
527 m_stat->add(MpiInfo(eMpiName::Allgather).name(),sr_time,0);
534nonBlockingAllGather(
const void* send_buf,
void* recv_buf,
535 Int64 nb_elem,MPI_Datatype datatype)
537 MPI_Request mpi_request = MPI_REQUEST_NULL;
539 void* _sbuf =
const_cast<void*
>(send_buf);
540 int _nb_elem = _checkSize(nb_elem);
541 _trace(
"MPI_Iallgather");
542 double begin_time = MPI_Wtime();
543 ret = MPI_Iallgather(_sbuf,_nb_elem,datatype,recv_buf,_nb_elem,datatype,
545 double end_time = MPI_Wtime();
546 double sr_time = (end_time-begin_time);
548 m_stat->add(
"IAllGather",sr_time,0);
549 ARCCORE_ADD_REQUEST(mpi_request);
557gatherVariable(
const void* send_buf,
void* recv_buf,
const int* recv_counts,
558 const int* recv_indexes,
Int64 nb_elem,
Int32 root,MPI_Datatype datatype)
560 void* _sbuf =
const_cast<void*
>(send_buf);
561 int _nb_elem = _checkSize(nb_elem);
562 int _root =
static_cast<int>(root);
563 _trace(MpiInfo(eMpiName::Gatherv).name().localstr());
564 double begin_time = MPI_Wtime();
565 m_mpi_prof->gatherVariable(_sbuf, _nb_elem, datatype, recv_buf, recv_counts, recv_indexes, datatype, _root,
m_communicator);
566 double end_time = MPI_Wtime();
567 double sr_time = (end_time-begin_time);
569 m_stat->add(MpiInfo(eMpiName::Gatherv).name().localstr(),sr_time,0);
576allGatherVariable(
const void* send_buf,
void* recv_buf,
const int* recv_counts,
577 const int* recv_indexes,
Int64 nb_elem,MPI_Datatype datatype)
579 void* _sbuf =
const_cast<void*
>(send_buf);
580 int _nb_elem = _checkSize(nb_elem);
581 _trace(MpiInfo(eMpiName::Allgatherv).name().localstr());
586 double begin_time = MPI_Wtime();
587 m_mpi_prof->allGatherVariable(_sbuf, _nb_elem, datatype, recv_buf, recv_counts, recv_indexes, datatype,
m_communicator);
588 double end_time = MPI_Wtime();
589 double sr_time = (end_time-begin_time);
591 m_stat->add(MpiInfo(eMpiName::Allgatherv).name().localstr(),sr_time,0);
598scatterVariable(
const void* send_buf,
const int* send_count,
const int* send_indexes,
599 void* recv_buf,
Int64 nb_elem,
Int32 root,MPI_Datatype datatype)
601 void* _sbuf =
const_cast<void*
>(send_buf);
602 int* _send_count =
const_cast<int*
>(send_count);
603 int* _send_indexes =
const_cast<int*
>(send_indexes);
604 int _nb_elem = _checkSize(nb_elem);
605 _trace(MpiInfo(eMpiName::Scatterv).name().localstr());
606 double begin_time = MPI_Wtime();
607 m_mpi_prof->scatterVariable(_sbuf,
616 double end_time = MPI_Wtime();
617 double sr_time = (end_time-begin_time);
619 m_stat->add(MpiInfo(eMpiName::Scatterv).name(),sr_time,0);
626allToAll(
const void* send_buf,
void* recv_buf,
Integer count,MPI_Datatype datatype)
628 void* _sbuf =
const_cast<void*
>(send_buf);
629 int icount = _checkSize(count);
630 _trace(MpiInfo(eMpiName::Alltoall).name().localstr());
631 double begin_time = MPI_Wtime();
632 m_mpi_prof->allToAll(_sbuf, icount, datatype, recv_buf, icount, datatype,
m_communicator);
633 double end_time = MPI_Wtime();
634 double sr_time = (end_time-begin_time);
636 m_stat->add(MpiInfo(eMpiName::Alltoall).name().localstr(),sr_time,0);
643nonBlockingAllToAll(
const void* send_buf,
void* recv_buf,
Integer count,MPI_Datatype datatype)
645 MPI_Request mpi_request = MPI_REQUEST_NULL;
647 void* _sbuf =
const_cast<void*
>(send_buf);
648 int icount = _checkSize(count);
649 _trace(
"MPI_IAlltoall");
650 double begin_time = MPI_Wtime();
651 ret = MPI_Ialltoall(_sbuf,icount,datatype,recv_buf,icount,datatype,
m_communicator,&mpi_request);
652 double end_time = MPI_Wtime();
653 double sr_time = (end_time-begin_time);
655 m_stat->add(
"IAllToAll",sr_time,0);
656 ARCCORE_ADD_REQUEST(mpi_request);
664allToAllVariable(
const void* send_buf,
const int* send_counts,
665 const int* send_indexes,
void* recv_buf,
const int* recv_counts,
666 const int* recv_indexes,MPI_Datatype datatype)
668 void* _sbuf =
const_cast<void*
>(send_buf);
669 int* _send_counts =
const_cast<int*
>(send_counts);
670 int* _send_indexes =
const_cast<int*
>(send_indexes);
671 int* _recv_counts =
const_cast<int*
>(recv_counts);
672 int* _recv_indexes =
const_cast<int*
>(recv_indexes);
674 _trace(MpiInfo(eMpiName::Alltoallv).name().localstr());
675 double begin_time = MPI_Wtime();
676 m_mpi_prof->allToAllVariable(_sbuf, _send_counts, _send_indexes, datatype,
678 double end_time = MPI_Wtime();
679 double sr_time = (end_time-begin_time);
681 m_stat->add(MpiInfo(eMpiName::Alltoallv).name(),sr_time,0);
688nonBlockingAllToAllVariable(
const void* send_buf,
const int* send_counts,
689 const int* send_indexes,
void* recv_buf,
const int* recv_counts,
690 const int* recv_indexes,MPI_Datatype datatype)
692 MPI_Request mpi_request = MPI_REQUEST_NULL;
694 void* _sbuf =
const_cast<void*
>(send_buf);
695 int* _send_counts =
const_cast<int*
>(send_counts);
696 int* _send_indexes =
const_cast<int*
>(send_indexes);
697 int* _recv_counts =
const_cast<int*
>(recv_counts);
698 int* _recv_indexes =
const_cast<int*
>(recv_indexes);
700 _trace(
"MPI_Ialltoallv");
701 double begin_time = MPI_Wtime();
702 ret = MPI_Ialltoallv(_sbuf,_send_counts,_send_indexes,datatype,
703 recv_buf,_recv_counts,_recv_indexes,datatype,
705 double end_time = MPI_Wtime();
706 double sr_time = (end_time-begin_time);
708 m_stat->add(
"IAllToAll",sr_time,0);
709 ARCCORE_ADD_REQUEST(mpi_request);
732 MPI_Request mpi_request = MPI_REQUEST_NULL;
735 ARCCORE_ADD_REQUEST(mpi_request);
743allReduce(
const void* send_buf,
void* recv_buf,
Int64 count,MPI_Datatype datatype,MPI_Op op)
745 void* _sbuf =
const_cast<void*
>(send_buf);
746 int _n = _checkSize(count);
747 double begin_time = MPI_Wtime();
748 _trace(MpiInfo(eMpiName::Allreduce).name().localstr());
751 m_mpi_prof->allReduce(_sbuf, recv_buf, _n, datatype, op,
m_communicator);
753 catch(TimeoutException& ex)
755 std::ostringstream ostr;
756 ostr <<
"MPI_Allreduce"
757 <<
" send_buf=" << send_buf
758 <<
" recv_buf=" << recv_buf
760 <<
" datatype=" << datatype
762 <<
" NB=" << m_nb_all_reduce;
763 ex.setAdditionalInfo(ostr.str());
766 double end_time = MPI_Wtime();
767 m_stat->add(MpiInfo(eMpiName::Allreduce).name(),end_time-begin_time,count);
774nonBlockingAllReduce(
const void* send_buf,
void* recv_buf,
Int64 count,MPI_Datatype datatype,MPI_Op op)
776 MPI_Request mpi_request = MPI_REQUEST_NULL;
778 void* _sbuf =
const_cast<void*
>(send_buf);
779 int _n = _checkSize(count);
780 double begin_time = MPI_Wtime();
781 _trace(
"MPI_IAllreduce");
782 ret = MPI_Iallreduce(_sbuf,recv_buf,_n,datatype,op,
m_communicator,&mpi_request);
783 double end_time = MPI_Wtime();
784 m_stat->add(
"IReduce",end_time-begin_time,_n);
785 ARCCORE_ADD_REQUEST(mpi_request);
793reduce(
const void* send_buf,
void* recv_buf,
Int64 count,MPI_Datatype datatype,MPI_Op op,
Integer root)
795 void* _sbuf =
const_cast<void*
>(send_buf);
796 int _n = _checkSize(count);
797 int _root =
static_cast<int>(root);
798 double begin_time = MPI_Wtime();
799 _trace(MpiInfo(eMpiName::Reduce).name().localstr());
802 m_mpi_prof->reduce(_sbuf, recv_buf, _n, datatype, op, _root,
m_communicator);
804 catch(TimeoutException& ex)
806 std::ostringstream ostr;
808 <<
" send_buf=" << send_buf
809 <<
" recv_buf=" << recv_buf
811 <<
" datatype=" << datatype
814 <<
" NB=" << m_nb_reduce;
815 ex.setAdditionalInfo(ostr.str());
819 double end_time = MPI_Wtime();
820 m_stat->add(MpiInfo(eMpiName::Reduce).name(),end_time-begin_time,0);
827scan(
const void* send_buf,
void* recv_buf,
Int64 count,MPI_Datatype datatype,MPI_Op op)
829 void* _sbuf =
const_cast<void*
>(send_buf);
830 int _n = _checkSize(count);
831 double begin_time = MPI_Wtime();
832 _trace(MpiInfo(eMpiName::Scan).name().localstr());
833 m_mpi_prof->scan(_sbuf, recv_buf, _n, datatype, op,
m_communicator);
834 double end_time = MPI_Wtime();
835 m_stat->add(MpiInfo(eMpiName::Scan).name(),end_time-begin_time,count);
842scanExclusive(
const void* send_buf,
void* recv_buf,
Int64 count, MPI_Datatype datatype, MPI_Op op)
844 void* _sbuf =
const_cast<void*
>(send_buf);
845 int _n = _checkSize(count);
846 double begin_time = MPI_Wtime();
847 _trace(MpiInfo(eMpiName::Scan).name().localstr());
848 m_mpi_prof->scanExclusive(_sbuf, recv_buf, _n, datatype, op,
m_communicator);
849 double end_time = MPI_Wtime();
850 m_stat->add(MpiInfo(eMpiName::Scan).name(), end_time - begin_time, count);
857directSendRecv(
const void* send_buffer,
Int64 send_buffer_size,
858 void* recv_buffer,
Int64 recv_buffer_size,
859 Int32 proc,
Int64 elem_size, MPI_Datatype data_type)
861 void* v_send_buffer =
const_cast<void*
>(send_buffer);
862 MPI_Status mpi_status;
863 double begin_time = MPI_Wtime();
864 _trace(MpiInfo(eMpiName::Sendrecv).name().localstr());
865 int sbuf_size = _checkSize(send_buffer_size);
866 int rbuf_size = _checkSize(recv_buffer_size);
867 m_mpi_prof->sendRecv(v_send_buffer, sbuf_size, data_type, proc, 99,
868 recv_buffer, rbuf_size, data_type, proc, 99,
870 double end_time = MPI_Wtime();
871 Int64 send_size = send_buffer_size * elem_size;
872 Int64 recv_size = recv_buffer_size * elem_size;
873 double sr_time = (end_time-begin_time);
877 m_stat->add(MpiInfo(eMpiName::Sendrecv).name(),sr_time,send_size+recv_size);
885 Int32 dest_rank,MPI_Datatype data_type,
int mpi_tag)
887 void* v_send_buffer =
const_cast<void*
>(send_buffer);
888 MPI_Request mpi_request = MPI_REQUEST_NULL;
889 int sbuf_size = _checkSize(send_buffer_size);
891 m_mpi_prof->iSend(v_send_buffer, sbuf_size, data_type, dest_rank, mpi_tag,
m_communicator, &mpi_request);
893 info() <<
" ISend ret=" << ret <<
" proc=" << dest_rank <<
" tag=" << mpi_tag <<
" request=" << mpi_request;
894 ARCCORE_ADD_REQUEST(mpi_request);
902directSend(
const void* send_buffer,
Int64 send_buffer_size,
903 Int32 proc,
Int64 elem_size,MPI_Datatype data_type,
904 int mpi_tag,
bool is_blocked
907 void* v_send_buffer =
const_cast<void*
>(send_buffer);
908 MPI_Request mpi_request = MPI_REQUEST_NULL;
910 double begin_time = 0.0;
911 double end_time = 0.0;
912 Int64 send_size = send_buffer_size * elem_size;
915 info() <<
"MPI_TRACE: MPI Send: send before"
916 <<
" size=" << send_size
918 <<
" tag=" << mpi_tag
919 <<
" datatype=" << data_type
920 <<
" blocking " << is_blocked;
929 begin_time = MPI_Wtime();
930 int sbuf_size = _checkSize(send_buffer_size);
931 m_mpi_prof->iSend(v_send_buffer, sbuf_size, data_type, proc, mpi_tag,
m_communicator, &mpi_request);
934 MPI_Status mpi_status;
935 while (is_finished==0){
937 MPI_Request_get_status(mpi_request,&is_finished,&mpi_status);
939 m_mpi_prof->wait(&mpi_request, (MPI_Status *) MPI_STATUS_IGNORE);
940 end_time = MPI_Wtime();
941 mpi_request = MPI_REQUEST_NULL;
946 MpiLock::Section mls(m_mpi_lock);
947 begin_time = MPI_Wtime();
948 int sbuf_size = _checkSize(send_buffer_size);
949 m_mpi_prof->send(v_send_buffer, sbuf_size, data_type, proc, mpi_tag,
m_communicator);
950 end_time = MPI_Wtime();
955 MpiLock::Section mls(m_mpi_lock);
956 begin_time = MPI_Wtime();
957 int sbuf_size = _checkSize(send_buffer_size);
958 m_mpi_prof->iSend(v_send_buffer, sbuf_size, data_type, proc, mpi_tag,
m_communicator, &mpi_request);
960 info() <<
" ISend ret=" << ret <<
" proc=" << proc <<
" tag=" << mpi_tag <<
" request=" << mpi_request;
961 end_time = MPI_Wtime();
962 ARCCORE_ADD_REQUEST(mpi_request);
965 info() <<
"MPI Send: send after"
966 <<
" request=" << mpi_request;
969 double sr_time = (end_time-begin_time);
972 <<
" time " << sr_time <<
" blocking " << is_blocked;
974 m_stat->add(MpiInfo(eMpiName::Send).name(),end_time-begin_time,send_size);
982directSendPack(
const void* send_buffer,
Int64 send_buffer_size,
983 Int32 proc,
int mpi_tag,
bool is_blocked)
985 return directSend(send_buffer,send_buffer_size,proc,1,MPI_PACKED,mpi_tag,is_blocked);
1009 Int32 source_rank,MPI_Datatype data_type,
int mpi_tag)
1011 int rbuf_size = _checkSize(recv_buffer_size);
1013 MPI_Request mpi_request = MPI_REQUEST_NULL;
1014 m_mpi_prof->iRecv(recv_buffer, rbuf_size, data_type, source_rank, mpi_tag,
m_communicator, &mpi_request);
1015 ARCCORE_ADD_REQUEST(mpi_request);
1023directRecv(
void* recv_buffer,
Int64 recv_buffer_size,
1024 Int32 proc,
Int64 elem_size,MPI_Datatype data_type,
1025 int mpi_tag,
bool is_blocked)
1027 MPI_Status mpi_status;
1028 MPI_Request mpi_request = MPI_REQUEST_NULL;
1030 double begin_time = 0.0;
1031 double end_time = 0.0;
1034 if (proc==A_PROC_NULL_RANK)
1036 if (proc == A_NULL_RANK && !m_is_allow_null_rank_for_any_source)
1037 ARCCORE_FATAL(
"Can not use A_NULL_RANK for any source. Use A_ANY_SOURCE_RANK instead");
1038 if (proc==A_NULL_RANK || proc==A_ANY_SOURCE_RANK)
1039 i_proc = MPI_ANY_SOURCE;
1041 i_proc =
static_cast<int>(proc);
1043 Int64 recv_size = recv_buffer_size * elem_size;
1045 info() <<
"MPI_TRACE: MPI Recv: recv before "
1046 <<
" size=" << recv_size
1047 <<
" from=" << i_proc
1048 <<
" tag=" << mpi_tag
1049 <<
" datatype=" << data_type
1050 <<
" blocking=" << is_blocked;
1060 begin_time = MPI_Wtime();
1061 int rbuf_size = _checkSize(recv_buffer_size);
1062 m_mpi_prof->iRecv(recv_buffer, rbuf_size, data_type, i_proc, mpi_tag,
m_communicator, &mpi_request);
1064 int is_finished = 0;
1065 MPI_Status mpi_status;
1066 while (is_finished==0){
1068 MPI_Request_get_status(mpi_request,&is_finished,&mpi_status);
1069 if (is_finished!=0){
1070 end_time = MPI_Wtime();
1071 m_mpi_prof->wait(&mpi_request, (MPI_Status *) MPI_STATUS_IGNORE);
1072 mpi_request = MPI_REQUEST_NULL;
1077 MpiLock::Section mls(m_mpi_lock);
1078 begin_time = MPI_Wtime();
1079 int rbuf_size = _checkSize(recv_buffer_size);
1080 m_mpi_prof->recv(recv_buffer, rbuf_size, data_type, i_proc, mpi_tag,
m_communicator, &mpi_status);
1081 end_time = MPI_Wtime();
1086 MpiLock::Section mls(m_mpi_lock);
1087 begin_time = MPI_Wtime();
1088 int rbuf_size = _checkSize(recv_buffer_size);
1089 m_mpi_prof->iRecv(recv_buffer, rbuf_size, data_type, i_proc, mpi_tag,
m_communicator, &mpi_request);
1090 end_time = MPI_Wtime();
1091 ARCCORE_ADD_REQUEST(mpi_request);
1094 info() <<
"MPI Recv: recv after "
1095 <<
" request=" << mpi_request;
1098 double sr_time = (end_time-begin_time);
1101 <<
" time " << sr_time <<
" blocking " << is_blocked;
1102 m_stat->add(MpiInfo(eMpiName::Recv).name(),end_time-begin_time,recv_size);
1112 double begin_time = MPI_Wtime();
1114 int recv_buffer_size = 0;
1115 _trace(
"MPI_Probe");
1117 m_mpi_prof->getCount(&status, MPI_PACKED, &recv_buffer_size);
1119 recv_buffer.resize(recv_buffer_size);
1120 m_mpi_prof->recv(recv_buffer.data(), recv_buffer_size, MPI_PACKED, proc, 101,
m_communicator, &status);
1122 double end_time = MPI_Wtime();
1123 Int64 recv_size = recv_buffer_size;
1124 double sr_time = (end_time-begin_time);
1126 <<
" time " << sr_time;
1127 m_stat->add(MpiInfo(eMpiName::Recv).name(),end_time-begin_time,recv_size);
1134_buildSourceInfoFromStatus(
const MPI_Status& mpi_status)
1137 MPI_Count message_size = 0;
1138 MPI_Get_elements_x(&mpi_status,MPI_BYTE,&message_size);
1139 MessageTag tag(mpi_status.MPI_TAG);
1140 MessageRank rank(mpi_status.MPI_SOURCE);
1141 return MessageSourceInfo(rank,tag,message_size);
1150 MPI_Status mpi_status;
1151 int has_message = 0;
1152 MPI_Message message;
1154 int mpi_source = source.value();
1155 if (source.isProcNull())
1156 ARCCORE_THROW(NotImplementedException,
"Probe with MPI_PROC_NULL");
1157 if (source.isNull() && !m_is_allow_null_rank_for_any_source)
1158 ARCCORE_FATAL(
"Can not use MPI_Mprobe with null rank. Use MessageRank::anySourceRank() instead");
1159 if (source.isNull() || source.isAnySource())
1160 mpi_source = MPI_ANY_SOURCE;
1161 int mpi_tag = tag.value();
1163 mpi_tag = MPI_ANY_TAG;
1165 ret = MPI_Mprobe(mpi_source,mpi_tag,
m_communicator,&message,&mpi_status);
1169 ret = MPI_Improbe(mpi_source, mpi_tag,
m_communicator, &has_message, &message, &mpi_status);
1173 MessageId ret_message;
1174 if (has_message!=0){
1175 MessageSourceInfo si(_buildSourceInfoFromStatus(mpi_status));
1176 ret_message = MessageId(si,message);
1187 if (!message.isValid())
1191 if (!message.isRankTag())
1192 ARCCORE_FATAL(
"Invalid message_info: message.isRankTag() is false");
1194 return _probeMessage(message.destinationRank(),message.tag(),message.isBlocking());
1203 MPI_Status mpi_status;
1204 int has_message = 0;
1206 int mpi_source = source.value();
1207 if (source.isProcNull())
1208 ARCCORE_THROW(NotImplementedException,
"Probe with MPI_PROC_NULL");
1209 if (source.isNull() && !m_is_allow_null_rank_for_any_source)
1210 ARCCORE_FATAL(
"Can not use MPI_Probe with null rank. Use MessageRank::anySourceRank() instead");
1211 if (source.isNull() || source.isAnySource())
1212 mpi_source = MPI_ANY_SOURCE;
1213 int mpi_tag = tag.value();
1215 mpi_tag = MPI_ANY_TAG;
1221 ret = MPI_Iprobe(mpi_source,mpi_tag,
m_communicator,&has_message,&mpi_status);
1225 return _buildSourceInfoFromStatus(mpi_status);
1235 if (!message.isValid())
1239 if (!message.isRankTag())
1240 ARCCORE_FATAL(
"Invalid message_info: message.isRankTag() is false");
1242 return _legacyProbeMessage(message.destinationRank(),message.tag(),message.isBlocking());
1249directRecv(
void* recv_buffer,
Int64 recv_buffer_size,
1253 MPI_Status mpi_status;
1254 MPI_Request mpi_request = MPI_REQUEST_NULL;
1255 MPI_Message mpi_message = (MPI_Message)message;
1257 double begin_time = 0.0;
1258 double end_time = 0.0;
1260 Int64 recv_size = recv_buffer_size * elem_size;
1262 info() <<
"MPI_TRACE: MPI Mrecv: recv before "
1263 <<
" size=" << recv_size
1264 <<
" from_msg=" << message
1265 <<
" datatype=" << data_type
1266 <<
" blocking=" << is_blocked;
1276 begin_time = MPI_Wtime();
1277 int rbuf_size = _checkSize(recv_buffer_size);
1278 MPI_Imrecv(recv_buffer,rbuf_size,data_type,&mpi_message,&mpi_request);
1281 int is_finished = 0;
1282 MPI_Status mpi_status;
1283 while (is_finished==0){
1285 MPI_Request_get_status(mpi_request,&is_finished,&mpi_status);
1286 if (is_finished!=0){
1287 end_time = MPI_Wtime();
1288 m_mpi_prof->wait(&mpi_request, (MPI_Status *) MPI_STATUS_IGNORE);
1289 mpi_request = MPI_REQUEST_NULL;
1295 begin_time = MPI_Wtime();
1296 int rbuf_size = _checkSize(recv_buffer_size);
1297 MPI_Mrecv(recv_buffer,rbuf_size,data_type,&mpi_message,&mpi_status);
1299 end_time = MPI_Wtime();
1305 begin_time = MPI_Wtime();
1306 int rbuf_size = _checkSize(recv_buffer_size);
1308 ret = MPI_Imrecv(recv_buffer,rbuf_size,data_type,&mpi_message,&mpi_request);
1310 end_time = MPI_Wtime();
1311 ARCCORE_ADD_REQUEST(mpi_request);
1314 info() <<
"MPI Recv: recv after "
1315 <<
" request=" << mpi_request;
1318 double sr_time = (end_time-begin_time);
1321 <<
" time " << sr_time <<
" blocking " << is_blocked;
1322 m_stat->add(
MpiInfo(eMpiName::Recv).name(),end_time-begin_time,recv_size);
1330directRecvPack(
void* recv_buffer,
Int64 recv_buffer_size,
1331 Int32 proc,
int mpi_tag,
bool is_blocking)
1333 return directRecv(recv_buffer,recv_buffer_size,proc,1,MPI_PACKED,mpi_tag,is_blocking);
1345 while (_waitAllRequestsMPI(requests, indexes, mpi_status)){
1355waitSomeRequests(ArrayView<Request> requests,
1356 ArrayView<bool> indexes,
1357 bool is_non_blocking)
1359 UniqueArray<MPI_Status> mpi_status(requests.size());
1360 waitSomeRequestsMPI(requests, indexes, mpi_status, is_non_blocking);
1371 , mpi_source_rank(source_rank)
1372 , mpi_source_tag(source_tag)
1377 int mpi_source_rank = MPI_PROC_NULL;
1378 int mpi_source_tag = 0;
1392 for(
Integer i=0; i<size; ++i ) {
1393 if (done_indexes[i]){
1399 if (r.hasSubRequest()){
1401 info() <<
"Done request with sub-request r=" << r <<
" mpi_r=" << r <<
" i=" << i
1402 <<
" source_rank=" << status[i].MPI_SOURCE
1403 <<
" source_tag=" << status[i].MPI_TAG;
1404 new_requests.
add(
SubRequestInfo(r.subRequest(), i, status[i].MPI_SOURCE, status[i].MPI_TAG));
1417 bool has_new_request =
false;
1418 if (!new_requests.
empty()){
1420 UniqueArray<MPI_Status> old_status(size);
1423 for(
Integer i=0; i<size; ++i ){
1424 if (done_indexes[i]){
1425 old_status[i] = status[index];
1434 info() <<
"Before handle new request index=" << index
1435 <<
" sri.source_rank=" << sri.mpi_source_rank
1436 <<
" sri.source_tag=" << sri.mpi_source_tag;
1437 SubRequestCompletionInfo completion_info(MessageRank(old_status[index].MPI_SOURCE), MessageTag(old_status[index].MPI_TAG));
1438 Request r = sri.sub_request->executeOnCompletion(completion_info);
1440 info() <<
"Handle new request index=" << index <<
" old_r=" << requests[index] <<
" new_r=" << r;
1445 has_new_request =
true;
1446 requests[index] = r;
1447 done_indexes[index] =
false;
1452 for(
Integer i=0; i<size; ++i ){
1453 if (done_indexes[i]){
1454 status[index] = old_status[i];
1461 return has_new_request;
1472 Integer size = requests.size();
1476 UniqueArray<MPI_Request> mpi_request(size);
1477 for(
Integer i=0; i<size; ++i ){
1478 mpi_request[i] = (MPI_Request)(requests[i]);
1481 info() <<
" MPI_waitall begin size=" << size;
1482 double diff_time = 0.0;
1484 double begin_time = MPI_Wtime();
1485 for(
Integer i=0; i<size; ++i ){
1486 MPI_Request request = (MPI_Request)(mpi_request[i]);
1487 int is_finished = 0;
1488 while (is_finished==0){
1489 MpiLock::Section mls(m_mpi_lock);
1490 m_mpi_prof->test(&request, &is_finished, (MPI_Status *) MPI_STATUS_IGNORE);
1493 double end_time = MPI_Wtime();
1494 diff_time = end_time - begin_time;
1498 MpiLock::Section mls(m_mpi_lock);
1499 double begin_time = MPI_Wtime();
1500 m_mpi_prof->waitAll(size, mpi_request.data(), mpi_status.data());
1501 double end_time = MPI_Wtime();
1502 diff_time = end_time - begin_time;
1506 for(
Integer i=0; i<size; ++i ){
1510 bool has_new_request = _handleEndRequests(requests,indexes,mpi_status);
1512 info() <<
" MPI_waitall end size=" << size;
1513 m_stat->add(MpiInfo(eMpiName::Waitall).name(),diff_time,size);
1514 return has_new_request;
1524 Integer size = requests.size();
1528 UniqueArray<MPI_Request> mpi_request(size);
1529 UniqueArray<MPI_Request> saved_mpi_request(size);
1530 UniqueArray<int> completed_requests(size);
1531 int nb_completed_request = 0;
1535 for (
Integer i = 0; i < size; ++i) {
1539 if (!requests[i].isValid()) {
1540 saved_mpi_request[i] = MPI_REQUEST_NULL;
1543 saved_mpi_request[i] =
static_cast<MPI_Request
>(requests[i]);
1549 bool is_print_debug = m_is_trace || (!is_non_blocking);
1551 debug() <<
"WaitRequestBegin is_non_blocking=" << is_non_blocking <<
" n=" << size;
1553 double begin_time = MPI_Wtime();
1556 if (is_non_blocking){
1557 _trace(MpiInfo(eMpiName::Testsome).name().localstr());
1559 MpiLock::Section mls(m_mpi_lock);
1560 m_mpi_prof->testSome(size, saved_mpi_request.data(), &nb_completed_request,
1561 completed_requests.data(), mpi_status.data());
1564 if (nb_completed_request == MPI_UNDEFINED)
1565 nb_completed_request = 0;
1567 debug() <<
"WaitSomeRequestMPI: TestSome nb_completed=" << nb_completed_request;
1570 _trace(MpiInfo(eMpiName::Waitsome).name().localstr());
1574 MpiLock::Section mls(m_mpi_lock);
1575 m_mpi_prof->waitSome(size, saved_mpi_request.data(), &nb_completed_request,
1576 completed_requests.data(), mpi_status.data());
1580 if (nb_completed_request == MPI_UNDEFINED)
1581 nb_completed_request = 0;
1583 debug() <<
"WaitSomeRequest nb_completed=" << nb_completed_request;
1586 catch(TimeoutException& ex)
1588 std::ostringstream ostr;
1589 if (is_non_blocking)
1590 ostr << MpiInfo(eMpiName::Testsome).name();
1592 ostr << MpiInfo(eMpiName::Waitsome).name();
1593 ostr <<
" size=" << size
1594 <<
" is_non_blocking=" << is_non_blocking;
1595 ex.setAdditionalInfo(ostr.str());
1599 for(
int z=0; z<nb_completed_request; ++z ){
1600 int index = completed_requests[z];
1602 debug() <<
"Completed my_rank=" << m_comm_rank <<
" z=" << z
1603 <<
" index=" << index
1604 <<
" tag=" << mpi_status[z].MPI_TAG
1605 <<
" source=" << mpi_status[z].MPI_SOURCE;
1607 indexes[index] =
true;
1610 bool has_new_request = _handleEndRequests(requests,indexes,mpi_status);
1611 if (has_new_request){
1616 double end_time = MPI_Wtime();
1617 m_stat->add(MpiInfo(eMpiName::Waitsome).name(),end_time-begin_time,size);
1626 if (!request.isValid()){
1627 warning() <<
"MpiAdapter::freeRequest() null request r=" << (MPI_Request)request;
1628 _checkFatalInRequest();
1632 MpiLock::Section mls(m_mpi_lock);
1634 auto mr = (MPI_Request)request;
1636 MPI_Request_free(&mr);
1648 if (!request.isValid())
1651 auto mr = (MPI_Request)request;
1652 int is_finished = 0;
1655 MpiLock::Section mls(m_mpi_lock);
1660 RequestSet::Iterator request_iter = m_request_set->findRequest(mr);
1662 m_mpi_prof->test(&mr, &is_finished, (MPI_Status *) MPI_STATUS_IGNORE);
1664 if (is_finished!=0){
1665 m_request_set->removeRequest(request_iter);
1666 if (request.hasSubRequest())
1667 ARCCORE_THROW(NotImplementedException,
"SubRequest support");
1684 m_request_set->addRequest(request);
1695 m_request_set->removeRequest(request);
1702enableDebugRequest(
bool enable_debug_request)
1704 m_stat->
enable(enable_debug_request);
1713_checkFatalInRequest()
1715 if (isRequestErrorAreFatal())
1725 m_mpi_prof = mpi_profiling;
1731IMpiProfiling* MpiAdapter::
1732getMpiProfiling()
const
1744 m_mpi_prof =
nullptr;
1748 IMpiProfiling* p =
dynamic_cast<IMpiProfiling*
>(profiler);
1750 ARCCORE_FATAL(
"Invalid profiler. Profiler has to implemented interface 'IMpiProfiling'");
1768initializeWindowCreator(MPI_Comm comm_machine)
1770 if (m_window_creator.isNull()) {
1771 Integer machine_comm_rank = 0;
1772 Integer machine_comm_size = 0;
1773 ::MPI_Comm_rank(comm_machine, &machine_comm_rank);
1774 ::MPI_Comm_size(comm_machine, &machine_comm_size);
1775 m_window_creator =
makeRef(
new MpiMachineShMemWinBaseInternalCreator(comm_machine, machine_comm_rank, machine_comm_size,
m_communicator, m_comm_size));
1783windowCreator()
const
1785 return m_window_creator.get();
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
#define ARCCORE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
bool empty() const
Capacité (nombre d'éléments alloués) du vecteur.
Vue modifiable d'un tableau d'un type T.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Interface d'un service de trace des appels de fonctions.
virtual StackTrace stackTrace(int first_function=0)=0
Chaîne de caractère indiquant la pile d'appel.
Interface du gestionnaire de traces.
Interface du gestionnaire des échanges de messages.
Interface d'un profiler pour les échanges de messages.
Statistiques sur le parallélisme.
virtual void enable(bool is_enabled)=0
Active ou désactive les statistiques.
Informations sur la source d'un message.
Interface d'abstraction pour les operations MPI. Sert principalement a utiliser un decorateur pour le...
void _removeRequest(MPI_Request request)
Iterator findRequest(MPI_Request request)
Vérifie que la requête est dans la liste.
bool m_no_check_request
Vrai si on vérifie pas les requêtes.
void _addRequest(MPI_Request request, const TraceInfo &trace_info)
MpiAdapter(ITraceMng *msg, IStat *stat, MPI_Comm comm, MpiLock *mpi_lock, IMpiProfiling *mpi_prof=nullptr)
void setRequestErrorAreFatal(bool v)
Indique si les erreurs dans la liste des requêtes sont fatales.
int commRank() const
Rang de cette instance dans le communicateur.
void destroy()
Détruit l'instance. Elle ne doit plus être utilisée par la suite.
MPI_Comm m_communicator
Communicateur MPI.
Request sendNonBlockingNoStat(const void *send_buffer, Int64 send_buffer_size, Int32 proc, MPI_Datatype data_type, int mpi_tag)
Version non bloquante de send sans statistique temporelle.
void setCheckRequest(bool v)
Indique si on vérifie les requêtes.
void setPrintRequestError(bool v)
Indique si on affiche des messages pour les erreurs dans les requêtes.
Request buildRequest(int ret, MPI_Request request)
Construit une requête Arccore à partir d'une requête MPI.
MPI_Request m_empty_request1
Requêtes vides. Voir MpiAdapter.cc pour plus d'infos.
void _addRequest(MPI_Request request)
Request receiveNonBlockingNoStat(void *recv_buffer, Int64 recv_buffer_size, Int32 source_rank, MPI_Datatype data_type, int mpi_tag)
Version non bloquante de receive sans statistiques temporelles.
void _removeRequest(MPI_Request request)
Structure informative liee aux enumerationx pour les operations MPI. Donne le nom associe a l'enum ai...
Verrou pour les appels MPI.
Spécialisation MPI d'une 'Request'.
Implementation de l'interface des operations MPI. Correspond a un simple appel aux fonctions MPI du m...
static IMessagePassingMng * create(MPI_Comm comm, bool clean_comm=false)
Créé un gestionnaire associé au communicateur comm.
Informations pour envoyer/recevoir un message point à point.
Exception lorsqu'une fonction n'est pas implémentée.
Référence à une instance.
const String & toString() const
Chaîne de caractères indiquant la pile d'appel.
Chaîne de caractères unicode.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage error() const
Flot pour un message d'erreur.
TraceMessage warning() const
Flot pour un message d'avertissement.
Vecteur 1D de données avec sémantique par valeur (style STL).
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
bool arccoreIsCheck()
Vrai si on est en mode vérification.
std::int32_t Int32
Type entier signé sur 32 bits.