Arcane  v3.15.3.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
MpiParallelMng.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* MpiParallelMng.cc (C) 2000-2025 */
9/* */
10/* Gestionnaire de parallélisme utilisant MPI. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Collection.h"
15#include "arcane/utils/Enumerator.h"
16#include "arcane/utils/ScopedPtr.h"
17#include "arcane/utils/PlatformUtils.h"
18#include "arcane/utils/TimeoutException.h"
19#include "arcane/utils/NotImplementedException.h"
20#include "arcane/utils/ArgumentException.h"
21#include "arcane/utils/ITraceMng.h"
22#include "arcane/utils/ValueConvert.h"
23#include "arcane/utils/Exception.h"
24#include "arcane/utils/HPReal.h"
25
26#include "arcane/core/IIOMng.h"
27#include "arcane/core/Timer.h"
28#include "arcane/core/IItemFamily.h"
29#include "arcane/core/SerializeMessage.h"
30#include "arcane/core/parallel/IStat.h"
31
32#include "arcane/parallel/mpi/MpiParallelMng.h"
33#include "arcane/parallel/mpi/MpiAdapter.h"
34#include "arcane/parallel/mpi/MpiParallelDispatch.h"
35#include "arcane/parallel/mpi/MpiSerializeMessageList.h"
36#include "arcane/parallel/mpi/MpiTimerMng.h"
37#include "arcane/parallel/mpi/MpiLock.h"
38#include "arcane/parallel/mpi/MpiSerializeMessage.h"
39#include "arcane/parallel/mpi/MpiParallelNonBlockingCollective.h"
40#include "arcane/parallel/mpi/MpiDatatype.h"
41#include "arcane/parallel/mpi/IVariableSynchronizerMpiCommunicator.h"
42
43#include "arcane/impl/ParallelReplication.h"
44#include "arcane/impl/SequentialParallelMng.h"
45#include "arcane/impl/ParallelMngUtilsFactoryBase.h"
46#include "arcane/impl/internal/VariableSynchronizer.h"
47
48#include "arccore/message_passing_mpi/MpiMessagePassingMng.h"
49#include "arccore/message_passing_mpi/MpiRequestList.h"
50#include "arccore/message_passing_mpi/MpiSerializeDispatcher.h"
51#include "arccore/message_passing/Dispatchers.h"
53#include "arccore/message_passing/SerializeMessageList.h"
54
55//#define ARCANE_TRACE_MPI
56
57/*---------------------------------------------------------------------------*/
58/*---------------------------------------------------------------------------*/
59
60namespace Arcane
61{
62using namespace Arcane::MessagePassing;
63using namespace Arccore::MessagePassing::Mpi;
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68extern "C++" IIOMng*
69arcaneCreateIOMng(IParallelMng* psm);
70
71#if defined(ARCANE_HAS_MPI_NEIGHBOR)
72// Défini dans MpiNeighborVariableSynchronizeDispatcher
74arcaneCreateMpiNeighborVariableSynchronizerFactory(MpiParallelMng* mpi_pm,
76#endif
78arcaneCreateMpiBlockVariableSynchronizerFactory(MpiParallelMng* mpi_pm, Int32 block_size, Int32 nb_sequence);
80arcaneCreateMpiVariableSynchronizerFactory(MpiParallelMng* mpi_pm);
82arcaneCreateMpiDirectSendrecvVariableSynchronizerFactory(MpiParallelMng* mpi_pm);
84arcaneCreateMpiLegacyVariableSynchronizerFactory(MpiParallelMng* mpi_pm);
85
86/*---------------------------------------------------------------------------*/
87/*---------------------------------------------------------------------------*/
88
89MpiParallelMngBuildInfo::
90MpiParallelMngBuildInfo(MPI_Comm comm)
91: is_parallel(false)
92, comm_rank(MessagePassing::A_NULL_RANK)
93, comm_nb_rank(0)
94, stat(nullptr)
95, trace_mng(nullptr)
96, timer_mng(nullptr)
97, thread_mng(nullptr)
98, mpi_comm(comm)
99, is_mpi_comm_owned(true)
100, mpi_lock(nullptr)
101{
102 ::MPI_Comm_rank(comm,&comm_rank);
103 ::MPI_Comm_size(comm,&comm_nb_rank);
104
105 m_dispatchers_ref = createRef<MP::Dispatchers>();
106 MP::Mpi::MpiMessagePassingMng::BuildInfo bi(comm_rank,comm_nb_rank,m_dispatchers_ref.get(),mpi_comm);
107
108 m_message_passing_mng_ref = createRef<MP::Mpi::MpiMessagePassingMng>(bi);
109}
110
111/*---------------------------------------------------------------------------*/
112/*---------------------------------------------------------------------------*/
113
114/*---------------------------------------------------------------------------*/
115/*---------------------------------------------------------------------------*/
121{
122 public:
124 : m_mpi_parallel_mng(pm){}
126 {
127 _checkFreeCommunicator();
128 }
129 MPI_Comm communicator() const override
130 {
131 return m_topology_communicator;
132 }
134 {
135 Int32ConstArrayView comm_ranks = var_syncer->communicatingRanks();
136 const Int32 nb_message = comm_ranks.size();
137
138 MpiParallelMng* pm = m_mpi_parallel_mng;
139
141
143 for( Integer i=0; i<nb_message; ++i ){
144 destinations[i] = comm_ranks[i];
145 }
146
147 _checkFreeCommunicator();
148
151 MPI_INFO_NULL, 0, &m_topology_communicator);
152
153 if (r!=MPI_SUCCESS)
154 ARCANE_FATAL("Error '{0}' in MPI_Dist_graph_create",r);
155
156 // Vérifie que l'ordre des rangs pour l'implémentation MPI est le même que celui qu'on a dans
157 // le VariableSynchronizer.
158 {
159 int indegree = 0;
160 int outdegree = 0;
161 int weighted = 0;
162 MPI_Dist_graph_neighbors_count(m_topology_communicator,&indegree,&outdegree,&weighted);
163
164 if (indegree!=nb_message)
165 ARCANE_FATAL("Bad value '{0}' for 'indegree' (expected={1})",indegree,nb_message);
167 ARCANE_FATAL("Bad value '{0}' for 'outdegree' (expected={1})",outdegree,nb_message);
168
171
173
174 for(int k=0; k<outdegree; ++k){
175 int x = dsts[k];
176 if (x!=comm_ranks[k])
177 ARCANE_FATAL("Invalid destination rank order k={0} v={1} expected={2}",k,x,comm_ranks[k]);
178 }
179
180 for(int k=0; k<indegree; ++k ){
181 int x = srcs[k];
182 if (x!=comm_ranks[k])
183 ARCANE_FATAL("Invalid source rank order k={0} v={1} expected={2}",k,x,comm_ranks[k]);
184 }
185 }
186 }
187
188 private:
189
190 MpiParallelMng* m_mpi_parallel_mng = nullptr;
191 MPI_Comm m_topology_communicator = MPI_COMM_NULL;
192
193 private:
194
195 void _checkFreeCommunicator()
196 {
197 if (m_topology_communicator!=MPI_COMM_NULL)
198 MPI_Comm_free(&m_topology_communicator);
199 m_topology_communicator = MPI_COMM_NULL;
200 }
201};
202
203/*---------------------------------------------------------------------------*/
204/*---------------------------------------------------------------------------*/
213{
214 public:
219 , m_topology_info(topology_info)
220 {
221 }
222 public:
223 void compute() override
224 {
225 VariableSynchronizer::compute();
226 // Si non nul, calcule la topologie
227 if (m_topology_info.get())
228 m_topology_info->compute(this);
229 }
230 private:
232};
233
234/*---------------------------------------------------------------------------*/
235/*---------------------------------------------------------------------------*/
236
239{
240 public:
242 : m_synchronizer_version(2)
243 {
244 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="1")
245 m_synchronizer_version = 1;
246 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="2")
247 m_synchronizer_version = 2;
248 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="3")
249 m_synchronizer_version = 3;
250 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="4"){
251 m_synchronizer_version = 4;
252 String v = platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_BLOCK_SIZE");
253 if (!v.null()){
254 Int32 block_size = 0;
255 if (!builtInGetValue(block_size,v))
256 m_synchronize_block_size = block_size;
257 m_synchronize_block_size = std::clamp(m_synchronize_block_size,0,1000000000);
258 }
259 v = platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_NB_SEQUENCE");
260 if (!v.null()){
261 Int32 nb_sequence = 0;
262 if (!builtInGetValue(nb_sequence,v))
263 m_synchronize_nb_sequence = nb_sequence;
264 m_synchronize_nb_sequence = std::clamp(m_synchronize_nb_sequence,1,1024*1024);
265 }
266 }
267 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="5")
268 m_synchronizer_version = 5;
269 }
270 public:
271
273 {
274 return _createSynchronizer(pm,family->allItems());
275 }
276
278 {
279 return _createSynchronizer(pm,group);
280 }
281
282 private:
283
284 Ref<IVariableSynchronizer> _createSynchronizer(IParallelMng* pm,const ItemGroup& group)
285 {
288 ITraceMng* tm = pm->traceMng();
290 // N'affiche les informations que pour le groupe de toutes les mailles pour éviter d'afficher
291 // plusieurs fois le même message.
292 bool do_print = (group.isAllItems() && group.itemKind()==IK_Cell);
293 if (m_synchronizer_version == 2){
294 if (do_print)
295 tm->info() << "Using MpiSynchronizer V2";
296 generic_factory = arcaneCreateMpiVariableSynchronizerFactory(mpi_pm);
297 }
298 else if (m_synchronizer_version == 3 ){
299 if (do_print)
300 tm->info() << "Using MpiSynchronizer V3";
301 generic_factory = arcaneCreateMpiDirectSendrecvVariableSynchronizerFactory(mpi_pm);
302 }
303 else if (m_synchronizer_version == 4){
304 if (do_print)
305 tm->info() << "Using MpiSynchronizer V4 block_size=" << m_synchronize_block_size
306 << " nb_sequence=" << m_synchronize_nb_sequence;
307 generic_factory = arcaneCreateMpiBlockVariableSynchronizerFactory(mpi_pm,m_synchronize_block_size,m_synchronize_nb_sequence);
308 }
309 else if (m_synchronizer_version == 5){
310 if (do_print)
311 tm->info() << "Using MpiSynchronizer V5";
313#if defined(ARCANE_HAS_MPI_NEIGHBOR)
314 generic_factory = arcaneCreateMpiNeighborVariableSynchronizerFactory(mpi_pm,topology_info);
315#else
316 throw NotSupportedException(A_FUNCINFO,"Synchronize implementation V5 is not supported with this version of MPI");
317#endif
318 }
319 else{
320 if (do_print)
321 tm->info() << "Using MpiSynchronizer V1";
322 generic_factory = arcaneCreateMpiLegacyVariableSynchronizerFactory(mpi_pm);
323 }
324 if (!generic_factory.get())
325 ARCANE_FATAL("No factory created");
327 }
328
329 private:
330
331 Integer m_synchronizer_version = 1;
332 Int32 m_synchronize_block_size = 32000;
333 Int32 m_synchronize_nb_sequence = 1;
334};
335
336/*---------------------------------------------------------------------------*/
337/*---------------------------------------------------------------------------*/
338
339/*---------------------------------------------------------------------------*/
340/*---------------------------------------------------------------------------*/
341
342MpiParallelMng::
343MpiParallelMng(const MpiParallelMngBuildInfo& bi)
344: ParallelMngDispatcher(ParallelMngDispatcherBuildInfo(bi.dispatchersRef(),bi.messagePassingMngRef()))
345, m_trace(bi.trace_mng)
346, m_thread_mng(bi.thread_mng)
347, m_world_parallel_mng(bi.world_parallel_mng)
348, m_timer_mng(bi.timer_mng)
349, m_replication(new ParallelReplication())
350, m_is_parallel(bi.is_parallel)
351, m_comm_rank(bi.commRank())
352, m_comm_size(bi.commSize())
353, m_stat(bi.stat)
354, m_communicator(bi.mpiComm())
355, m_is_communicator_owned(bi.is_mpi_comm_owned)
356, m_mpi_lock(bi.mpi_lock)
357, m_non_blocking_collective(nullptr)
358, m_utils_factory(createRef<MpiParallelMngUtilsFactory>())
359{
360 if (!m_world_parallel_mng){
361 m_trace->debug()<<"[MpiParallelMng] No m_world_parallel_mng found, reverting to ourselves!";
362 m_world_parallel_mng = this;
363 }
364}
365
366/*---------------------------------------------------------------------------*/
367/*---------------------------------------------------------------------------*/
368
369MpiParallelMng::
370~MpiParallelMng()
371{
372 delete m_non_blocking_collective;
373 m_sequential_parallel_mng.reset();
374 if (m_is_communicator_owned){
375 MpiLock::Section ls(m_mpi_lock);
376 MPI_Comm_free(&m_communicator);
377 }
378 delete m_replication;
379 delete m_io_mng;
380 if (m_is_timer_owned)
381 delete m_timer_mng;
382 arcaneCallFunctionAndTerminateIfThrow([&]() { m_adapter->destroy(); });
383 delete m_datatype_list;
384}
385
386/*---------------------------------------------------------------------------*/
387/*---------------------------------------------------------------------------*/
388
389namespace
390{
391
392/*---------------------------------------------------------------------------*/
393/*---------------------------------------------------------------------------*/
394// Classe pour créer les différents dispatchers
395class DispatchCreator
396{
397 public:
399 : m_tm(tm), m_mpm(mpm), m_adapter(adapter), m_datatype_list(datatype_list){}
400 public:
401 template<typename DataType> MpiParallelDispatchT<DataType>*
402 create()
403 {
404 MpiDatatype* dt = m_datatype_list->datatype(DataType());
405 return new MpiParallelDispatchT<DataType>(m_tm,m_mpm,m_adapter,dt);
406 }
407
408 ITraceMng* m_tm;
409 IMessagePassingMng* m_mpm;
410 MpiAdapter* m_adapter;
411 MpiDatatypeList* m_datatype_list;
412};
413
414/*---------------------------------------------------------------------------*/
415/*---------------------------------------------------------------------------*/
416
417class ControlDispatcherDecorator
419{
420 public:
421
422 ControlDispatcherDecorator(IParallelMng* pm, MpiAdapter* adapter)
423 : ParallelMngDispatcher::DefaultControlDispatcher(pm), m_adapter(adapter) {}
424
425 IMessagePassingMng* commSplit(bool keep) override
426 {
427 return m_adapter->commSplit(keep);
428 }
429 MP::IProfiler* profiler() const override { return m_adapter->profiler(); }
430 void setProfiler(MP::IProfiler* p) override { m_adapter->setProfiler(p); }
431
432 private:
433 MpiAdapter* m_adapter;
434};
435}
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
439
441build()
442{
443 ITraceMng* tm = traceMng();
444 if (!m_timer_mng){
445 m_timer_mng = new MpiTimerMng(tm);
446 m_is_timer_owned = true;
447 }
448
449 // Créé le gestionnaire séquentiel associé.
450 {
452 bi.setTraceMng(traceMng());
453 bi.setCommunicator(communicator());
454 bi.setThreadMng(threadMng());
455 m_sequential_parallel_mng = arcaneCreateSequentialParallelMngRef(bi);
456 }
457
458 // Indique que les reduces doivent être fait dans l'ordre des processeurs
459 // afin de garantir une exécution déterministe
460 bool is_ordered_reduce = false;
461 if (platform::getEnvironmentVariable("ARCANE_ORDERED_REDUCE")=="TRUE")
462 is_ordered_reduce = true;
463 m_datatype_list = new MpiDatatypeList(is_ordered_reduce);
464
465 ARCANE_CHECK_POINTER(m_stat);
466
467 MpiAdapter* adapter = new MpiAdapter(m_trace,m_stat->toArccoreStat(),m_communicator,m_mpi_lock);
468 m_adapter = adapter;
469 auto mpm = _messagePassingMng();
470
471 // NOTE: cette instance sera détruite par le ParallelMngDispatcher
472 auto* control_dispatcher = new ControlDispatcherDecorator(this,m_adapter);
473 _setControlDispatcher(control_dispatcher);
474
475 // NOTE: cette instance sera détruite par le ParallelMngDispatcher
476 auto* serialize_dispatcher = new MpiSerializeDispatcher(m_adapter);
477 m_mpi_serialize_dispatcher = serialize_dispatcher;
478 _setSerializeDispatcher(serialize_dispatcher);
479
480 DispatchCreator creator(m_trace,mpm,m_adapter,m_datatype_list);
481 this->createDispatchers(creator);
482
483 m_io_mng = arcaneCreateIOMng(this);
484
485 m_non_blocking_collective = new MpiParallelNonBlockingCollective(tm,this,adapter);
486 m_non_blocking_collective->build();
487 if (m_mpi_lock)
488 m_trace->info() << "Using mpi with locks.";
489
490 // Utilise par défaut (janvier 2024) la nouvelle implémentation de la sérialisation,
491 // mais on laisse l'ancienne accessible au cas où.
492 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_LIST_VERSION") == "1") {
493 m_use_serialize_list_v2 = false;
494 m_trace->info() << "Using MPI SerializeList version 1";
495 }
496}
497
498/*---------------------------------------------------------------------------*/
499/*---------------------------------------------------------------------------*/
500
501/*----------------------------------------------------------------------------*/
502/*---------------------------------------------------------------------------*/
503
506{
507 Trace::Setter mci(m_trace,"Mpi");
508 if (m_is_initialized){
509 m_trace->warning() << "MpiParallelMng already initialized";
510 return;
511 }
512
513 m_trace->info() << "Initialisation de MpiParallelMng";
514 m_sequential_parallel_mng->initialize();
515
516 m_adapter->setTimeMetricCollector(timeMetricCollector());
517
518 m_is_initialized = true;
519}
520
521/*---------------------------------------------------------------------------*/
522/*---------------------------------------------------------------------------*/
523
524void MpiParallelMng::
525sendSerializer(ISerializer* s,Int32 rank)
526{
527 Trace::Setter mci(m_trace,"Mpi");
528 Timer::Phase tphase(timeStats(),TP_Communication);
530 m_mpi_serialize_dispatcher->legacySendSerializer(s,{MessageRank(rank),mpi_tag,Blocking});
531}
532
533/*---------------------------------------------------------------------------*/
534/*---------------------------------------------------------------------------*/
535
538{
539 auto x = new SerializeMessage(m_comm_rank,rank,ISerializeMessage::MT_Send);
540 return x;
541}
542
543/*---------------------------------------------------------------------------*/
544/*---------------------------------------------------------------------------*/
545
546Request MpiParallelMng::
547sendSerializer(ISerializer* s,Int32 rank,[[maybe_unused]] ByteArray& bytes)
548{
549 Trace::Setter mci(m_trace,"Mpi");
550 Timer::Phase tphase(timeStats(),TP_Communication);
552 return m_mpi_serialize_dispatcher->legacySendSerializer(s,{MessageRank(rank),mpi_tag,NonBlocking});
553}
554
555/*---------------------------------------------------------------------------*/
556/*---------------------------------------------------------------------------*/
557
558void MpiParallelMng::
559broadcastSerializer(ISerializer* values,Int32 rank)
560{
561 Timer::Phase tphase(timeStats(),TP_Communication);
562 m_mpi_serialize_dispatcher->broadcastSerializer(values,MessageRank(rank));
563}
564
565/*---------------------------------------------------------------------------*/
566/*---------------------------------------------------------------------------*/
567
568void MpiParallelMng::
569recvSerializer(ISerializer* values,Int32 rank)
570{
571 Trace::Setter mci(m_trace,"Mpi");
572 Timer::Phase tphase(timeStats(),TP_Communication);
574 m_mpi_serialize_dispatcher->legacyReceiveSerializer(values,MessageRank(rank),mpi_tag);
575}
576
577/*---------------------------------------------------------------------------*/
578/*---------------------------------------------------------------------------*/
579
582{
583 auto x = new SerializeMessage(m_comm_rank,rank,ISerializeMessage::MT_Recv);
584 return x;
585}
586
587/*---------------------------------------------------------------------------*/
588/*---------------------------------------------------------------------------*/
589
591probe(const PointToPointMessageInfo& message) -> MessageId
592{
593 return m_adapter->probeMessage(message);
594}
595
596/*---------------------------------------------------------------------------*/
597/*---------------------------------------------------------------------------*/
598
601{
602 return m_adapter->legacyProbeMessage(message);
603}
604
605/*---------------------------------------------------------------------------*/
606/*---------------------------------------------------------------------------*/
607
608Request MpiParallelMng::
609sendSerializer(const ISerializer* s,const PointToPointMessageInfo& message)
610{
611 return m_mpi_serialize_dispatcher->sendSerializer(s,message);
612}
613
614/*---------------------------------------------------------------------------*/
615/*---------------------------------------------------------------------------*/
616
617Request MpiParallelMng::
618receiveSerializer(ISerializer* s,const PointToPointMessageInfo& message)
619{
620 return m_mpi_serialize_dispatcher->receiveSerializer(s,message);
621}
622
623/*---------------------------------------------------------------------------*/
624/*---------------------------------------------------------------------------*/
625
628{
629 for( Integer i=0, is=requests.size(); i<is; ++i )
630 m_adapter->freeRequest(requests[i]);
631}
632
633/*---------------------------------------------------------------------------*/
634/*---------------------------------------------------------------------------*/
635
636void MpiParallelMng::
637_checkFinishedSubRequests()
638{
639 m_mpi_serialize_dispatcher->checkFinishedSubRequests();
640}
641
642/*---------------------------------------------------------------------------*/
643/*---------------------------------------------------------------------------*/
644
645Ref<IParallelMng> MpiParallelMng::
646sequentialParallelMngRef()
647{
648 return m_sequential_parallel_mng;
649}
650
653{
654 return m_sequential_parallel_mng.get();
655}
656
657/*---------------------------------------------------------------------------*/
658/*---------------------------------------------------------------------------*/
659
662{
663 if (m_stat)
664 m_stat->print(m_trace);
665}
666
667/*---------------------------------------------------------------------------*/
668/*---------------------------------------------------------------------------*/
669
671barrier()
672{
673 traceMng()->flush();
674 m_adapter->barrier();
675}
676
677/*---------------------------------------------------------------------------*/
678/*---------------------------------------------------------------------------*/
679
682{
683 m_adapter->waitAllRequests(requests);
684 _checkFinishedSubRequests();
685}
686
687/*---------------------------------------------------------------------------*/
688/*---------------------------------------------------------------------------*/
689
692{
693 return _waitSomeRequests(requests, false);
694}
695
696/*---------------------------------------------------------------------------*/
697/*---------------------------------------------------------------------------*/
698
701{
702 return _waitSomeRequests(requests, true);
703}
704
705/*---------------------------------------------------------------------------*/
706/*---------------------------------------------------------------------------*/
707
708UniqueArray<Integer> MpiParallelMng::
709_waitSomeRequests(ArrayView<Request> requests, bool is_non_blocking)
710{
712 UniqueArray<bool> done_indexes(requests.size());
713
714 m_adapter->waitSomeRequests(requests, done_indexes, is_non_blocking);
715 for (int i = 0 ; i < requests.size() ; i++) {
716 if (done_indexes[i])
717 results.add(i);
718 }
719 return results;
720}
721
722/*---------------------------------------------------------------------------*/
723/*---------------------------------------------------------------------------*/
724
725ISerializeMessageList* MpiParallelMng::
726_createSerializeMessageList()
727{
728 if (m_use_serialize_list_v2)
729 return new MP::internal::SerializeMessageList(messagePassingMng());
730 return new MpiSerializeMessageList(serializeDispatcher());
731}
732
733/*---------------------------------------------------------------------------*/
734/*---------------------------------------------------------------------------*/
735
738{
739 return m_utils_factory->createGetVariablesValuesOperation(this)._release();
740}
741
742/*---------------------------------------------------------------------------*/
743/*---------------------------------------------------------------------------*/
744
747{
748 return m_utils_factory->createTransferValuesOperation(this)._release();
749}
750
751/*---------------------------------------------------------------------------*/
752/*---------------------------------------------------------------------------*/
753
756{
757 return m_utils_factory->createExchanger(this)._release();
758}
759
760/*---------------------------------------------------------------------------*/
761/*---------------------------------------------------------------------------*/
762
765{
766 return m_utils_factory->createSynchronizer(this,family)._release();
767}
768
769/*---------------------------------------------------------------------------*/
770/*---------------------------------------------------------------------------*/
771
773createSynchronizer(const ItemGroup& group)
774{
775 return m_utils_factory->createSynchronizer(this,group)._release();
776}
777
778/*---------------------------------------------------------------------------*/
779/*---------------------------------------------------------------------------*/
780
783{
784 return m_utils_factory->createTopology(this)._release();
785}
786
787/*---------------------------------------------------------------------------*/
788/*---------------------------------------------------------------------------*/
789
791replication() const
792{
793 return m_replication;
794}
795
796/*---------------------------------------------------------------------------*/
797/*---------------------------------------------------------------------------*/
798
801{
802 delete m_replication;
803 m_replication = v;
804}
805
806/*---------------------------------------------------------------------------*/
807/*---------------------------------------------------------------------------*/
808
809IParallelMng* MpiParallelMng::
810_createSubParallelMng(MPI_Comm sub_communicator)
811{
812 // Si nul, ce rang ne fait pas partie du sous-communicateur
814 return nullptr;
815
816 int sub_rank = -1;
818
820 bi.is_parallel = isParallel();
821 bi.stat = m_stat;
822 bi.timer_mng = m_timer_mng;
823 bi.thread_mng = m_thread_mng;
824 bi.trace_mng = m_trace;
825 bi.world_parallel_mng = m_world_parallel_mng;
826 bi.mpi_lock = m_mpi_lock;
827
829 sub_pm->build();
830 return sub_pm;
831}
832
833/*---------------------------------------------------------------------------*/
834/*---------------------------------------------------------------------------*/
835
836Ref<IParallelMng> MpiParallelMng::
837_createSubParallelMngRef(Int32 color, Int32 key)
838{
839 if (color < 0)
840 color = MPI_UNDEFINED;
842 MPI_Comm_split(m_communicator, color, key, &sub_communicator);
843 IParallelMng* sub_pm = _createSubParallelMng(sub_communicator);
844 return makeRef(sub_pm);
845}
846
847/*---------------------------------------------------------------------------*/
848/*---------------------------------------------------------------------------*/
849
850IParallelMng* MpiParallelMng::
851_createSubParallelMng(Int32ConstArrayView kept_ranks)
852{
854 MPI_Comm_group(m_communicator, &mpi_group);
857 for (Integer i = 0; i < nb_sub_rank; ++i)
858 mpi_kept_ranks[i] = (int)kept_ranks[i];
859
863
866 return _createSubParallelMng(sub_communicator);
867}
868
869/*---------------------------------------------------------------------------*/
870/*---------------------------------------------------------------------------*/
879: public MpiRequestList
880{
881 using Base = MpiRequestList;
882 public:
883 explicit RequestList(MpiParallelMng* pm)
884 : Base(pm->m_adapter), m_parallel_mng(pm){}
885 public:
887 {
889 m_parallel_mng->_checkFinishedSubRequests();
890 };
891 private:
892 MpiParallelMng* m_parallel_mng;
893};
894
895/*---------------------------------------------------------------------------*/
896/*---------------------------------------------------------------------------*/
897
903
904/*---------------------------------------------------------------------------*/
905/*---------------------------------------------------------------------------*/
906
909{
910 return m_utils_factory;
911}
912
913/*---------------------------------------------------------------------------*/
914/*---------------------------------------------------------------------------*/
915
916bool MpiParallelMng::
917_isAcceleratorAware() const
918{
920}
921
922/*---------------------------------------------------------------------------*/
923/*---------------------------------------------------------------------------*/
924
925} // End namespace Arcane
926
927/*---------------------------------------------------------------------------*/
928/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Liste des fonctions d'échange de message.
Tableau d'items de types quelconques.
Opérations pour accéder aux valeurs de variables d'un autre sous-domaine.
Interface du gestionnaire des entrées sorties.
Definition IIOMng.h:42
Interface d'une famille d'entités.
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
Echange d'informations entre processeurs.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual Parallel::Communicator communicator() const =0
Communicateur MPI associé à ce gestionnaire.
virtual void build()=0
Construit l'instance.
Informations sur la réplication des sous-domaines en parallèle.
Informations sur la topologie d'allocation des coeurs de calcul.
Envoie de valeurs sur différents processeurs.
Interface d'un communicateur MPI spécifique pour les synchronisations.
Interface d'un service de synchronisation de variable.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
eItemKind itemKind() const
Genre du groupe. Il s'agit du genre de ses éléments.
Definition ItemGroup.h:109
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
Definition ItemGroup.cc:609
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
void destroy()
Détruit l'instance. Elle ne doit plus être utilisée par la suite.
Request receiveSerializer(ISerializer *s, const PointToPointMessageInfo &message) override
Message de réception.
Request sendSerializer(const ISerializer *s, const PointToPointMessageInfo &message) override
Message d'envoi.
Gère les MPI_Datatype associées aux types Arcane.
Ref< IVariableSynchronizer > createSynchronizer(IParallelMng *pm, IItemFamily *family) override
Retourne une interface pour synchroniser des variables sur le groupe de la famille family.
Ref< IVariableSynchronizer > createSynchronizer(IParallelMng *pm, const ItemGroup &group) override
Retourne une interface pour synchroniser des variables sur le groupe group.
Spécialisation de MpiRequestList pour MpiParallelMng.
void _wait(Parallel::eWaitType wait_type) override
Effectue l'attente ou le test.
Gestionnaire du parallélisme utilisant MPI.
IParallelMng * worldParallelMng() const override
Gestionnaire de parallélisme sur l'ensemble des ressources allouées.
MessageSourceInfo legacyProbe(const PointToPointMessageInfo &message) override
Sonde si des messages sont disponibles.
void barrier() override
Effectue une barière.
UniqueArray< Integer > waitSomeRequests(ArrayView< Request > requests) override
Bloque en attendant qu'une des requêtes rvalues soit terminée.
void waitAllRequests(ArrayView< Request > requests) override
Bloque en attendant que les requêtes rvalues soient terminées.
MessageId probe(const PointToPointMessageInfo &message) override
Sonde si des messages sont disponibles.
void build() override
Construit l'instance.
void printStats() override
Affiche des statistiques liées à ce gestionnaire du parallélisme.
bool m_is_initialized
true si déjà initialisé
IParallelMng * sequentialParallelMng() override
Retourne un gestionnaire de parallélisme séquentiel.
IThreadMng * threadMng() const override
Gestionnaire de threads.
ITimerMng * timerMng() const override
Gestionnaire de timers.
void initialize() override
Initialise le gestionnaire du parallélisme.
IVariableSynchronizer * createSynchronizer(IItemFamily *family) override
Retourne une interface pour synchroniser des variables sur le groupe de la famille family.
ISerializeMessage * createSendSerializer(Int32 rank) override
Créé un message non bloquant pour envoyer des données sérialisées au rang rank.
bool isParallel() const override
Retourne true si l'exécution est parallèle.
Ref< IParallelMngUtilsFactory > _internalUtilsFactory() const override
Fabrique des fonctions utilitaires.
ITraceMng * traceMng() const override
Gestionnaire de traces.
IParallelTopology * createTopology() override
Créé une instance contenant les infos sur la topologie des rangs de ce gestionnnaire.
Int32 m_comm_rank
Numéro du processeur actuel.
Communicator communicator() const override
Communicateur MPI associé à ce gestionnaire.
IParallelExchanger * createExchanger() override
Retourne une interface pour transférer des messages entre processeurs.
IParallelReplication * replication() const override
Informations sur la réplication.
void setReplication(IParallelReplication *v) override
Positionne les Informations sur la réplication.
Ref< Parallel::IRequestList > createRequestListRef() override
Créé une liste de requêtes pour ce gestionnaire.
ITransferValuesParallelOperation * createTransferValuesOperation() override
Retourne une opération pour transférer des valeurs entre sous-domaine.
UniqueArray< Integer > testSomeRequests(ArrayView< Request > requests) override
Test si une des requêtes rvalues est terminée.
IGetVariablesValuesParallelOperation * createGetVariablesValuesOperation() override
Retourne une opération pour récupérer les valeurs d'une variable sur les entités d'un autre sous-doma...
ISerializeMessage * createReceiveSerializer(Int32 rank) override
Créé un message non bloquant pour recevoir des données sérialisées du rang rank.
void freeRequests(ArrayView< Parallel::Request > requests) override
Libère les requêtes.
Gestionnaire du parallélisme utilisant MPI.
Gestionnaire de timer utisant la bibliothèque MPI.
Definition MpiTimerMng.h:39
Synchronizer spécifique MPI.
void compute() override
Recalcule les infos de synchronisation.
Implémentation de Arccore::MessagePassing::IControlDispatcher.
Redirige la gestion des messages des sous-domaines suivant le type de l'argument.
IMessagePassingMng * messagePassingMng() const override
Gestionnaire de message de Arccore associé
ITimeMetricCollector * timeMetricCollector() const override
Collecteur Arccore des statistiques temporelles (peut être nul)
ITimeStats * timeStats() const override
Gestionnaire de statistiques associé (peut être nul)
Classe de base d'une fabrique pour les fonctions utilitaires de IParallelMng.
Informations sur la réplication des sous-domaines en parallèle.
virtual void print(ITraceMng *trace)=0
Imprime sur trace les statistiques.
Message utilisant un SerializeBuffer.
Positionne la phase de l'action en cours d'exécution.
Definition Timer.h:128
Communicateur spécifique créé via MPI_Dist_graph_create_adjacent.
MPI_Comm communicator() const override
Récupère le communicateur spécifique de la topologie.
void compute(VariableSynchronizer *var_syncer) override
Calcul le communicateur spécifique.
Interface d'un service de synchronisation de variable.
Vue constante d'un tableau de type T.
Interface du gestionnaire de traces.
virtual TraceMessage warning()=0
Flot pour un message d'avertissement.
virtual TraceMessage info()=0
Flot pour un message d'information.
virtual void flush()=0
Flush tous les flots.
Interface du gestionnaire des échanges de messages.
Interface d'un profiler pour les échanges de messages.
Definition IProfiler.h:31
Informations sur la source d'un message.
void _wait(eWaitType wait_type) override
Effectue l'attente ou le test.
Informations pour envoyer/recevoir un message point à point.
Requête d'un message.
Definition Request.h:77
static MessageTag defaultTag()
Tag par défaut pour les messages de sérialisation.
Exception lorsqu'une opération n'est pas supportée.
Chaîne de caractères unicode.
bool null() const
Retourne true si la chaîne est nulle.
Definition String.cc:304
TraceMessage info() const
Flot pour un message d'information.
Positionne une classe de message.
Déclarations des types et méthodes utilisés par les mécanismes d'échange de messages.
Definition Parallel.h:50
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
ARCANE_MPI_EXPORT bool arcaneIsAcceleratorAwareMPI()
Indique si le runtime actuel de MPI a le support des accélérateurs.
Definition ArcaneMpi.cc:82
@ IK_Cell
Entité de maillage de genre maille.
void arcaneCallFunctionAndTerminateIfThrow(std::function< void()> function)
Int32 Integer
Type représentant un entier.
Ref< TrueType > createRef(Args &&... args)
Créé une instance de type TrueType avec les arguments Args et retourne une référence dessus.
std::int32_t Int32
Type entier signé sur 32 bits.
Infos pour construire un MpiParallelMng.
Infos pour construire un SequentialParallelMng.