Arcane  v3.14.10.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-2024 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-2024 */
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 Arccore::MessagePassing::Mpi;
63
64/*---------------------------------------------------------------------------*/
65/*---------------------------------------------------------------------------*/
66
67extern "C++" IIOMng*
68arcaneCreateIOMng(IParallelMng* psm);
69
70#if defined(ARCANE_HAS_MPI_NEIGHBOR)
71// Défini dans MpiNeighborVariableSynchronizeDispatcher
73arcaneCreateMpiNeighborVariableSynchronizerFactory(MpiParallelMng* mpi_pm,
75#endif
77arcaneCreateMpiBlockVariableSynchronizerFactory(MpiParallelMng* mpi_pm, Int32 block_size, Int32 nb_sequence);
79arcaneCreateMpiVariableSynchronizerFactory(MpiParallelMng* mpi_pm);
81arcaneCreateMpiDirectSendrecvVariableSynchronizerFactory(MpiParallelMng* mpi_pm);
83arcaneCreateMpiLegacyVariableSynchronizerFactory(MpiParallelMng* mpi_pm);
84
85/*---------------------------------------------------------------------------*/
86/*---------------------------------------------------------------------------*/
87
88MpiParallelMngBuildInfo::
89MpiParallelMngBuildInfo(MPI_Comm comm)
90: is_parallel(false)
91, comm_rank(A_NULL_RANK)
92, comm_nb_rank(0)
93, stat(nullptr)
94, trace_mng(nullptr)
95, timer_mng(nullptr)
96, thread_mng(nullptr)
97, mpi_comm(comm)
98, is_mpi_comm_owned(true)
99, mpi_lock(nullptr)
100{
101 ::MPI_Comm_rank(comm,&comm_rank);
102 ::MPI_Comm_size(comm,&comm_nb_rank);
103
104 m_dispatchers_ref = createRef<MP::Dispatchers>();
105 MP::Mpi::MpiMessagePassingMng::BuildInfo bi(comm_rank,comm_nb_rank,m_dispatchers_ref.get(),mpi_comm);
106
107 m_message_passing_mng_ref = createRef<MP::Mpi::MpiMessagePassingMng>(bi);
108}
109
110/*---------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------*/
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
120{
121 public:
123 : m_mpi_parallel_mng(pm){}
125 {
126 _checkFreeCommunicator();
127 }
128 MPI_Comm communicator() const override
129 {
130 return m_topology_communicator;
131 }
133 {
134 Int32ConstArrayView comm_ranks = var_syncer->communicatingRanks();
135 const Int32 nb_message = comm_ranks.size();
136
137 MpiParallelMng* pm = m_mpi_parallel_mng;
138
140
142 for( Integer i=0; i<nb_message; ++i ){
143 destinations[i] = comm_ranks[i];
144 }
145
146 _checkFreeCommunicator();
147
150 MPI_INFO_NULL, 0, &m_topology_communicator);
151
152 if (r!=MPI_SUCCESS)
153 ARCANE_FATAL("Error '{0}' in MPI_Dist_graph_create",r);
154
155 // Vérifie que l'ordre des rangs pour l'implémentation MPI est le même que celui qu'on a dans
156 // le VariableSynchronizer.
157 {
158 int indegree = 0;
159 int outdegree = 0;
160 int weighted = 0;
161 MPI_Dist_graph_neighbors_count(m_topology_communicator,&indegree,&outdegree,&weighted);
162
163 if (indegree!=nb_message)
164 ARCANE_FATAL("Bad value '{0}' for 'indegree' (expected={1})",indegree,nb_message);
166 ARCANE_FATAL("Bad value '{0}' for 'outdegree' (expected={1})",outdegree,nb_message);
167
170
172
173 for(int k=0; k<outdegree; ++k){
174 int x = dsts[k];
175 if (x!=comm_ranks[k])
176 ARCANE_FATAL("Invalid destination rank order k={0} v={1} expected={2}",k,x,comm_ranks[k]);
177 }
178
179 for(int k=0; k<indegree; ++k ){
180 int x = srcs[k];
181 if (x!=comm_ranks[k])
182 ARCANE_FATAL("Invalid source rank order k={0} v={1} expected={2}",k,x,comm_ranks[k]);
183 }
184 }
185 }
186
187 private:
188
189 MpiParallelMng* m_mpi_parallel_mng = nullptr;
190 MPI_Comm m_topology_communicator = MPI_COMM_NULL;
191
192 private:
193
194 void _checkFreeCommunicator()
195 {
196 if (m_topology_communicator!=MPI_COMM_NULL)
197 MPI_Comm_free(&m_topology_communicator);
198 m_topology_communicator = MPI_COMM_NULL;
199 }
200};
201
202/*---------------------------------------------------------------------------*/
203/*---------------------------------------------------------------------------*/
212{
213 public:
218 , m_topology_info(topology_info)
219 {
220 }
221 public:
222 void compute() override
223 {
224 VariableSynchronizer::compute();
225 // Si non nul, calcule la topologie
226 if (m_topology_info.get())
227 m_topology_info->compute(this);
228 }
229 private:
231};
232
233/*---------------------------------------------------------------------------*/
234/*---------------------------------------------------------------------------*/
235
238{
239 public:
241 : m_synchronizer_version(2)
242 {
243 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="1")
244 m_synchronizer_version = 1;
245 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="2")
246 m_synchronizer_version = 2;
247 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="3")
248 m_synchronizer_version = 3;
249 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="4"){
250 m_synchronizer_version = 4;
251 String v = platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_BLOCK_SIZE");
252 if (!v.null()){
253 Int32 block_size = 0;
254 if (!builtInGetValue(block_size,v))
255 m_synchronize_block_size = block_size;
256 m_synchronize_block_size = std::clamp(m_synchronize_block_size,0,1000000000);
257 }
258 v = platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_NB_SEQUENCE");
259 if (!v.null()){
260 Int32 nb_sequence = 0;
261 if (!builtInGetValue(nb_sequence,v))
262 m_synchronize_nb_sequence = nb_sequence;
263 m_synchronize_nb_sequence = std::clamp(m_synchronize_nb_sequence,1,1024*1024);
264 }
265 }
266 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_VERSION")=="5")
267 m_synchronizer_version = 5;
268 }
269 public:
270
272 {
273 return _createSynchronizer(pm,family->allItems());
274 }
275
277 {
278 return _createSynchronizer(pm,group);
279 }
280
281 private:
282
283 Ref<IVariableSynchronizer> _createSynchronizer(IParallelMng* pm,const ItemGroup& group)
284 {
287 ITraceMng* tm = pm->traceMng();
289 // N'affiche les informations que pour le groupe de toutes les mailles pour éviter d'afficher
290 // plusieurs fois le même message.
291 bool do_print = (group.isAllItems() && group.itemKind()==IK_Cell);
292 if (m_synchronizer_version == 2){
293 if (do_print)
294 tm->info() << "Using MpiSynchronizer V2";
295 generic_factory = arcaneCreateMpiVariableSynchronizerFactory(mpi_pm);
296 }
297 else if (m_synchronizer_version == 3 ){
298 if (do_print)
299 tm->info() << "Using MpiSynchronizer V3";
300 generic_factory = arcaneCreateMpiDirectSendrecvVariableSynchronizerFactory(mpi_pm);
301 }
302 else if (m_synchronizer_version == 4){
303 if (do_print)
304 tm->info() << "Using MpiSynchronizer V4 block_size=" << m_synchronize_block_size
305 << " nb_sequence=" << m_synchronize_nb_sequence;
306 generic_factory = arcaneCreateMpiBlockVariableSynchronizerFactory(mpi_pm,m_synchronize_block_size,m_synchronize_nb_sequence);
307 }
308 else if (m_synchronizer_version == 5){
309 if (do_print)
310 tm->info() << "Using MpiSynchronizer V5";
312#if defined(ARCANE_HAS_MPI_NEIGHBOR)
313 generic_factory = arcaneCreateMpiNeighborVariableSynchronizerFactory(mpi_pm,topology_info);
314#else
315 throw NotSupportedException(A_FUNCINFO,"Synchronize implementation V5 is not supported with this version of MPI");
316#endif
317 }
318 else{
319 if (do_print)
320 tm->info() << "Using MpiSynchronizer V1";
321 generic_factory = arcaneCreateMpiLegacyVariableSynchronizerFactory(mpi_pm);
322 }
323 if (!generic_factory.get())
324 ARCANE_FATAL("No factory created");
326 }
327
328 private:
329
330 Integer m_synchronizer_version = 1;
331 Int32 m_synchronize_block_size = 32000;
332 Int32 m_synchronize_nb_sequence = 1;
333};
334
335/*---------------------------------------------------------------------------*/
336/*---------------------------------------------------------------------------*/
337
338/*---------------------------------------------------------------------------*/
339/*---------------------------------------------------------------------------*/
340
341MpiParallelMng::
342MpiParallelMng(const MpiParallelMngBuildInfo& bi)
343: ParallelMngDispatcher(ParallelMngDispatcherBuildInfo(bi.dispatchersRef(),bi.messagePassingMngRef()))
344, m_trace(bi.trace_mng)
345, m_thread_mng(bi.thread_mng)
346, m_world_parallel_mng(bi.world_parallel_mng)
347, m_timer_mng(bi.timer_mng)
348, m_replication(new ParallelReplication())
349, m_is_parallel(bi.is_parallel)
350, m_comm_rank(bi.commRank())
351, m_comm_size(bi.commSize())
352, m_stat(bi.stat)
353, m_communicator(bi.mpiComm())
354, m_is_communicator_owned(bi.is_mpi_comm_owned)
355, m_mpi_lock(bi.mpi_lock)
356, m_non_blocking_collective(nullptr)
357, m_utils_factory(createRef<MpiParallelMngUtilsFactory>())
358{
359 if (!m_world_parallel_mng){
360 m_trace->debug()<<"[MpiParallelMng] No m_world_parallel_mng found, reverting to ourselves!";
361 m_world_parallel_mng = this;
362 }
363}
364
365/*---------------------------------------------------------------------------*/
366/*---------------------------------------------------------------------------*/
367
368MpiParallelMng::
369~MpiParallelMng()
370{
371 delete m_non_blocking_collective;
372 m_sequential_parallel_mng.reset();
373 if (m_is_communicator_owned){
374 MpiLock::Section ls(m_mpi_lock);
375 MPI_Comm_free(&m_communicator);
376 }
377 delete m_replication;
378 delete m_io_mng;
379 if (m_is_timer_owned)
380 delete m_timer_mng;
381 arcaneCallFunctionAndTerminateIfThrow([&]() { m_adapter->destroy(); });
382 delete m_datatype_list;
383}
384
385/*---------------------------------------------------------------------------*/
386/*---------------------------------------------------------------------------*/
387
388namespace
389{
390
391/*---------------------------------------------------------------------------*/
392/*---------------------------------------------------------------------------*/
393// Classe pour créer les différents dispatchers
394class DispatchCreator
395{
396 public:
398 : m_tm(tm), m_mpm(mpm), m_adapter(adapter), m_datatype_list(datatype_list){}
399 public:
400 template<typename DataType> MpiParallelDispatchT<DataType>*
401 create()
402 {
403 MpiDatatype* dt = m_datatype_list->datatype(DataType());
404 return new MpiParallelDispatchT<DataType>(m_tm,m_mpm,m_adapter,dt);
405 }
406
407 ITraceMng* m_tm;
408 IMessagePassingMng* m_mpm;
409 MpiAdapter* m_adapter;
410 MpiDatatypeList* m_datatype_list;
411};
412
413/*---------------------------------------------------------------------------*/
414/*---------------------------------------------------------------------------*/
415
416class ControlDispatcherDecorator
418{
419 public:
420
421 ControlDispatcherDecorator(IParallelMng* pm, MpiAdapter* adapter)
422 : ParallelMngDispatcher::DefaultControlDispatcher(pm), m_adapter(adapter) {}
423
424 IMessagePassingMng* commSplit(bool keep) override
425 {
426 return m_adapter->commSplit(keep);
427 }
428 MP::IProfiler* profiler() const override { return m_adapter->profiler(); }
429 void setProfiler(MP::IProfiler* p) override { m_adapter->setProfiler(p); }
430
431 private:
432 MpiAdapter* m_adapter;
433};
434}
435
436/*---------------------------------------------------------------------------*/
437/*---------------------------------------------------------------------------*/
438
440build()
441{
442 ITraceMng* tm = traceMng();
443 if (!m_timer_mng){
444 m_timer_mng = new MpiTimerMng(tm);
445 m_is_timer_owned = true;
446 }
447
448 // Créé le gestionnaire séquentiel associé.
449 {
451 bi.setTraceMng(traceMng());
452 bi.setCommunicator(communicator());
453 bi.setThreadMng(threadMng());
454 m_sequential_parallel_mng = arcaneCreateSequentialParallelMngRef(bi);
455 }
456
457 // Indique que les reduces doivent être fait dans l'ordre des processeurs
458 // afin de garantir une exécution déterministe
459 bool is_ordered_reduce = false;
460 if (platform::getEnvironmentVariable("ARCANE_ORDERED_REDUCE")=="TRUE")
461 is_ordered_reduce = true;
462 m_datatype_list = new MpiDatatypeList(is_ordered_reduce);
463
464 ARCANE_CHECK_POINTER(m_stat);
465
466 MpiAdapter* adapter = new MpiAdapter(m_trace,m_stat->toArccoreStat(),m_communicator,m_mpi_lock);
467 m_adapter = adapter;
468 auto mpm = _messagePassingMng();
469
470 // NOTE: cette instance sera détruite par le ParallelMngDispatcher
471 auto* control_dispatcher = new ControlDispatcherDecorator(this,m_adapter);
472 _setControlDispatcher(control_dispatcher);
473
474 // NOTE: cette instance sera détruite par le ParallelMngDispatcher
475 auto* serialize_dispatcher = new MpiSerializeDispatcher(m_adapter);
476 m_mpi_serialize_dispatcher = serialize_dispatcher;
477 _setSerializeDispatcher(serialize_dispatcher);
478
479 DispatchCreator creator(m_trace,mpm,m_adapter,m_datatype_list);
480 this->createDispatchers(creator);
481
482 m_io_mng = arcaneCreateIOMng(this);
483
484 m_non_blocking_collective = new MpiParallelNonBlockingCollective(tm,this,adapter);
485 m_non_blocking_collective->build();
486 if (m_mpi_lock)
487 m_trace->info() << "Using mpi with locks.";
488
489 // Utilise par défaut (janvier 2024) la nouvelle implémentation de la sérialisation,
490 // mais on laisse l'ancienne accessible au cas où.
491 if (platform::getEnvironmentVariable("ARCANE_SYNCHRONIZE_LIST_VERSION") == "1") {
492 m_use_serialize_list_v2 = false;
493 m_trace->info() << "Using MPI SerializeList version 1";
494 }
495}
496
497/*---------------------------------------------------------------------------*/
498/*---------------------------------------------------------------------------*/
499
500/*----------------------------------------------------------------------------*/
501/*---------------------------------------------------------------------------*/
502
505{
506 Trace::Setter mci(m_trace,"Mpi");
507 if (m_is_initialized){
508 m_trace->warning() << "MpiParallelMng already initialized";
509 return;
510 }
511
512 m_trace->info() << "Initialisation de MpiParallelMng";
513 m_sequential_parallel_mng->initialize();
514
515 m_adapter->setTimeMetricCollector(timeMetricCollector());
516
517 m_is_initialized = true;
518}
519
520/*---------------------------------------------------------------------------*/
521/*---------------------------------------------------------------------------*/
522
523void MpiParallelMng::
524sendSerializer(ISerializer* s,Int32 rank)
525{
526 Trace::Setter mci(m_trace,"Mpi");
527 Timer::Phase tphase(timeStats(),TP_Communication);
529 m_mpi_serialize_dispatcher->legacySendSerializer(s,{MessageRank(rank),mpi_tag,Blocking});
530}
531
532/*---------------------------------------------------------------------------*/
533/*---------------------------------------------------------------------------*/
534
536createSendSerializer(Int32 rank)
537{
538 auto x = new SerializeMessage(m_comm_rank,rank,ISerializeMessage::MT_Send);
539 return x;
540}
541
542/*---------------------------------------------------------------------------*/
543/*---------------------------------------------------------------------------*/
544
545Request MpiParallelMng::
546sendSerializer(ISerializer* s,Int32 rank,[[maybe_unused]] ByteArray& bytes)
547{
548 Trace::Setter mci(m_trace,"Mpi");
549 Timer::Phase tphase(timeStats(),TP_Communication);
551 return m_mpi_serialize_dispatcher->legacySendSerializer(s,{MessageRank(rank),mpi_tag,NonBlocking});
552}
553
554/*---------------------------------------------------------------------------*/
555/*---------------------------------------------------------------------------*/
556
557void MpiParallelMng::
558broadcastSerializer(ISerializer* values,Int32 rank)
559{
560 Timer::Phase tphase(timeStats(),TP_Communication);
561 m_mpi_serialize_dispatcher->broadcastSerializer(values,MessageRank(rank));
562}
563
564/*---------------------------------------------------------------------------*/
565/*---------------------------------------------------------------------------*/
566
567void MpiParallelMng::
568recvSerializer(ISerializer* values,Int32 rank)
569{
570 Trace::Setter mci(m_trace,"Mpi");
571 Timer::Phase tphase(timeStats(),TP_Communication);
573 m_mpi_serialize_dispatcher->legacyReceiveSerializer(values,MessageRank(rank),mpi_tag);
574}
575
576/*---------------------------------------------------------------------------*/
577/*---------------------------------------------------------------------------*/
578
580createReceiveSerializer(Int32 rank)
581{
582 auto x = new SerializeMessage(m_comm_rank,rank,ISerializeMessage::MT_Recv);
583 return x;
584}
585
586/*---------------------------------------------------------------------------*/
587/*---------------------------------------------------------------------------*/
588
590probe(const PointToPointMessageInfo& message) -> MessageId
591{
592 return m_adapter->probeMessage(message);
593}
594
595/*---------------------------------------------------------------------------*/
596/*---------------------------------------------------------------------------*/
597
600{
601 return m_adapter->legacyProbeMessage(message);
602}
603
604/*---------------------------------------------------------------------------*/
605/*---------------------------------------------------------------------------*/
606
607Request MpiParallelMng::
608sendSerializer(const ISerializer* s,const PointToPointMessageInfo& message)
609{
610 return m_mpi_serialize_dispatcher->sendSerializer(s,message);
611}
612
613/*---------------------------------------------------------------------------*/
614/*---------------------------------------------------------------------------*/
615
616Request MpiParallelMng::
617receiveSerializer(ISerializer* s,const PointToPointMessageInfo& message)
618{
619 return m_mpi_serialize_dispatcher->receiveSerializer(s,message);
620}
621
622/*---------------------------------------------------------------------------*/
623/*---------------------------------------------------------------------------*/
624
627{
628 for( Integer i=0, is=requests.size(); i<is; ++i )
629 m_adapter->freeRequest(requests[i]);
630}
631
632/*---------------------------------------------------------------------------*/
633/*---------------------------------------------------------------------------*/
634
635void MpiParallelMng::
636_checkFinishedSubRequests()
637{
638 m_mpi_serialize_dispatcher->checkFinishedSubRequests();
639}
640
641/*---------------------------------------------------------------------------*/
642/*---------------------------------------------------------------------------*/
643
644Ref<IParallelMng> MpiParallelMng::
645sequentialParallelMngRef()
646{
647 return m_sequential_parallel_mng;
648}
649
652{
653 return m_sequential_parallel_mng.get();
654}
655
656/*---------------------------------------------------------------------------*/
657/*---------------------------------------------------------------------------*/
658
661{
662 if (m_stat)
663 m_stat->print(m_trace);
664}
665
666/*---------------------------------------------------------------------------*/
667/*---------------------------------------------------------------------------*/
668
670barrier()
671{
672 traceMng()->flush();
673 m_adapter->barrier();
674}
675
676/*---------------------------------------------------------------------------*/
677/*---------------------------------------------------------------------------*/
678
681{
682 m_adapter->waitAllRequests(requests);
683 _checkFinishedSubRequests();
684}
685
686/*---------------------------------------------------------------------------*/
687/*---------------------------------------------------------------------------*/
688
691{
692 return _waitSomeRequests(requests, false);
693}
694
695/*---------------------------------------------------------------------------*/
696/*---------------------------------------------------------------------------*/
697
700{
701 return _waitSomeRequests(requests, true);
702}
703
704/*---------------------------------------------------------------------------*/
705/*---------------------------------------------------------------------------*/
706
707UniqueArray<Integer> MpiParallelMng::
708_waitSomeRequests(ArrayView<Request> requests, bool is_non_blocking)
709{
711 UniqueArray<bool> done_indexes(requests.size());
712
713 m_adapter->waitSomeRequests(requests, done_indexes, is_non_blocking);
714 for (int i = 0 ; i < requests.size() ; i++) {
715 if (done_indexes[i])
716 results.add(i);
717 }
718 return results;
719}
720
721/*---------------------------------------------------------------------------*/
722/*---------------------------------------------------------------------------*/
723
724ISerializeMessageList* MpiParallelMng::
725_createSerializeMessageList()
726{
727 if (m_use_serialize_list_v2)
728 return new MP::internal::SerializeMessageList(messagePassingMng());
729 return new MpiSerializeMessageList(serializeDispatcher());
730}
731
732/*---------------------------------------------------------------------------*/
733/*---------------------------------------------------------------------------*/
734
737{
738 return m_utils_factory->createGetVariablesValuesOperation(this)._release();
739}
740
741/*---------------------------------------------------------------------------*/
742/*---------------------------------------------------------------------------*/
743
746{
747 return m_utils_factory->createTransferValuesOperation(this)._release();
748}
749
750/*---------------------------------------------------------------------------*/
751/*---------------------------------------------------------------------------*/
752
755{
756 return m_utils_factory->createExchanger(this)._release();
757}
758
759/*---------------------------------------------------------------------------*/
760/*---------------------------------------------------------------------------*/
761
764{
765 return m_utils_factory->createSynchronizer(this,family)._release();
766}
767
768/*---------------------------------------------------------------------------*/
769/*---------------------------------------------------------------------------*/
770
772createSynchronizer(const ItemGroup& group)
773{
774 return m_utils_factory->createSynchronizer(this,group)._release();
775}
776
777/*---------------------------------------------------------------------------*/
778/*---------------------------------------------------------------------------*/
779
782{
783 return m_utils_factory->createTopology(this)._release();
784}
785
786/*---------------------------------------------------------------------------*/
787/*---------------------------------------------------------------------------*/
788
790replication() const
791{
792 return m_replication;
793}
794
795/*---------------------------------------------------------------------------*/
796/*---------------------------------------------------------------------------*/
797
800{
801 delete m_replication;
802 m_replication = v;
803}
804
805/*---------------------------------------------------------------------------*/
806/*---------------------------------------------------------------------------*/
807
808IParallelMng* MpiParallelMng::
809_createSubParallelMng(MPI_Comm sub_communicator)
810{
811 // Si nul, ce rang ne fait pas partie du sous-communicateur
813 return nullptr;
814
815 int sub_rank = -1;
817
819 bi.is_parallel = isParallel();
820 bi.stat = m_stat;
821 bi.timer_mng = m_timer_mng;
822 bi.thread_mng = m_thread_mng;
823 bi.trace_mng = m_trace;
824 bi.world_parallel_mng = m_world_parallel_mng;
825 bi.mpi_lock = m_mpi_lock;
826
828 sub_pm->build();
829 return sub_pm;
830}
831
832/*---------------------------------------------------------------------------*/
833/*---------------------------------------------------------------------------*/
834
835Ref<IParallelMng> MpiParallelMng::
836_createSubParallelMngRef(Int32 color, Int32 key)
837{
838 if (color < 0)
839 color = MPI_UNDEFINED;
841 MPI_Comm_split(m_communicator, color, key, &sub_communicator);
842 IParallelMng* sub_pm = _createSubParallelMng(sub_communicator);
843 return makeRef(sub_pm);
844}
845
846/*---------------------------------------------------------------------------*/
847/*---------------------------------------------------------------------------*/
848
849IParallelMng* MpiParallelMng::
850_createSubParallelMng(Int32ConstArrayView kept_ranks)
851{
853 MPI_Comm_group(m_communicator, &mpi_group);
856 for (Integer i = 0; i < nb_sub_rank; ++i)
857 mpi_kept_ranks[i] = (int)kept_ranks[i];
858
862
864 return _createSubParallelMng(sub_communicator);
865}
866
867/*---------------------------------------------------------------------------*/
868/*---------------------------------------------------------------------------*/
877: public MpiRequestList
878{
879 using Base = MpiRequestList;
880 public:
881 explicit RequestList(MpiParallelMng* pm)
882 : Base(pm->m_adapter), m_parallel_mng(pm){}
883 public:
885 {
887 m_parallel_mng->_checkFinishedSubRequests();
888 };
889 private:
890 MpiParallelMng* m_parallel_mng;
891};
892
893/*---------------------------------------------------------------------------*/
894/*---------------------------------------------------------------------------*/
895
901
902/*---------------------------------------------------------------------------*/
903/*---------------------------------------------------------------------------*/
904
907{
908 return m_utils_factory;
909}
910
911/*---------------------------------------------------------------------------*/
912/*---------------------------------------------------------------------------*/
913
914bool MpiParallelMng::
915_isAcceleratorAware() const
916{
918}
919
920/*---------------------------------------------------------------------------*/
921/*---------------------------------------------------------------------------*/
922
923} // End namespace Arcane
924
925/*---------------------------------------------------------------------------*/
926/*---------------------------------------------------------------------------*/
#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:120
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 destroy()
Détruit l'instance. Elle ne doit plus être utilisée par la suite.
void _wait(eWaitType wait_type) override
Effectue l'attente ou le test.
Request receiveSerializer(ISerializer *s, const PointToPointMessageInfo &message) override
Message de réception.
Request sendSerializer(const ISerializer *s, const PointToPointMessageInfo &message) override
Message d'envoi.
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.
-*- 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:75
@ 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.
Infos pour construire un MpiParallelMng.
Infos pour construire un SequentialParallelMng.