Serialbox  2.2.0
Data serialization library and tools for C/C++, Python and Fortran
Serializer.h
Go to the documentation of this file.
1 //===-- serialbox/core/frontend/stella/Serializer.h ---------------------------------*- C++ -*-===//
2 //
3 // S E R I A L B O X
4 //
5 // This file is distributed under terms of BSD license.
6 // See LICENSE.txt for more information
7 //
8 //===------------------------------------------------------------------------------------------===//
9 //
13 //===------------------------------------------------------------------------------------------===//
14 
15 #ifndef SERIALBOX_CORE_FRONTEND_STELLA_SERIALIZER_H
16 #define SERIALBOX_CORE_FRONTEND_STELLA_SERIALIZER_H
17 
18 #ifdef SERIALBOX_HAS_STELLA
19 #include "DataFieldStorageFormat.h"
20 #include "DataFieldStorageStrides.h"
21 #endif
22 
29 #include <boost/shared_ptr.hpp>
30 #include <map>
31 #include <sstream>
32 #include <string>
33 #include <vector>
34 
35 namespace serialbox {
36 
37 namespace stella {
38 
44  SerializerOpenModeRead,
45  SerializerOpenModeWrite,
46  SerializerOpenModeAppend
47 };
48 
52 class Serializer {
53 public:
54  Serializer();
55 
65  static void EnableSerialization();
66 
76  static void DisableSerialization();
77 
81  SerializerOpenMode mode() const;
82 
86  std::string directory() const;
87 
91  std::string prefix() const;
92 
106  void Init(const std::string& directory, const std::string& prefix, SerializerOpenMode mode);
107 
108  //===----------------------------------------------------------------------------------------===//
109  // Global meta-information
110  //===----------------------------------------------------------------------------------------===//
111 
113  const MetainfoSet& globalMetainfo() const { return globalMetainfo_; }
114 
118  template <typename ValueType>
119  void AddMetainfo(const std::string& key, ValueType value) {
120  globalMetainfo_.AddMetainfo(key, value);
121  }
122 
123  //===----------------------------------------------------------------------------------------===//
124  // Register fields
125  //===----------------------------------------------------------------------------------------===//
126 
153  bool RegisterField(const std::string& name, std::string type, int bytesPerElement, int iSize,
154  int jSize, int kSize, int lSize, int iMinusHalo, int iPlusHalo, int jMinusHalo,
155  int jPlusHalo, int kMinusHalo, int kPlusHalo, int lMinusHalo, int lPlusHalo);
156 
160  const DataFieldInfo& FindField(const std::string& fieldname) const;
161 
166  void AddFieldMetainfo(const std::string& fieldname, const std::string& key, bool value);
167  void AddFieldMetainfo(const std::string& fieldname, const std::string& key, int value);
168  void AddFieldMetainfo(const std::string& fieldname, const std::string& key, float value);
169  void AddFieldMetainfo(const std::string& fieldname, const std::string& key, double value);
170  void AddFieldMetainfo(const std::string& fieldname, const std::string& key, std::string value);
171  void AddFieldMetainfo(const std::string& fieldname, const std::string& key, const char* value) {
172  AddFieldMetainfo(fieldname, key, std::string(value));
173  }
175 
181  std::vector<std::string> fieldnames() const;
182 
186  const std::vector<Savepoint>& savepoints() const { return savepoints_; }
187 
194  std::vector<std::string> FieldsAtSavepoint(const Savepoint& savepoint) const;
195 
196  //===----------------------------------------------------------------------------------------===//
197  // Writing
198  //===----------------------------------------------------------------------------------------===//
199 
215  void WriteField(const std::string& fieldName, const Savepoint& savepoint, const void* pData,
216  int iStride, int jStride, int kStride, int lStride);
217 
218 #ifdef SERIALBOX_HAS_STELLA
219  template <typename TDataField>
238  void WriteField(std::string name, const TDataField& field, const Savepoint& savepoint);
239 #endif
240 
241  //===----------------------------------------------------------------------------------------===//
242  // Reading
243  //===----------------------------------------------------------------------------------------===//
244 
263  void ReadField(const std::string& fieldName, const Savepoint& savepoint, void* pData, int iStride,
264  int jStride, int kStride, int lStride, bool alsoPrevious = false) const;
265 
266 #ifdef SERIALBOX_HAS_STELLA
267  template <typename TDataField>
285  void ReadField(std::string name, TDataField& field, const Savepoint& savepoint,
286  bool alsoPrevious = false) const;
287 #endif
288 
290  std::string ToString() const;
291 
293  boost::shared_ptr<SerializerImpl>& getImpl() { return serializerImpl_; }
294  const boost::shared_ptr<SerializerImpl>& getImpl() const { return serializerImpl_; }
295 
296 private:
297  // Implementation pointer
298  boost::shared_ptr<SerializerImpl> serializerImpl_;
299 
300  // These data-strucures allow to return refrences but do not actually own any data but they need
301  // to be kept in sync with the data from serializerImpl!
302  MetainfoSet globalMetainfo_;
303  std::vector<Savepoint> savepoints_;
304  std::map<std::string, DataFieldInfo> datafieldInfos_;
305 
306  // This variable can take three values:
307  //
308  // 0: the variable is not yet initialized -> the serialization is enabled if the environment
309  // variable STELLA_SERIALIZATION_DISABLE is not set to a positive value. The first
310  // serializer which is initialized has to set this value either to +1 or to -1 according to
311  // the environment.
312  // +1: the serialization is enabled, independently of the environment
313  // -1: the serialization is disabled, independently of the environment
314  //
315  // The value is initialized to 0
316  static int enabled_;
317 };
318 
319 //===------------------------------------------------------------------------------------------===//
320 // Implementation of template methods
321 //===------------------------------------------------------------------------------------------===//
322 
323 #ifdef SERIALBOX_HAS_STELLA
324 template <typename TDataField>
325 void Serializer::WriteField(std::string name, const TDataField& field, const Savepoint& savepoint) {
326 
327  if(name.empty())
328  name = field.name();
329 
330  // Retrieve size, boundaries and strides
331  IJKSize size;
332  size.Init(field.storage().allocatedSize().iSize(), field.storage().allocatedSize().jSize(),
333  field.storage().allocatedSize().kSize());
334 
335  IJKBoundary boundary;
336  boundary.Init(field.boundary().iMinusOffset(), field.boundary().iPlusOffset(),
337  field.boundary().jMinusOffset(), field.boundary().jPlusOffset(),
338  field.boundary().kMinusOffset(), field.boundary().kPlusOffset());
339 
340  const int bytesPerElement = sizeof(typename TDataField::ValueType);
341 
342  DataFieldStorageStrides<typename TDataField::StorageFormat::StorageOrder> strides;
343  strides.Init(field.storage().paddedSize());
344  const int iStride = strides.ComputeStride(1, 0, 0) * bytesPerElement;
345  const int jStride = strides.ComputeStride(0, 1, 0) * bytesPerElement;
346  const int kStride = strides.ComputeStride(0, 0, 1) * bytesPerElement;
347 
348  // Register field
349  this->RegisterField(name, type_name<typename TDataField::ValueType>(), bytesPerElement,
350  size.iSize(), size.jSize(), size.kSize(), 1, -boundary.iMinusOffset(),
351  boundary.iPlusOffset(), -boundary.jMinusOffset(), boundary.jPlusOffset(),
352  -boundary.kMinusOffset(), boundary.kPlusOffset(), 0, 0);
353 
354  this->WriteField(name, savepoint, field.storage().pStorageBase(), iStride, jStride, kStride, 0);
355 }
356 
357 template <typename TDataField>
358 void Serializer::ReadField(std::string name, TDataField& field, const Savepoint& savepoint,
359  bool alsoPrevious) const {
360  typedef typename TDataField::ValueType ValueType;
361 
362  if(name.empty())
363  name = field.name();
364 
365  // Get info of serialized field
366  const DataFieldInfo& info = FindField(name);
367  const int bytesPerElement = sizeof(typename TDataField::ValueType);
368 
369  // Get strides according to STELLA
370  DataFieldStorageStrides<typename TDataField::StorageFormat::StorageOrder> stridesSTELLA;
371  stridesSTELLA.Init(field.storage().paddedSize());
372 
373  // Get rid of degenerated dimensions and fix strides
374  std::vector<int> allSizes, size, allStrides, strides;
375  allSizes.push_back(field.storage().allocatedSize().iSize());
376  allSizes.push_back(field.storage().allocatedSize().jSize());
377  allSizes.push_back(field.storage().allocatedSize().kSize());
378  allSizes.push_back(0);
379  allStrides.push_back(stridesSTELLA.ComputeStride(1, 0, 0) * bytesPerElement);
380  allStrides.push_back(stridesSTELLA.ComputeStride(0, 1, 0) * bytesPerElement);
381  allStrides.push_back(stridesSTELLA.ComputeStride(0, 0, 1) * bytesPerElement);
382  for (int i = 0; i < 4; ++i) {
383  if (allSizes[i] > 1)
384  {
385  size.push_back(allSizes[i]);
386  strides.push_back(allStrides[i]);
387  }
388  }
389  size.resize(4, 0);
390 
391  IJKBoundary boundary;
392  boundary.Init(field.boundary().iMinusOffset(), field.boundary().iPlusOffset(),
393  field.boundary().jMinusOffset(), field.boundary().jPlusOffset(),
394  field.boundary().kMinusOffset(), field.boundary().kPlusOffset());
395 
396 
397  if((info.iSize() != size[0]) || (info.jSize() != size[1]) ||
398  (info.kSize() != size[2]) || (info.lSize() != 0)) {
399  // Throw exception
400  std::ostringstream errorstr;
401  errorstr << "Error: the requested field " << name << " has a different size than"
402  << " the provided data field.\n";
403  errorstr << "Registerd as: " << info.iSize() << "x" << info.jSize() << "x" << info.kSize()
404  << "x" << info.lSize() << "\n";
405  errorstr << "Given : " << size[0] << "x" << size[1] << "x" << size[2]
406  << "x" << size[3] << "x0" << "\n";
408  exception.Init(errorstr.str());
409  throw exception;
410  }
411 
412  // Check data type
413  if(info.type() != type_name<ValueType>()) {
414  // Throw exception
415  std::ostringstream errorstr;
416  errorstr << "Error: the requested field " << name << " has different type than"
417  << " the provided data field (expected " << info.type() << ", got "
418  << type_name<ValueType>() << ")";
420  exception.Init(errorstr.str());
421  throw exception;
422  }
423 
424  // This hack is used to retrieve the storage pointer for the host memory in case of GPU fields
425  // This will synchronize the host storage
426  ValueType* data =
427  &field(boundary.iMinusOffset(), boundary.jMinusOffset(), boundary.kMinusOffset());
428 
429  // Perform the read
430  this->ReadField(name, savepoint, data, strides[0], strides[1], strides[2], 0, alsoPrevious);
431 }
432 #endif
433 
434 } // namespace stella
435 
436 } // namespace serialbox
437 
438 #endif
boost::shared_ptr< SerializerImpl > & getImpl()
Get implementation pointer.
Definition: Serializer.h:293
int iSize() const
The size of the field in i-direction, including the halo.
static void EnableSerialization()
Enable serialization.
Definition: Serializer.cpp:43
std::vector< std::string > fieldnames() const
Gives access to the registered fields.
Definition: Serializer.cpp:207
int kSize() const
The size of the field in k-direction, including the halo.
Information of a data-field.
Definition: DataFieldInfo.h:31
int kMinusOffset() const
Offset in k-minus direction.
Definition: IJKBoundary.h:98
int lSize() const
The size of the field in l-direction, including the halo.
void AddMetainfo(const std::string &key, ValueType value)
Definition: Serializer.h:119
void Init(const std::string &directory, const std::string &prefix, SerializerOpenMode mode)
Initializes the serializer.
Definition: Serializer.cpp:51
void ReadField(const std::string &fieldName, const Savepoint &savepoint, void *pData, int iStride, int jStride, int kStride, int lStride, bool alsoPrevious=false) const
Deserializes data from file.
Definition: Serializer.cpp:267
int jSize() const
Size in j dimension.
Definition: IJKSize.h:66
int jPlusOffset() const
Offset in j-plus direction.
Definition: IJKBoundary.h:95
std::string type() const
The field scalar type.
std::string ToString() const
Convert to string.
Definition: Serializer.cpp:286
std::string prefix() const
Prefix of the files.
Definition: Serializer.cpp:49
Namespace of the STELLA frontend.
Definition: ForwardDecl.h:27
Namespace of the serialbox library.
Definition: Archive.h:25
Meta-information set.
Definition: MetainfoSet.h:36
static void DisableSerialization()
Disable serialization.
Definition: Serializer.cpp:45
Implementation of the STELLA Savepoint.
Definition: Savepoint.h:30
int jMinusOffset() const
Offset in j-minus direction.
Definition: IJKBoundary.h:92
std::vector< std::string > FieldsAtSavepoint(const Savepoint &savepoint) const
Gives all fields which are available at the given savepoint and return their names.
Definition: Serializer.cpp:209
Exception of the STELLA frontend.
const MetainfoSet & globalMetainfo() const
Read-only access to the metainformation.
Definition: Serializer.h:113
serialbox::Exception exception
Exception class which stores a human-readable error description.
Definition: Exception.h:33
const std::vector< Savepoint > & savepoints() const
Gives access to the list of savepoints.
Definition: Serializer.h:186
SerializerOpenMode
OpenPolicy of the Serializer.
Definition: Serializer.h:43
void Init(const int iMinusOffset, const int iPlusOffset, const int jMinusOffset, const int jPlusOffset, const int kMinusOffset, const int kPlusOffset)
Init the container.
Definition: IJKBoundary.h:75
int kPlusOffset() const
Offset in k-plus direction.
Definition: IJKBoundary.h:101
void AddFieldMetainfo(const std::string &fieldname, const std::string &key, bool value)
Adds a key-value metainformation pair to a field.
Definition: Serializer.cpp:158
bool RegisterField(const std::string &name, std::string type, int bytesPerElement, int iSize, int jSize, int kSize, int lSize, int iMinusHalo, int iPlusHalo, int jMinusHalo, int jPlusHalo, int kMinusHalo, int kPlusHalo, int lMinusHalo, int lPlusHalo)
Register a field into the serializer.
Definition: Serializer.cpp:93
const DataFieldInfo & FindField(const std::string &fieldname) const
Gives access to field info.
Definition: Serializer.cpp:146
int iSize() const
Size in i dimension.
Definition: IJKSize.h:63
Container for i, j, k Size.
Definition: IJKSize.h:27
SerializerOpenMode mode() const
Open mode.
Definition: Serializer.cpp:30
void WriteField(const std::string &fieldName, const Savepoint &savepoint, const void *pData, int iStride, int jStride, int kStride, int lStride)
Serializes data to file.
Definition: Serializer.cpp:243
void Init(const int iSize, const int jSize, const int kSize)
Init the container.
Definition: IJKSize.h:55
Container for the boundary size.
Definition: IJKBoundary.h:36
int kSize() const
Size in k dimension.
Definition: IJKSize.h:69
int iPlusOffset() const
Offset in i-plus direction.
Definition: IJKBoundary.h:89
int iMinusOffset() const
Offset in i-minus direction.
Definition: IJKBoundary.h:86
void AddMetainfo(const std::string &key, const int &value)
Add a new key-value pair into the set. The key must not exist yet.
Definition: MetainfoSet.cpp:58
void Init(const std::string &errormsg)
Initialize the exception with an explanatory string errormsg
Implementation of the STELLA Serializer.
Definition: Serializer.h:52
std::string directory() const
Directory where the data are stored.
Definition: Serializer.cpp:47
int jSize() const
The size of the field in j-direction, including the halo.