Arcane  v3.14.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
ArcaneBasicVerifierService.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/* ArcaneBasicVerifierService.cc (C) 2000-2024 */
9/* */
10/* Service de comparaison des variables. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/ITraceMng.h"
15#include "arcane/utils/FatalErrorException.h"
16#include "arcane/utils/PlatformUtils.h"
17#include "arcane/utils/StringBuilder.h"
18#include "arcane/utils/ValueConvert.h"
19
20#include "arcane/core/IParallelMng.h"
21#include "arcane/core/VariableCollection.h"
22#include "arcane/core/IVariableUtilities.h"
23#include "arcane/core/VerifierService.h"
24#include "arcane/core/ItemGroup.h"
25#include "arcane/core/IVariableMng.h"
26#include "arcane/core/IVariable.h"
27#include "arcane/core/ISubDomain.h"
29#include "arcane/core/IData.h"
30#include "arcane/core/internal/IVariableInternal.h"
31
32#include "arcane/std/internal/BasicReader.h"
33#include "arcane/std/internal/BasicWriter.h"
34
35/*---------------------------------------------------------------------------*/
36/*---------------------------------------------------------------------------*/
37
38namespace Arcane
39{
40using namespace Arcane::impl;
41
42/*---------------------------------------------------------------------------*/
43/*---------------------------------------------------------------------------*/
44
46: public VerifierService
47{
50 {
51 public:
52
54 : m_variable_mng(vm)
55 {}
56 ItemGroup getWantedGroup(VariableMetaData* vmd) override
57 {
58 String full_name = vmd->fullName();
60 if (!var)
61 ARCANE_FATAL("Variable '{0}' not found");
62 return var->itemGroup();
63 }
64
65 private:
66
67 IVariableMng* m_variable_mng;
68 };
69
70 public:
71
74 {
75 }
76
77 public:
78
79 void build() override {}
80 void writeReferenceFile() override;
82
83 protected:
84
85 void _setFormatVersion(Int32 v)
86 {
87 m_wanted_format_version = v;
88 }
89
90 private:
91
92 String m_full_file_name;
93 Int32 m_wanted_format_version = 1;
94
95 private:
96
97 void _computeFullFileName(bool is_read)
98 {
99 ARCANE_UNUSED(is_read);
101 //m_full_file_name = fileName();
102 const String& sub_dir = subDir();
103 if (!sub_dir.empty()) {
104 s += "/";
105 s += sub_dir;
106 }
107 m_full_file_name = s;
108 }
109 void _doVerifHash(BasicReader* reader, const VariableCollection& variables);
110 void _writeReferenceFile(const String& file_name);
111};
112
113/*---------------------------------------------------------------------------*/
114/*---------------------------------------------------------------------------*/
115
116void ArcaneBasicVerifierService::
117_writeReferenceFile(const String& file_name)
118{
119 ISubDomain* sd = subDomain();
120 IParallelMng* pm = sd->parallelMng();
121 IVariableMng* vm = sd->variableMng();
122 auto open_mode = BasicReaderWriterCommon::OpenModeTruncate;
123 // Pour l'instant utilise la version 1
124 // A partir de janvier 2019, il est possible d'utiliser la version 2 ou 3
125 // car le comparateur C# supporte cette version.
126 Int32 version = m_wanted_format_version;
127 bool want_parallel = pm->isParallel();
128 ScopedPtrT<BasicWriter> verif(new BasicWriter(sd->application(), pm, file_name,
129 open_mode, version, want_parallel));
130 if (compareMode() == eCompareMode::HashOnly)
131 verif->setSaveValues(false);
132
133 verif->initialize();
134
135 // En parallèle, comme l'écriture nécessite des communications entre les sous-domaines,
136 // il est indispensable que tous les PE aient les mêmes variables. On les filtre pour
137 // garantir cela.
138 VariableCollection used_variables = vm->usedVariables();
139 if (pm->isParallel()) {
140 bool dump_not_common = true;
141 VariableCollection filtered_variables = vm->utilities()->filterCommonVariables(pm, used_variables, dump_not_common);
142 vm->writeVariables(verif.get(), filtered_variables);
143 }
144 else {
145 vm->writeVariables(verif.get(), used_variables);
146 }
147}
148
149/*---------------------------------------------------------------------------*/
150/*---------------------------------------------------------------------------*/
151
154{
155 _computeFullFileName(false);
156 String dir_name = platform::getFileDirName(m_full_file_name);
157 platform::recursiveCreateDirectory(m_full_file_name);
158 _writeReferenceFile(m_full_file_name);
159}
160
161/*---------------------------------------------------------------------------*/
162/*---------------------------------------------------------------------------*/
163
166{
167 ISubDomain* sd = subDomain();
168 IParallelMng* pm = sd->parallelMng();
169 IVariableMng* vm = subDomain()->variableMng();
170 ITraceMng* tm = sd->traceMng();
171 _computeFullFileName(true);
172 bool want_parallel = pm->isParallel();
173 Ref<BasicReader> reader = makeRef(new BasicReader(sd->application(), pm, A_NULL_RANK, m_full_file_name, want_parallel));
174 reader->initialize();
176 reader->setItemGroupFinder(&group_finder);
177
180
181 // En parallèle, comme la lecture nécessite des communications entre les sous-domaines,
182 // il est indispensable que tous les PE aient les mêmes variables. On les filtre pour
183 // garantir cela.
184 if (pm->isParallel()) {
185 IVariableMng* vm = sd->variableMng();
186 bool dump_not_common = true;
187 VariableCollection filtered_variables = vm->utilities()->filterCommonVariables(pm, read_variables, dump_not_common);
189 }
190
191 tm->info() << "Checking (" << m_full_file_name << ")";
192 reader->beginRead(read_variables);
193 if (compareMode() == eCompareMode::Values)
194 _doVerif(reader.get(), read_variables, compare_ghost);
195 if (compareMode() == eCompareMode::HashOnly)
196 _doVerifHash(reader.get(), read_variables);
197 reader->endRead();
198}
199
200/*---------------------------------------------------------------------------*/
201/*---------------------------------------------------------------------------*/
202namespace
203{
204 String
205 _getHashValueOrNull(const std::map<String, String>& comparison_hash_map, const String& name)
206 {
207 auto x = comparison_hash_map.find(name);
208 if (x != comparison_hash_map.end())
209 return x->second;
210 return {};
211 }
212} // namespace
213
214void ArcaneBasicVerifierService::
215_doVerifHash(BasicReader* ref_reader, const VariableCollection& variables)
216{
217 ISubDomain* sd = subDomain();
218 IParallelMng* pm = sd->parallelMng();
219 bool is_master = pm->isMasterIO();
220 const bool want_parallel = pm->isParallel();
221
222 info() << "Check Verif Hash";
223 // Récupère l'algorithm de calcul du hash
224 IHashAlgorithm* ref_compare_hash_algo = ref_reader->comparisonHashAlgorithm();
226 // TODO: regarder s'il faut ne rien faire ou s'il faut signaler une erreur.
227 return;
228
229 // Calcul les hash des valeurs courantes des variables
230 std::map<String, String> current_comparison_hash_map;
232 info() << "DoVerifHash";
233 for (VariableCollection::Enumerator ivar(variables); ++ivar;) {
234 IVariable* var = *ivar;
236 IData* data = var->data();
237 // En parallèle, trie les entités par uniqueId() croissant.
238 // En séquentiel c'est toujours le cas.
239 // NOTE: pour l'instant on utilise le IParallelMng global mais il faudrait
240 // vérifier s'il ne faut pas utiliser celui associé au maillage de la
241 // variable courante \a var.
242 if (want_parallel) {
243 // En parallèle, ne compare que les variables sur les entités
244 ItemGroup group = var->itemGroup();
245 if (group.null())
246 continue;
247 Ref<ParallelDataWriter> writer = parallel_data_writers.getOrCreateWriter(group);
248 allocated_data = writer->getSortedValues(data);
249 data = allocated_data.get();
250 }
251 String hash_string = var->_internalApi()->computeComparisonHashCollective(ref_compare_hash_algo, data);
252 if (!hash_string.empty())
253 current_comparison_hash_map.try_emplace(var->fullName(), hash_string);
254 }
255
256 std::map<String, String> ref_comparison_hash_map;
257 ref_reader->fillComparisonHash(ref_comparison_hash_map);
258 if (is_master) {
259 Int32 nb_variable = 0;
260 Int32 nb_compared = 0;
262 for (VariableCollection::Enumerator ivar(variables); ++ivar;) {
263 IVariable* var = *ivar;
264 String var_full_name = var->fullName();
265 ++nb_variable;
268 if (!ref_hash.empty() && !current_hash.empty()) {
269 ++nb_compared;
270 if (ref_hash != current_hash) {
271 info() << "Different hash ref_hash=" << ref_hash << " current=" << current_hash
272 << " var=" << var_full_name;
273 ++nb_different;
274 }
275 else
276 info(4) << "Found Hash hash=" << ref_hash << " var=" << var_full_name;
277 }
278 }
279 info() << "NbVariable=" << nb_variable << " nb_compared=" << nb_compared << " nb_different=" << nb_different;
280 }
281}
282
283/*---------------------------------------------------------------------------*/
284/*---------------------------------------------------------------------------*/
285
286/*---------------------------------------------------------------------------*/
287/*---------------------------------------------------------------------------*/
288
291{
292 public:
293
296 {
297 }
298};
299
300/*---------------------------------------------------------------------------*/
301/*---------------------------------------------------------------------------*/
302
305{
306 public:
307
310 {
311 _setFormatVersion(3);
312 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_VERIF_HASHONLY", true)) {
313 bool use_hash = (v.value() != 0);
314 info() << "ArcaneBasicVerifierServiceV3: using hash?=" << use_hash;
316 }
317 }
318};
319
320/*---------------------------------------------------------------------------*/
321/*---------------------------------------------------------------------------*/
322
324 ServiceProperty("ArcaneBasicVerifier2", ST_SubDomain),
326
328 ServiceProperty("ArcaneBasicVerifier3", ST_SubDomain),
330
331/*---------------------------------------------------------------------------*/
332/*---------------------------------------------------------------------------*/
333
334/*---------------------------------------------------------------------------*/
335/*---------------------------------------------------------------------------*/
336
337} // End namespace Arcane
338
339/*---------------------------------------------------------------------------*/
340/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Ce fichier contient les différentes fabriques de services et macro pour enregistrer les services.
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
void build() override
Construction de niveau build du service.
void doVerifFromReferenceFile(bool parallel_sequential, bool compare_ghost) override
Effectue la vérification à partir du fichier référence.
void writeReferenceFile() override
Ecrit le fichier référence.
Interface d'une donnée.
Definition IData.h:33
Interface d'un algorithme de hashage.
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual bool isMasterIO() const =0
true si l'instance est un gestionnaire maître des entrées/sorties.
virtual bool isParallel() const =0
Retourne true si l'exécution est parallèle.
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual IVariableMng * variableMng()=0
Retourne le gestionnaire de variables.
Interface du gestionnaire de variables.
virtual IVariable * findVariableFullyQualified(const String &name)=0
Retourne la variable de nom complet name ou 0 si aucune de se nom existe.
Interface d'une variable.
Definition IVariable.h:54
Interface du service de vérification des données entre deux exécutions.
@ Values
Compare toutes les valeurs.
@ HashOnly
Compare uniquement les hash des valeurs.
Groupe d'entités de maillage.
Definition ItemGroup.h:49
bool null() const
true is le groupe est le groupe nul
Definition ItemGroup.h:70
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
liste de 'ParallelDataWriter'.
Structure contenant les informations pour créer un service.
Propriétés de création d'un service.
Collection de variables.
Meta-données sur une variable.
Classe de base du service de vérification des données entre deux exécutions.
String fileName() const override
Nom du fichier contenant les valeurs de référence.
virtual void _getVariables(VariableList variables, bool parallel_sequential)
Remplit dans variables la liste des variables devant être relues.
void setCompareMode(eCompareMode v) override
Type de comparaison souhaité
String subDir() const override
Nom du fichier contenant les valeurs de référence.
Interface pour retrouver le groupe associée à une variable à partir de ces meta-données.
Definition BasicReader.h:45
Lecture/Ecriture simple.
Definition BasicWriter.h:38
Interface du gestionnaire de traces.
Constructeur de chaîne de caractère unicode.
Chaîne de caractères unicode.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
@ ST_SubDomain
Le service s'utilise au niveau du sous-domaine.