source: GenericIO.h @ 00587dc

Revision 00587dc, 9.2 KB checked in by Hal Finkel <hfinkel@…>, 10 years ago (diff)

Initial Commit (gio-base-20150317)

  • Property mode set to 100644
Line 
1#ifndef GENERICIO_H
2#define GENERICIO_H
3
4#include <cstdlib>
5#include <vector>
6#include <string>
7#include <iostream>
8#include <limits>
9#include <stdint.h>
10
11#ifndef GENERICIO_NO_MPI
12#include <mpi.h>
13#else
14#include <fstream>
15#endif
16
17#include <unistd.h>
18
19namespace gio {
20
21class GenericFileIO {
22public:
23  virtual ~GenericFileIO() {}
24
25public:
26  virtual void open(const std::string &FN, bool ForReading = false) = 0;
27  virtual void setSize(size_t sz) = 0;
28  virtual void read(void *buf, size_t count, off_t offset,
29                    const std::string &D) = 0;
30  virtual void write(const void *buf, size_t count, off_t offset,
31                     const std::string &D) = 0;
32
33protected:
34  std::string FileName;
35};
36
37#ifndef GENERICIO_NO_MPI
38class GenericFileIO_MPI : public GenericFileIO {
39public:
40  GenericFileIO_MPI(const MPI_Comm &C) : FH(MPI_FILE_NULL), Comm(C) {}
41  virtual ~GenericFileIO_MPI();
42
43public:
44  virtual void open(const std::string &FN, bool ForReading = false);
45  virtual void setSize(size_t sz);
46  virtual void read(void *buf, size_t count, off_t offset, const std::string &D);
47  virtual void write(const void *buf, size_t count, off_t offset, const std::string &D);
48
49protected:
50  MPI_File FH;
51  MPI_Comm Comm;
52};
53
54class GenericFileIO_MPICollective : public GenericFileIO_MPI {
55public:
56  GenericFileIO_MPICollective(const MPI_Comm &C) : GenericFileIO_MPI(C) {}
57
58public:
59  void read(void *buf, size_t count, off_t offset, const std::string &D);
60  void write(const void *buf, size_t count, off_t offset, const std::string &D);
61};
62#endif
63
64class GenericFileIO_POSIX : public GenericFileIO {
65public:
66  GenericFileIO_POSIX() : FH(-1) {}
67  ~GenericFileIO_POSIX();
68
69public:
70  void open(const std::string &FN, bool ForReading = false);
71  void setSize(size_t sz);
72  void read(void *buf, size_t count, off_t offset, const std::string &D);
73  void write(const void *buf, size_t count, off_t offset, const std::string &D);
74
75protected:
76  int FH;
77};
78
79class GenericIO {
80public:
81  enum VariableFlags {
82    VarHasExtraSpace =  (1 << 0), // Note that this flag indicates that the
83                                  // extra space is available, but the GenericIO
84                                  // implementation is required to
85                                  // preserve its contents.
86    VarIsPhysCoordX  =  (1 << 1),
87    VarIsPhysCoordY  =  (1 << 2),
88    VarIsPhysCoordZ  =  (1 << 3),
89    VarMaybePhysGhost = (1 << 4)
90  };
91
92  struct VariableInfo {
93    VariableInfo(const std::string &N, std::size_t S, bool IF, bool IS,
94                 bool PCX, bool PCY, bool PCZ, bool PG)
95      : Name(N), Size(S), IsFloat(IF), IsSigned(IS),
96        IsPhysCoordX(PCX), IsPhysCoordY(PCY), IsPhysCoordZ(PCZ),
97        MaybePhysGhost(PG) {}
98
99    std::string Name;
100    std::size_t Size;
101    bool IsFloat;
102    bool IsSigned;
103    bool IsPhysCoordX, IsPhysCoordY, IsPhysCoordZ;
104    bool MaybePhysGhost;
105  };
106
107public:
108  struct Variable {
109    template <typename T>
110    Variable(const std::string &N, T* D, unsigned Flags = 0)
111      : Name(N), Size(sizeof(T)),
112        IsFloat(!std::numeric_limits<T>::is_integer),
113        IsSigned(std::numeric_limits<T>::is_signed),
114        Data((void *) D), HasExtraSpace(Flags & VarHasExtraSpace),
115        IsPhysCoordX(Flags & VarIsPhysCoordX),
116        IsPhysCoordY(Flags & VarIsPhysCoordY),
117        IsPhysCoordZ(Flags & VarIsPhysCoordZ),
118        MaybePhysGhost(Flags & VarMaybePhysGhost) {}
119
120    Variable(const VariableInfo &VI, void *D, unsigned Flags = 0)
121      : Name(VI.Name), Size(VI.Size), IsFloat(VI.IsFloat),
122        IsSigned(VI.IsSigned), Data(D),
123        HasExtraSpace(Flags & VarHasExtraSpace),
124        IsPhysCoordX((Flags & VarIsPhysCoordX) || VI.IsPhysCoordX),
125        IsPhysCoordY((Flags & VarIsPhysCoordY) || VI.IsPhysCoordY),
126        IsPhysCoordZ((Flags & VarIsPhysCoordZ) || VI.IsPhysCoordZ),
127        MaybePhysGhost((Flags & VarMaybePhysGhost) || VI.MaybePhysGhost) {}
128
129    std::string Name;
130    std::size_t Size;
131    bool IsFloat;
132    bool IsSigned;
133    void *Data;
134    bool HasExtraSpace;
135    bool IsPhysCoordX, IsPhysCoordY, IsPhysCoordZ;
136    bool MaybePhysGhost;
137  };
138
139public:
140  enum FileIO {
141    FileIOMPI,
142    FileIOPOSIX,
143    FileIOMPICollective
144  };
145
146#ifndef GENERICIO_NO_MPI
147  GenericIO(const MPI_Comm &C, const std::string &FN, unsigned FIOT = -1)
148    : NElems(0), FileIOType(FIOT == (unsigned) -1 ? DefaultFileIOType : FIOT),
149      Partition(DefaultPartition), Comm(C), FileName(FN), SplitComm(MPI_COMM_NULL) {
150    std::fill(PhysOrigin, PhysOrigin + 3, 0.0);
151    std::fill(PhysScale,  PhysScale + 3, 0.0);
152  }
153#else
154  GenericIO(const std::string &FN, unsigned FIOT = -1)
155    : NElems(0), FileIOType(FIOT == (unsigned) -1 ? DefaultFileIOType : FIOT),
156      Partition(DefaultPartition), FileName(FN) {
157    std::fill(PhysOrigin, PhysOrigin + 3, 0.0);
158    std::fill(PhysScale,  PhysScale + 3, 0.0);
159  }
160#endif
161
162  ~GenericIO() {
163    close();
164
165#ifndef GENERICIO_NO_MPI
166    if (SplitComm != MPI_COMM_NULL)
167      MPI_Comm_free(&SplitComm);
168#endif
169  }
170
171public:
172  std::size_t requestedExtraSpace() const {
173    return 8;
174  }
175
176  void setNumElems(std::size_t E) {
177    NElems = E;
178
179#ifndef GENERICIO_NO_MPI
180    int IsLarge = E >= CollectiveMPIIOThreshold;
181    int AllIsLarge;
182    MPI_Allreduce(&IsLarge, &AllIsLarge, 1, MPI_INT, MPI_SUM, Comm);
183    if (!AllIsLarge)
184      FileIOType = FileIOMPICollective;
185#endif
186  }
187
188  void setPhysOrigin(double O, int Dim = -1) {
189    if (Dim >= 0)
190      PhysOrigin[Dim] = O;
191    else
192      std::fill(PhysOrigin, PhysOrigin + 3, O);
193  }
194
195  void setPhysScale(double S, int Dim = -1) {
196    if (Dim >= 0)
197      PhysScale[Dim] = S;
198    else
199      std::fill(PhysScale,  PhysScale + 3, S);
200  }
201
202  template <typename T>
203  void addVariable(const std::string &Name, T *Data,
204                   unsigned Flags = 0) {
205    Vars.push_back(Variable(Name, Data, Flags));
206  }
207
208  template <typename T, typename A>
209  void addVariable(const std::string &Name, std::vector<T, A> &Data,
210                   unsigned Flags = 0) {
211    T *D = Data.empty() ? 0 : &Data[0];
212    addVariable(Name, D, Flags);
213  }
214
215  void addVariable(const VariableInfo &VI, void *Data,
216                   unsigned Flags = 0) {
217    Vars.push_back(Variable(VI, Data, Flags));
218  }
219
220#ifndef GENERICIO_NO_MPI
221  // Writing
222  void write();
223#endif
224
225  // Reading
226  void openAndReadHeader(bool MustMatch = true, int EffRank = -1,
227                         bool CheckPartMap = true);
228
229  int readNRanks();
230  void readDims(int Dims[3]);
231
232  // Note: For partitioned inputs, this returns -1.
233  uint64_t readTotalNumElems();
234
235  void readPhysOrigin(double Origin[3]);
236  void readPhysScale(double Scale[3]);
237
238  void clearVariables() { this->Vars.clear(); };
239
240  int getNumberOfVariables() { return this->Vars.size(); };
241
242
243  void getVariableInfo(std::vector<VariableInfo> &VI);
244
245  std::size_t readNumElems(int EffRank = -1);
246  void readCoords(int Coords[3], int EffRank = -1);
247  int readGlobalRankNumber(int EffRank = -1);
248
249 void readData(int EffRank = -1, bool PrintStats = true, bool CollStats = true);
250
251  void close() {
252    FH.close();
253  }
254
255  void setPartition(int P) {
256    Partition = P;
257  }
258
259  static void setDefaultFileIOType(unsigned FIOT) {
260    DefaultFileIOType = FIOT;
261  }
262
263  static void setDefaultPartition(int P) {
264    DefaultPartition = P;
265  }
266
267  static void setNaturalDefaultPartition();
268
269  static void setDefaultShouldCompress(bool C) {
270    DefaultShouldCompress = C;
271  }
272
273#ifndef GENERICIO_NO_MPI
274  static void setCollectiveMPIIOThreshold(std::size_t T) {
275#ifndef GENERICIO_NO_NEVER_USE_COLLECTIVE_IO
276    CollectiveMPIIOThreshold = T;
277#endif
278  }
279#endif
280
281protected:
282  std::vector<Variable> Vars;
283  std::size_t NElems;
284
285  double PhysOrigin[3], PhysScale[3];
286
287  unsigned FileIOType;
288  int Partition;
289#ifndef GENERICIO_NO_MPI
290  MPI_Comm Comm;
291#endif
292  std::string FileName;
293
294  static unsigned DefaultFileIOType;
295  static int DefaultPartition;
296  static bool DefaultShouldCompress;
297
298#ifndef GENERICIO_NO_MPI
299  static std::size_t CollectiveMPIIOThreshold;
300#endif
301
302  std::vector<int> RankMap;
303#ifndef GENERICIO_NO_MPI
304  MPI_Comm SplitComm;
305#endif
306  std::string OpenFileName;
307
308  // This reference counting mechanism allows the the GenericIO class
309  // to be used in a cursor mode. To do this, make a copy of the class
310  // after reading the header but prior to adding the variables.
311  struct FHManager {
312    FHManager() : CountedFH(0) {
313      allocate();
314    }
315
316    FHManager(const FHManager& F) {
317      CountedFH = F.CountedFH;
318      CountedFH->Cnt += 1;
319    }
320
321    ~FHManager() {
322      close();
323    }
324
325    GenericFileIO *&get() {
326      if (!CountedFH)
327        allocate();
328
329      return CountedFH->GFIO;
330    }
331
332    std::vector<char> &getHeaderCache() {
333      if (!CountedFH)
334        allocate();
335
336      return CountedFH->HeaderCache;
337    }
338
339    void allocate() {
340      close();
341      CountedFH = new FHWCnt;
342    };
343
344    void close() {
345      if (CountedFH && CountedFH->Cnt == 1)
346        delete CountedFH;
347      else if (CountedFH)
348        CountedFH->Cnt -= 1;
349
350      CountedFH = 0;
351    }
352
353    struct FHWCnt {
354      FHWCnt() : GFIO(0), Cnt(1) {}
355
356      ~FHWCnt() {
357        close();
358      }
359
360protected:
361      void close() {
362        delete GFIO;
363        GFIO = 0;
364      }
365
366public:
367      GenericFileIO *GFIO;
368      size_t Cnt;
369
370      // Used for reading
371      std::vector<char> HeaderCache;
372    };
373
374    FHWCnt *CountedFH;
375  } FH;
376};
377
378} /* END namespace cosmotk */
379#endif // GENERICIO_H
380
Note: See TracBrowser for help on using the repository browser.