14#include "arcane/impl/internal/VariableSynchronizer.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/NotSupportedException.h"
18#include "arcane/utils/FatalErrorException.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/IMemoryRessourceMng.h"
21#include "arcane/utils/ValueConvert.h"
22#include "arcane/utils/internal/MemoryBuffer.h"
24#include "arcane/core/VariableSynchronizerEventArgs.h"
25#include "arcane/core/IParallelMng.h"
26#include "arcane/core/IItemFamily.h"
27#include "arcane/core/ItemPrinter.h"
28#include "arcane/core/IVariable.h"
29#include "arcane/core/IData.h"
30#include "arcane/core/VariableCollection.h"
31#include "arcane/core/Timer.h"
32#include "arcane/core/IMesh.h"
33#include "arcane/core/IVariableMng.h"
34#include "arcane/core/IVariableSynchronizerMng.h"
35#include "arcane/core/parallel/IStat.h"
36#include "arcane/core/internal/IDataInternal.h"
37#include "arcane/core/internal/IParallelMngInternal.h"
38#include "arcane/core/internal/IVariableSynchronizerMngInternal.h"
40#include "arcane/accelerator/core/Runner.h"
42#include "arcane/impl/DataSynchronizeInfo.h"
43#include "arcane/impl/internal/VariableSynchronizerComputeList.h"
44#include "arcane/impl/internal/IBufferCopier.h"
57extern "C++" Ref<IDataSynchronizeImplementationFactory>
58arcaneCreateSimpleVariableSynchronizerFactory(IParallelMng* pm);
76 , m_allocator(allocator)
77 , m_buffer(
sync_mng->createSynchronizeBuffer(allocator))
82 m_synchronizer_mng->releaseSynchronizeBuffer(m_allocator, m_buffer.get());
97 , m_variable_synchronizer_mng(
var_syncer->synchronizeMng())
101 , m_allocator(allocator)
105 if (!m_multi_dispatcher)
110 delete m_multi_dispatcher;
117 m_dispatcher->compute();
121 void initialize(IVariable* var)
124 m_event_args.initialize(var);
128 void initialize(
const VariableCollection& vars)
131 m_event_args.initialize(vars);
132 for (VariableCollectionEnumerator v(vars); ++v;)
136 Int32 nbVariable()
const {
return m_variables.size(); }
137 ConstArrayView<IVariable*> variables()
const {
return m_variables; }
142 Int32
nb_var = m_variables.size();
147 m_synchronize_result = synchronizeData(m_data_list[0],
is_compare_sync);
152 m_multi_dispatcher->synchronize(m_variables);
155 var->setIsSynchronized();
160 ScopedBuffer
tmp_buf(m_variable_synchronizer_mng->_internalApi(), m_allocator);
161 m_dispatcher->setSynchronizeBuffer(
tmp_buf.m_buffer);
163 return m_dispatcher->endSynchronize();
166 VariableSynchronizerEventArgs& eventArgs() {
return m_event_args; }
170 IVariableSynchronizer* m_variable_synchronizer =
nullptr;
171 IVariableSynchronizerMng* m_variable_synchronizer_mng =
nullptr;
172 Ref<IDataSynchronizeDispatcher> m_dispatcher;
173 IDataSynchronizeMultiDispatcher* m_multi_dispatcher =
nullptr;
174 VariableSynchronizerEventArgs m_event_args;
175 UniqueArray<IVariable*> m_variables;
176 UniqueArray<INumericDataInternal*> m_data_list;
177 DataSynchronizeResult m_synchronize_result;
178 IMemoryAllocator* m_allocator =
nullptr;
188 void _addVariable(IVariable* var)
190 INumericDataInternal* numapi = var->data()->_commonInternal()->numericData();
192 ARCANE_FATAL(
"Variable '{0}' can not be synchronized because it is not a numeric data", var->name());
193 m_variables.add(var);
194 m_data_list.add(numapi);
201VariableSynchronizer::
202VariableSynchronizer(IParallelMng* pm,
const ItemGroup& group,
203 Ref<IDataSynchronizeImplementationFactory> implementation_factory)
204: TraceAccessor(pm->traceMng())
208 m_sync_info = DataSynchronizeInfo::create();
209 m_partial_sync_info = DataSynchronizeInfo::create();
211 if (!implementation_factory.get())
212 implementation_factory = arcaneCreateSimpleVariableSynchronizerFactory(pm);
213 m_implementation_factory = implementation_factory;
215 m_variable_synchronizer_mng = group.itemFamily()->mesh()->variableMng()->synchronizerMng();
218 String s = platform::getEnvironmentVariable(
"ARCANE_ALLOW_MULTISYNC");
219 if (s ==
"0" || s ==
"FALSE" || s ==
"false")
220 m_allow_multi_sync =
false;
223 String s = platform::getEnvironmentVariable(
"ARCANE_TRACE_SYNCHRONIZE");
224 if (s ==
"1" || s ==
"TRUE" || s ==
"true")
229 if (
auto v = Convert::Type<Int32>::tryParseFromEnvironment(
"ARCANE_CHECK_SYNCHRONIZE_COHERENCE",
true))
230 m_is_check_coherence = (v.value()!=0);
232 m_default_message = _buildMessage();
233 m_partial_message = makeRef<SyncMessage>(_buildMessage(m_partial_sync_info));
239VariableSynchronizer::
240~VariableSynchronizer()
243 delete m_default_message;
249VariableSynchronizer::SyncMessage* VariableSynchronizer::
253 Runner* runner = internal_pm->defaultRunner();
254 bool is_accelerator_aware = internal_pm->isAcceleratorAware();
256 if (runner && is_accelerator_aware) {
260 return _buildMessage(m_sync_info);
266VariableSynchronizer::SyncMessage* VariableSynchronizer::
267_buildMessage(Ref<DataSynchronizeInfo>& sync_info)
269 GroupIndexTable* table =
nullptr;
273 Ref<IBufferCopier> buffer_copier;
275 buffer_copier = makeRef<IBufferCopier>(
new TableBufferCopier(table));
277 buffer_copier = makeRef<IBufferCopier>(
new DirectBufferCopier());
281 IMemoryAllocator* allocator =
nullptr;
286 buffer_copier->setRunQueue(internal_pm->defaultQueue());
291 Ref<IDataSynchronizeImplementation> sync_impl = m_implementation_factory->createInstance();
292 sync_impl->setDataSynchronizeInfo(sync_info.get());
294 DataSynchronizeDispatcherBuildInfo bi(m_parallel_mng, sync_impl, sync_info, buffer_copier);
295 return new SyncMessage(bi,
this, allocator);
310 m_default_message->compute();
312 info() <<
"End compute dispatcher Date=" << platform::getCurrentDateTime();
318void VariableSynchronizer::
319_doSynchronize(SyncMessage* message)
333 message->synchronize();
336 Int32 nb_var = message->nbVariable();
339 if (nb_var == 1 && m_variable_synchronizer_mng->isSynchronizationComparisonEnabled()) {
350 _sendEndEvent(event_args);
356void VariableSynchronizer::
362 if (local_ids == m_partial_local_ids.
constView()) {
369 m_partial_local_ids.
copy(local_ids);
374 for (
Int32 lid : local_ids) {
379 Int32 nb_comm_ranks = comm_ranks.size();
381 const DataSynchronizeBufferInfoList& send_info = m_sync_info->sendInfo();
382 const DataSynchronizeBufferInfoList& recv_info = m_sync_info->receiveInfo();
384 m_partial_sync_info = DataSynchronizeInfo::create();
386 if (!local_ids.empty()) {
388 UniqueArray<Int32> recv_grp;
389 UniqueArray<Int32> send_grp;
391 for (
Int32 index = 0; index < nb_comm_ranks; ++index) {
392 Int32 target_rank = comm_ranks[index];
393 ConstArrayView<Int32> send_lids = send_info.localIds(index);
394 ConstArrayView<Int32> recv_lids = recv_info.localIds(index);
399 for (
Int32 lid : recv_lids) {
405 for (
Int32 lid : send_lids) {
411 if ((!send_grp.empty()) || (!recv_grp.empty())) {
413 m_partial_sync_info->add(VariableSyncInfo(send_grp, recv_grp, target_rank));
418 m_partial_sync_info->recompute();
419 m_partial_message = makeRef<SyncMessage>(_buildMessage(m_partial_sync_info));
420 m_partial_message->compute();
426void VariableSynchronizer::
427_synchronize(IVariable* var, SyncMessage* message)
429 message->initialize(var);
431 IParallelMng* pm = m_parallel_mng;
432 if (m_is_check_coherence)
436 info() <<
" Synchronize variable " << var->fullName()
437 <<
" stack=" << platform::getStackTrace();
439 _doSynchronize(message);
448 _synchronize(
var, m_default_message);
458 _synchronize(
var, m_partial_message.get());
470 const bool use_multi = m_allow_multi_sync;
472 _synchronizeMulti(
vars, m_default_message);
476 _synchronize(*
ivar, m_default_message);
492 const bool use_multi = m_allow_multi_sync;
494 _synchronizeMulti(
vars, m_partial_message.get());
498 _synchronize(*
ivar, m_partial_message.get());
522 ARCANE_FATAL(
"Data can not be synchronized because it is not a numeric data");
523 _synchronize(
numapi,
false);
532 info(4) <<
"** VariableSynchronizer::changeLocalIds() group=" << m_item_group.
name();
534 m_default_message->compute();
551 if (
vars.count() == 1)
557 if (
var->isPartial())
573void VariableSynchronizer::
576 message->initialize(
vars);
581 info() <<
" MultiSynchronize"
582 <<
" stack=" << platform::getStackTrace();
585 _doSynchronize(message);
594 return m_sync_info->communicatingRanks();
603 return m_sync_info->sendInfo().localIds(index);
612 return m_sync_info->receiveInfo().localIds(index);
618void VariableSynchronizer::
622 args.setState(VariableSynchronizerEventArgs::State::BeginSynchronize);
629void VariableSynchronizer::
630_sendEndEvent(VariableSynchronizerEventArgs& args)
634 m_parallel_mng->
stat()->add(
"Synchronize", elapsed_time, 1);
635 args.setState(VariableSynchronizerEventArgs::State::EndSynchronize);
636 args.setElapsedTime(elapsed_time);
643void VariableSynchronizer::
644_sendEvent(VariableSynchronizerEventArgs& args)
646 m_variable_synchronizer_mng->onSynchronized().notify(args);
647 m_on_synchronized.notify(args);
653void VariableSynchronizer::
#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.
void setAsCurrentDevice()
Positionne le device associé à cette instance comme le device par défaut du contexte.
Infos pour construire un DataSynchronizeDispatcher.
Informations sur le résultat d'une synchronisation.
Interface pour gérer la synchronisation d'une donnée.
Interface de la synchronisation d'une liste de variables.
virtual void setSynchronizeBuffer(Ref< MemoryBuffer > buffer)=0
Positionne le buffer de synchronisation.
virtual void compute()=0
Recalcule les informations nécessaires après une mise à jour des informations de DataSynchronizeInfo.
virtual IDataInternal * _commonInternal()=0
virtual Int32 maxLocalId() const =0
virtual IMemoryAllocator * getAllocator(eMemoryRessource r)=0
Allocateur mémoire pour la ressource r.
Interface pour un 'IData' d'un type numérique.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual ITimeStats * timeStats() const =0
Gestionnaire de statistiques associé (peut être nul)
virtual IStat * stat()=0
Gestionnaire des statistiques.
virtual ITimerMng * timerMng() const =0
Gestionnaire de timers.
virtual IParallelMngInternal * _internalApi()=0
API interne à Arcane.
Interface gérant les statistiques sur les temps d'exécution.
API interne à Arcane de IVariableSynchronizerMng.
virtual bool isSynchronizationComparisonEnabled() const =0
Indique si on effectue les comparaisons des valeurs avant et après synchronisation.
Interface d'une variable.
Groupe d'entités de maillage.
const String & name() const
Nom du groupe.
SharedPtrT< GroupIndexTable > localIdToIndex() const
Table des local ids vers une position pour toutes les entités du groupe.
IItemFamily * itemFamily() const
Famille d'entité à laquelle appartient ce groupe (0 pour le group nul)
bool isAllItems() const
Indique si le groupe est celui de toutes les entités.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Positionne la phase de l'action en cours d'exécution.
Sentinelle pour le timer. La sentinelle associée à un timer permet de déclancher celui-ci au moment d...
@ TimerReal
Timer utilisant le temps réel.
Real lastActivationTime() const
Retourne le temps (en secondes) passé lors de la dernière activation du timer.
Calcule de la liste des entités à synchroniser.
Arguments de l'évènement notifiant une synchronisation de variables.
@ Different
Valeurs différentes avant et après la synchronisation.
@ Same
Même valeurs avant et après la synchronisation.
void setCompareStatus(Int32 i, CompareStatus v)
Positionne l'état de comparaison de la i-ème variable.
Gestion d'une synchronisation.
void synchronize()
Effectue la synchronisation.
Interface d'un service de synchronisation de variable.
void changeLocalIds(Int32ConstArrayView old_to_new_ids) override
Appelé lorsque les numéros locaux des entités sont modifiés.
void compute() override
Création de la liste des éléments de synchronisation.
bool _canSynchronizeMulti(const VariableCollection &vars)
Indique si les variables de la liste vars peuvent être synchronisées en une seule fois.
Int32ConstArrayView ghostItems(Int32 index) override
Liste des ids locaux des entités fantômes avec un sous-domaine.
Int32ConstArrayView sharedItems(Int32 index) override
Liste des ids locaux des entités partagées avec un sous-domaine.
void _setCurrentDevice()
Positionne le device associé à notre RunQueue comme le device courant.
void synchronizeData(IData *data) override
Synchronise la donnée data.
void synchronize(IVariable *var) override
Synchronise la variable var en mode bloquant.
Int32ConstArrayView communicatingRanks() override
Rangs des sous-domaines avec lesquels on communique.
void copy(Span< const T > rhs)
Copie les valeurs de rhs dans l'instance.
ConstArrayView< T > constView() const
Vue constante sur ce tableau.
Vue constante d'un tableau de type T.
Interface d'un allocateur pour la mémoire.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
void namedBarrier(IParallelMng *pm, const String &name)
Effectue une barrière nommée de nom name.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ Device
Alloue sur le device.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
eDataSynchronizeCompareStatus
Comparaison des valeurs des entités fantômes avant/après une synchronisation.
@ Different
Valeurs différentes avant et après la synchronisation.
@ Same
Même valeurs avant et après la synchronisation.