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"
56arcaneCreateSimpleVariableSynchronizerFactory(
IParallelMng* pm);
73 : m_synchronizer_mng(sync_mng)
74 , m_allocator(allocator)
75 , m_buffer(sync_mng->createSynchronizeBuffer(allocator))
78 ~ScopedBuffer()
noexcept(
false)
80 m_synchronizer_mng->releaseSynchronizeBuffer(m_allocator, m_buffer.get());
94 : m_variable_synchronizer_mng(var_syncer->synchronizeMng())
97 , m_event_args(var_syncer)
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();
143 bool is_compare_sync = m_variable_synchronizer_mng->isSynchronizationComparisonEnabled();
144 m_synchronize_result = synchronizeData(m_data_list[0], is_compare_sync);
147 ScopedBuffer tmp_buf(m_variable_synchronizer_mng->_internalApi(), m_allocator);
148 m_multi_dispatcher->setSynchronizeBuffer(tmp_buf.m_buffer);
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);
159 m_dispatcher->beginSynchronize(data, is_compare_sync);
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::
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();
215 if (s ==
"0" || s ==
"FALSE" || s ==
"false")
216 m_allow_multi_sync =
false;
220 if (s ==
"1" || s ==
"TRUE" || s ==
"true")
226 m_is_check_coherence = (v.value()!=0);
228 m_default_message = _buildMessage();
235VariableSynchronizer::
236~VariableSynchronizer()
239 delete m_default_message;
245VariableSynchronizer::SyncMessage* VariableSynchronizer::
248 auto* internal_pm = m_parallel_mng->_internalApi();
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;
266 if (!m_item_group.isAllItems())
267 table = m_item_group.localIdToIndex().get();
269 Ref<IBufferCopier> buffer_copier;
275 auto* internal_pm = m_parallel_mng->_internalApi();
277 IMemoryAllocator* allocator =
nullptr;
281 if (m_runner.isInitialized()) {
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);
302 VariableSynchronizerComputeList computer(
this);
306 m_default_message->compute();
314void VariableSynchronizer::
315_doSynchronize(SyncMessage* message)
325 _sendBeginEvent(event_args);
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);
367 UniqueArray<bool> flags(m_item_group.itemFamily()->maxLocalId());
370 for (
Int32 lid : local_ids) {
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();
416 m_partial_message->compute();
422void VariableSynchronizer::
425 message->initialize(var);
427 IParallelMng* pm = m_parallel_mng;
428 if (m_is_check_coherence)
430 debug(
Trace::High) <<
" Proc " << pm->commRank() <<
" Sync variable " << var->fullName();
432 info() <<
" Synchronize variable " << var->fullName()
435 _doSynchronize(message);
444 _synchronize(var, m_default_message);
453 _rebuildMessage(local_ids);
454 _synchronize(var, m_partial_message.get());
466 const bool use_multi = m_allow_multi_sync;
468 _synchronizeMulti(vars, m_default_message);
471 for (VariableCollection::Enumerator ivar(vars); ++ivar;) {
472 _synchronize(*ivar, m_default_message);
486 _rebuildMessage(local_ids);
488 const bool use_multi = m_allow_multi_sync;
490 _synchronizeMulti(vars, m_partial_message.get());
493 for (VariableCollection::Enumerator ivar(vars); ++ivar;) {
494 _synchronize(*ivar, m_partial_message.get());
506 return m_default_message->synchronizeData(data, is_compare_sync);
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();
529 m_sync_info->changeLocalIds(old_to_new_ids);
530 m_default_message->compute();
547 if (vars.count() == 1)
551 for (VariableCollection::Enumerator ivar(vars); ++ivar;) {
560 if (group != var_group)
569void VariableSynchronizer::
572 message->initialize(vars);
577 info() <<
" MultiSynchronize"
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::
653 m_sync_timer =
new Timer(m_parallel_mng->timerMng(),
"SyncTimer",
Timer::TimerReal);
668 if (m_runner.isInitialized())
669 m_runner.setAsCurrentDevice();
#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.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
static std::optional< Int32 > tryParseFromEnvironment(StringView s, bool throw_if_invalid)
Infos pour construire un DataSynchronizeDispatcher.
Informations sur le résultat d'une synchronisation.
virtual INumericDataInternal * numericData()
Interface générique pour les données numériques (nullptr si la donnée n'est pas numérique)
Interface pour gérer la synchronisation d'une donnée.
Interface de la synchronisation d'une liste de variables.
virtual void compute()=0
Recalcule les informations nécessaires après une mise à jour des informations de DataSynchronizeInfo.
virtual IDataInternal * _commonInternal()=0
Interface d'un allocateur pour la mémoire.
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.
Interface gérant les statistiques sur les temps d'exécution.
API interne à Arcane de IVariableSynchronizerMng.
Interface d'une variable.
virtual bool isPartial() const =0
Indique si la variable est partielle.
virtual ItemGroup itemGroup() const =0
Groupe du maillage associé.
Groupe d'entités de maillage.
virtual void add(const String &name, double elapsed_time, Int64 msg_size)=0
Ajoute une statistique.
Référence à une instance.
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.
Classe d'accès aux traces.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flot pour un message de debug.
TraceMessage info() const
Flot pour un message d'information.
void compute()
Création de la liste des éléments de synchronisation.
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.
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.
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.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.