TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
EcrFicPartageMPIIO.cpp
1/****************************************************************************
2* Copyright (c) 2026, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <EcrFicPartageMPIIO.h>
17#include <OBuffer.h>
18#include <PE_Groups.h>
19#include <communications.h>
20#include <Comm_Group_MPI.h>
21#include <string>
22
23Implemente_instanciable_sans_constructeur_ni_destructeur(EcrFicPartageMPIIO,"EcrFicPartageMPIIO",SFichier);
24
25#ifdef MPI_
26static void handle_error(int errcode, const char *str)
27{
28 char msg[MPI_MAX_ERROR_STRING];
29 int resultlen;
30 MPI_Error_string(errcode, msg, &resultlen);
31 Cerr << "======================" << finl;
32 Cerr << str << ": " << msg << finl;
33 Cerr << "Contact TRUST support." << finl;
35}
36#define MPI_CHECK(fn) { int errcode; errcode = fn;\
37 if (errcode != MPI_SUCCESS) handle_error(errcode, #fn); }
38#endif
39
41{
42 throw;
43}
44
46{
47 throw;
48}
49
51{
52 bin_ = 1; // Binaire par defaut
53#ifdef MPI_
54 mpi_file_=nullptr;
55#endif
56}
61
62#ifdef MPI_
63EcrFicPartageMPIIO::EcrFicPartageMPIIO(const char* name,IOS_OPEN_MODE mode)
64{
65 ouvrir(name, mode);
66}
67
68int EcrFicPartageMPIIO::ouvrir(const char* name,IOS_OPEN_MODE mode)
69{
70 MPI_Comm mpi_comm;
71 if (sub_type(Comm_Group_MPI,PE_Groups::current_group()))
72 mpi_comm = ref_cast(Comm_Group_MPI,PE_Groups::current_group()).get_mpi_comm();
73 else
74 mpi_comm = MPI_COMM_WORLD;
75 int MPI_OPEN = mode == ios::app ? MPI_MODE_APPEND : MPI_MODE_CREATE;
76 int MPI_MODE = (mode == ios::app || ios::out) ? MPI_MODE_WRONLY : MPI_MODE_RDONLY;
77 MPI_CHECK(MPI_File_open(mpi_comm, (char*)name, MPI_OPEN|MPI_MODE, MPI_INFO_NULL, &mpi_file_));
78 // Set MPI errors fatal:
79 MPI_File_set_errhandler(mpi_file_,MPI_ERRORS_ARE_FATAL);
80 // Set initial displacement:
81 disp_=0;
82 // Ecriture d'un entete specifique pour le build int64 ?
83 if (mode==ios::out)
84 {
85 if (je_suis_maitre())
86 {
87#ifdef INT_is_64_
88 Nom marq("INT64");
89 (*this)<<marq.getChar();
90#endif
91 }
92 }
93 /*
94 else
95 {
96 Cerr<<"not coded in EcrFicPartageMPIIO::ouvrir"<<finl;
97 exit();
98 }*/
99 return 1;
100}
101
103{
104 if (mpi_file_) MPI_File_close(&mpi_file_);
105 disp_=0;
106 return;
107}
108
109void EcrFicPartageMPIIO::check()
110{
111 if (Process::me()>0)
112 {
113 Cerr << "Only master process can call EcrFicPartageMPIIO::operator <<(...)" << finl;
114 exit();
115 }
116 MPI_Offset offset; // Relative position
117 MPI_File_get_position(mpi_file_, &offset);
118 MPI_Offset disp; // Absolute position
119 MPI_File_get_byte_offset(mpi_file_, offset, &disp);
120 if (disp_!=disp)
121 {
122 Cerr << "Error in EcrFicPartageMPIIO::check()" << finl;
123 Cerr << "Decalage : disp_= " << (int)disp_ << " disp=" << (int)disp << finl;
124 Cerr << "Contact TRUST support." << finl;
125 }
126}
127
128// Function write used in all the operator<< to avoid to duplicate the code
129void EcrFicPartageMPIIO::write(MPI_Datatype MPI_TYPE, const void* ob)
130{
131 // See explanations in Entree::operator_template() to understand
132 // the conversions made here:
133 bool convert = false;
134 if (MPI_TYPE == MPI_INT || MPI_TYPE == MPI_UNSIGNED)
135 convert = this->must_convert<int>();
136
137 MPI_Datatype MPI_TYPE2 = MPI_TYPE;
138 const void * ob2 = ob;
139 long l_val = 0;
140 unsigned long u_val = 0;
141 if(convert)
142 {
143 if (MPI_TYPE == MPI_INT)
144 {
145 l_val = *(static_cast<const int *>(ob)); // upcast
146 MPI_TYPE2 = MPI_LONG;
147 ob2 = &l_val;
148
149 }
150 else if (MPI_TYPE == MPI_UNSIGNED)
151 {
152 u_val = *(static_cast<const unsigned *>(ob)); // upcast
153 MPI_TYPE2 = MPI_UNSIGNED_LONG;
154 ob2 = &u_val;
155 }
156 else
157 Process::exit("EcrFicPartageMPIIO::write() -- Unexpected type!!");
158 }
159 int size;
160 MPI_Type_size(MPI_TYPE2, &size);
161 MPI_File_write(mpi_file_, ob2, 1, MPI_TYPE2, &mpi_status_);
162 disp_+=size;
163 check();
164}
165
167{
168 if (bin_)
169 {
170 // On n'ecrit pas les separateurs. Voir Sortie::operator<<(const Separateur& ob)
171 check();
172 }
173 else
174 {
175 if (ob.get_type() == ob.ENDL)
176 (*this)<<"\n";
177 else if (ob.get_type() == ob.SPACE)
178 (*this)<<" ";
179 else
180 {
181 Cerr << "Unknown separator in EcrFicPartageMPIIO::operator <<" << finl;
183 }
184 }
185 return *this;
186}
187
189{
190 int size=(int)strlen(ob) + 1;
191 //int size=strlen(ob);
192 for (int i=0; i<size; i++)
193 write(MPI_CHAR, &ob[i]);
194 return *this;
195}
196
197Sortie& EcrFicPartageMPIIO::operator <<(const std::string& str)
198{
199 return (*this) << str.c_str();
200}
201
203{
204 if (bin_)
205 write(MPI_INT, &ob);
206 else
207 (*this)<<std::to_string(ob).c_str();
208 return *this;
209}
210
211Sortie& EcrFicPartageMPIIO::operator <<(const unsigned ob)
212{
213 if (bin_)
214 write(MPI_UNSIGNED, &ob);
215 else
216 (*this)<<std::to_string(ob).c_str();
217 return *this;
218}
219
221{
222 if (bin_)
223 write(MPI_LONG, &ob);
224 else
225 (*this)<<std::to_string(ob).c_str();
226 return *this;
227}
228
229Sortie& EcrFicPartageMPIIO::operator <<(const long long ob)
230{
231 if (bin_)
232 write(MPI_LONG_LONG, &ob);
233 else
234 (*this)<<std::to_string(ob).c_str();
235 return *this;
236}
237
238Sortie& EcrFicPartageMPIIO::operator <<(const unsigned long ob)
239{
240 if (bin_)
241 write(MPI_UNSIGNED_LONG, &ob);
242 else
243 (*this)<<std::to_string(ob).c_str();
244 return *this;
245}
246
248{
249 if (bin_)
250 write(MPI_FLOAT, &ob);
251 else
252 (*this)<<std::to_string(ob).c_str();
253 return *this;
254}
256{
257 if (bin_)
258 write(MPI_DOUBLE, &ob);
259 else
260 (*this)<<std::to_string(ob).c_str(); // ToDo utiliser snprintf
261 return *this;
262}
264{
265 ob.printOn(*this);
266 check();
267 return *this;
268}
269
270int EcrFicPartageMPIIO::put(const unsigned* ob, std::streamsize n, std::streamsize pas)
271{
272 assert(n < std::numeric_limits<int>::max());
273 if (is_64b_)
274 Process::exit("EcrFicPartageMPIIO::put() not implemented for cross bitness (writing 'int' in a 64b file for example!");
275 return put(MPI_UNSIGNED, ob, (int)n);
276}
277
278int EcrFicPartageMPIIO::put(const int* ob, std::streamsize n, std::streamsize pas)
279{
280 assert(n < std::numeric_limits<int>::max());
281 if (is_64b_)
282 Process::exit("EcrFicPartageMPIIO::put() not implemented for cross bitness (writing 'int' in a 64b file for example!");
283 return put(MPI_INT, ob, (int)n);
284}
285
286int EcrFicPartageMPIIO::put(const long* ob, std::streamsize n, std::streamsize pas)
287{
288 assert(n < std::numeric_limits<int>::max());
289 return put(MPI_LONG, ob, (int)n);
290}
291
292int EcrFicPartageMPIIO::put(const long long* ob, std::streamsize n, std::streamsize pas)
293{
294 assert(n < std::numeric_limits<int>::max());
295 return put(MPI_LONG_LONG, ob, (int)n);
296}
297
298int EcrFicPartageMPIIO::put(const float* ob, std::streamsize n, std::streamsize pas)
299{
300 assert(n < std::numeric_limits<int>::max());
301 return put(MPI_FLOAT, ob, (int)n);
302}
303
304int EcrFicPartageMPIIO::put(const double* ob, std::streamsize n, std::streamsize pas)
305{
306 assert(n < std::numeric_limits<int>::max());
307 return put(MPI_DOUBLE, ob, (int)n);
308}
309
310
311// Function used for different MPI_Type
312// Good info/examples on MPI-IO:
313// See page 213: http://www.idris.fr/data/cours/parallel/mpi/IDRIS_MPI_cours_couleurs.pdf
314// See http://www.cac.cornell.edu/ranger/mpiadvtopics/fileptroffs.aspx
315// Default file view has etype=filetype=MPI_Byte and disp=0
316// MPI_File_get_position returns a relative offset in etype units of the current view
317// MPI_File_get_byte_offset converts a view relative offset (etype units) into an absolute byte position
318// MPI_File_set_view(file,disp,etype,...) disp should be specified in absolute bytes from the start of the file
319// sizeof(MPI_DOUBLE)=4 !!! Should use:MPI_Type_size( MPI_DOUBLE, &size ) to return 8 !!!
320// Ecriture d'une zone memoire pointee par ob contenant n MPI_TYPE :
321int EcrFicPartageMPIIO::put(MPI_Datatype MPI_TYPE, const void* ob, int n)
322{
323 MPI_Datatype etype;
324 etype=MPI_TYPE;
325 int sizeof_etype;
326 MPI_Type_size(etype,&sizeof_etype);
327
328 // filetype is n etype contigous:
329 MPI_Datatype filetype;
330 MPI_Type_contiguous(n, etype, &filetype);
331 MPI_Type_commit(&filetype);
332
333 // Before collecting operations, update disp_ on all processes:
334 envoyer_broadcast(disp_, 0);
335 MPI_Offset disp_me = disp_ + Process::mppartial_sum(n) * sizeof_etype;
336 // ROMIO hints:
337 if (Process::nproc()>1024)
338 {
339 char* ROMIO_HINTS=getenv("ROMIO_HINTS");
340 if (ROMIO_HINTS==nullptr)
341 {
342 Cerr << "Warning, no ROMIO_HINTS detected on your massive parallel calculation." << finl;
343 Cerr << "Performances of MPI I/O could be improved with ROMIO hints." << finl;
344 Cerr << "Contact TRUST support." << finl;
345 }
346 }
347
348 // Create info for using hints:
349 MPI_Info mpi_info;
350 MPI_Info_create(&mpi_info);
351 // Example (not used cause machine dependant):
352 /*
353 MPI_Info_set(mpi_info, "romio_cb_read", "enable");
354 MPI_Info_set(mpi_info, "romio_cb_write", "enable");
355 // Un processus par node s'occupe du buffering:
356 MPI_Info_set(mpi_info, "cb_config_list", "*:1");
357
358 // Striping count (max 160 sur LUSTRE):
359 Nom striping_factor=(Nom)min(Process::nproc(),160);
360 MPI_Info_set(mpi_info, "striping_factor", (char*)striping_factor.getChar());
361
362 // Striping units in bytes (ideal is stripe size = I/O operations):
363 Nom striping_unit=(Nom)(n * sizeof_etype);
364 MPI_Info_set(mpi_info, "striping_unit", (char*)striping_unit.getChar());
365 */
366
367 // Set a new view:
368 MPI_File_set_view(mpi_file_, disp_me, etype, filetype, (char*)"native", mpi_info);
369
370 // Write all:
371 statistics().begin_count(STD_COUNTERS::IO_EcrireFicPartageMPIIO,statistics().get_last_opened_counter_level()+1);
372 MPI_File_write_all(mpi_file_, (void*)ob, n, etype, MPI_STATUS_IGNORE);
373 statistics().end_count(STD_COUNTERS::IO_EcrireFicPartageMPIIO,1,n * sizeof_etype);
374
375 // Update the position of the pointer file:
376 disp_+=mp_sum(n) * sizeof_etype;
377
378 // Reset a simple view at this new position:
379 MPI_File_set_view(mpi_file_, disp_, MPI_BYTE, MPI_BYTE, (char*)"native", MPI_INFO_NULL);
380
381 // Free
382 MPI_Info_free(&mpi_info);
383 MPI_Type_free(&filetype);
384 return 1;
385}
386
387#endif
bool bin_
Is this a binary flux?
Definition AbstractIO.h:50
bool is_64b_
Will we be reading/writing in 64b? (Init in ctor to avoid including arch.h probably).
Definition AbstractIO.h:51
bool must_convert() const
Whether to convert an int into a long when reading/writing out data.
Class to use MPI-IO to write in a single file.
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
classe Objet_U Cette classe est la classe de base des Objets de TRUST
Definition Objet_U.h:73
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
static const Comm_Group & current_group()
renvoie une reference au groupe de processeurs actif courant
Definition PE_Groups.h:65
void begin_count(const STD_COUNTERS &std_cnt, int counter_lvl=-100000)
void end_count(const std::string &custom_count_name, int count_increment=1, long int quantity_increment=0)
End the count of a counter and update the counter values.
static trustIdType mppartial_sum(trustIdType i)
Calul de la somme partielle de i sur les processeurs 0 a me()-1 (renvoie 0 sur le processeur 0).
Definition Process.cpp:396
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
static int je_suis_maitre()
renvoie 1 si on est sur le processeur maitre du groupe courant (c'est a dire me() == 0),...
Definition Process.cpp:86
Cette classe est a la classe C++ ofstream ce que la classe Sortie est a la classe C++ ostream Elle re...
Definition SFichier.h:27
SFichier(const char *name, IOS_OPEN_MODE mode=ios::out)
Definition SFichier.h:30
Separateur pour les fichiers.
Definition Separateur.h:30
const Type & get_type() const
Definition Separateur.h:34
virtual int ouvrir(const char *name, IOS_OPEN_MODE mode=ios::out)
Classe de base des flux de sortie.
Definition Sortie.h:52
virtual int put(const unsigned *ob, std::streamsize n, std::streamsize nb_colonnes=1)
Definition Sortie.cpp:101
Sortie & operator<<(ostream &(*f)(ostream &))
Definition Sortie.cpp:116