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/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/impl/DataSynchronizeInfo.h"
41#include "arcane/impl/internal/VariableSynchronizerComputeList.h"
42#include "arcane/impl/internal/IBufferCopier.h"
55extern "C++" Ref<IDataSynchronizeImplementationFactory>
56arcaneCreateSimpleVariableSynchronizerFactory(IParallelMng* pm);
74 , m_allocator(allocator)
75 , m_buffer(
sync_mng->createSynchronizeBuffer(allocator))
80 m_synchronizer_mng->releaseSynchronizeBuffer(m_allocator, m_buffer.get());
94 : m_variable_synchronizer_mng(
var_syncer->synchronizeMng())
98 , m_allocator(allocator)
102 if (!m_multi_dispatcher)
107 delete m_multi_dispatcher;
114 m_dispatcher->compute();
118 void initialize(IVariable* var)
121 m_event_args.initialize(var);
125 void initialize(
const VariableCollection& vars)
128 m_event_args.initialize(vars);
129 for (VariableCollectionEnumerator v(vars); ++v;)
133 Int32 nbVariable()
const {
return m_variables.size(); }
134 ConstArrayView<IVariable*> variables()
const {
return m_variables; }
139 Int32
nb_var = m_variables.size();
144 m_synchronize_result = synchronizeData(m_data_list[0],
is_compare_sync);
149 m_multi_dispatcher->synchronize(m_variables);
152 var->setIsSynchronized();
157 ScopedBuffer
tmp_buf(m_variable_synchronizer_mng->_internalApi(), m_allocator);
158 m_dispatcher->setSynchronizeBuffer(
tmp_buf.m_buffer);
160 return m_dispatcher->endSynchronize();
163 VariableSynchronizerEventArgs& eventArgs() {
return m_event_args; }
167 IVariableSynchronizerMng* m_variable_synchronizer_mng =
nullptr;
168 Ref<IDataSynchronizeDispatcher> m_dispatcher;
169 IDataSynchronizeMultiDispatcher* m_multi_dispatcher =
nullptr;
170 VariableSynchronizerEventArgs m_event_args;
171 UniqueArray<IVariable*> m_variables;
172 UniqueArray<INumericDataInternal*> m_data_list;
173 DataSynchronizeResult m_synchronize_result;
174 IMemoryAllocator* m_allocator =
nullptr;
184 void _addVariable(IVariable* var)
186 INumericDataInternal* numapi = var->data()->_commonInternal()->numericData();
188 ARCANE_FATAL(
"Variable '{0}' can not be synchronized because it is not a numeric data", var->name());
189 m_variables.add(var);
190 m_data_list.add(numapi);
197VariableSynchronizer::
198VariableSynchronizer(IParallelMng* pm,
const ItemGroup& group,
199 Ref<IDataSynchronizeImplementationFactory> implementation_factory)
200: TraceAccessor(pm->traceMng())
204 m_sync_info = DataSynchronizeInfo::create();
205 m_partial_sync_info = DataSynchronizeInfo::create();
207 if (!implementation_factory.get())
208 implementation_factory = arcaneCreateSimpleVariableSynchronizerFactory(pm);
209 m_implementation_factory = implementation_factory;
211 m_variable_synchronizer_mng = group.itemFamily()->mesh()->variableMng()->synchronizerMng();
214 String s = platform::getEnvironmentVariable(
"ARCANE_ALLOW_MULTISYNC");
215 if (s ==
"0" || s ==
"FALSE" || s ==
"false")
216 m_allow_multi_sync =
false;
219 String s = platform::getEnvironmentVariable(
"ARCANE_TRACE_SYNCHRONIZE");
220 if (s ==
"1" || s ==
"TRUE" || s ==
"true")
225 if (
auto v = Convert::Type<Int32>::tryParseFromEnvironment(
"ARCANE_CHECK_SYNCHRONIZE_COHERENCE",
true))
226 m_is_check_coherence = (v.value()!=0);
228 m_default_message = _buildMessage();
229 m_partial_message = makeRef<SyncMessage>(_buildMessage(m_partial_sync_info));
235VariableSynchronizer::
236~VariableSynchronizer()
239 delete m_default_message;
245VariableSynchronizer::SyncMessage* VariableSynchronizer::
249 Runner runner = internal_pm->runner();
250 bool is_accelerator_aware = internal_pm->isAcceleratorAware();
252 if (runner.isInitialized() && is_accelerator_aware) {
256 return _buildMessage(m_sync_info);
262VariableSynchronizer::SyncMessage* VariableSynchronizer::
263_buildMessage(Ref<DataSynchronizeInfo>& sync_info)
265 GroupIndexTable* table =
nullptr;
269 Ref<IBufferCopier> buffer_copier;
271 buffer_copier = makeRef<IBufferCopier>(
new TableBufferCopier(table));
273 buffer_copier = makeRef<IBufferCopier>(
new DirectBufferCopier());
277 IMemoryAllocator* allocator =
nullptr;
282 buffer_copier->setRunQueue(internal_pm->queue());
287 Ref<IDataSynchronizeImplementation> sync_impl = m_implementation_factory->createInstance();
288 sync_impl->setDataSynchronizeInfo(sync_info.get());
290 DataSynchronizeDispatcherBuildInfo bi(m_parallel_mng, sync_impl, sync_info, buffer_copier);
291 return new SyncMessage(bi,
this, allocator);
306 m_default_message->compute();
308 info() <<
"End compute dispatcher Date=" << platform::getCurrentDateTime();
314void VariableSynchronizer::
315_doSynchronize(SyncMessage* message)
329 message->synchronize();
332 Int32 nb_var = message->nbVariable();
335 if (nb_var == 1 && m_variable_synchronizer_mng->isSynchronizationComparisonEnabled()) {
346 _sendEndEvent(event_args);
352void VariableSynchronizer::
358 if (local_ids == m_partial_local_ids.
constView()) {
365 m_partial_local_ids.
copy(local_ids);
370 for (
Int32 lid : local_ids) {
375 Int32 nb_comm_ranks = comm_ranks.size();
377 const DataSynchronizeBufferInfoList& send_info = m_sync_info->sendInfo();
378 const DataSynchronizeBufferInfoList& recv_info = m_sync_info->receiveInfo();
380 m_partial_sync_info = DataSynchronizeInfo::create();
382 if (!local_ids.empty()) {
384 UniqueArray<Int32> recv_grp;
385 UniqueArray<Int32> send_grp;
387 for (
Int32 index = 0; index < nb_comm_ranks; ++index) {
388 Int32 target_rank = comm_ranks[index];
389 ConstArrayView<Int32> send_lids = send_info.localIds(index);
390 ConstArrayView<Int32> recv_lids = recv_info.localIds(index);
395 for (
Int32 lid : recv_lids) {
401 for (
Int32 lid : send_lids) {
407 if ((!send_grp.empty()) || (!recv_grp.empty())) {
409 m_partial_sync_info->add(VariableSyncInfo(send_grp, recv_grp, target_rank));
414 m_partial_sync_info->recompute();
415 m_partial_message = makeRef<SyncMessage>(_buildMessage(m_partial_sync_info));
416 m_partial_message->compute();
422void VariableSynchronizer::
423_synchronize(IVariable* var, SyncMessage* message)
425 message->initialize(var);
427 IParallelMng* pm = m_parallel_mng;
428 if (m_is_check_coherence)
432 info() <<
" Synchronize variable " << var->fullName()
433 <<
" stack=" << platform::getStackTrace();
435 _doSynchronize(message);
444 _synchronize(
var, m_default_message);
454 _synchronize(
var, m_partial_message.get());
466 const bool use_multi = m_allow_multi_sync;
468 _synchronizeMulti(
vars, m_default_message);
472 _synchronize(*
ivar, m_default_message);
488 const bool use_multi = m_allow_multi_sync;
490 _synchronizeMulti(
vars, m_partial_message.get());
494 _synchronize(*
ivar, m_partial_message.get());
518 ARCANE_FATAL(
"Data can not be synchronized because it is not a numeric data");
519 _synchronize(
numapi,
false);
528 info(4) <<
"** VariableSynchronizer::changeLocalIds() group=" << m_item_group.
name();
530 m_default_message->compute();
547 if (
vars.count() == 1)
553 if (
var->isPartial())
569void VariableSynchronizer::
572 message->initialize(
vars);
577 info() <<
" MultiSynchronize"
578 <<
" stack=" << platform::getStackTrace();
581 _doSynchronize(message);
590 return m_sync_info->communicatingRanks();
599 return m_sync_info->sendInfo().localIds(index);
608 return m_sync_info->receiveInfo().localIds(index);
614void VariableSynchronizer::
618 args.setState(VariableSynchronizerEventArgs::State::BeginSynchronize);
625void VariableSynchronizer::
626_sendEndEvent(VariableSynchronizerEventArgs& args)
630 m_parallel_mng->
stat()->add(
"Synchronize", elapsed_time, 1);
631 args.setState(VariableSynchronizerEventArgs::State::EndSynchronize);
632 args.setElapsedTime(elapsed_time);
639void VariableSynchronizer::
640_sendEvent(VariableSynchronizerEventArgs& args)
642 m_variable_synchronizer_mng->onSynchronized().notify(args);
643 m_on_synchronized.notify(args);
649void 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.
Fonctions de gestion mémoire et des allocateurs.
bool isInitialized() const
Indique si l'instance a été initialisée.
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
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.
IMemoryAllocator * getAllocator(eMemoryResource mem_resource)
Allocateur par défaut pour la ressource mem_resource.
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 -*-
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.