vSMC  v3.0.0
Scalable Monte Carlo
hdf5.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/utility/hdf5.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_UTILITY_HDF5_HPP
33 #define VSMC_UTILITY_HDF5_HPP
34 
35 #include <vsmc/internal/common.hpp>
36 
37 #ifdef VSMC_INTEL
38 #pragma warning(push)
39 #pragma warning(disable : 2282)
40 #endif
41 
42 #include <hdf5.h>
43 
44 #ifdef VSMC_INTEL
45 #pragma warning(pop)
46 #endif
47 
48 #define VSMC_DEFINE_HDF5TYPE(CPPName, CName) \
49  class HDF5##CPPName : public HDF5ID<HDF5##CPPName> \
50  { \
51  public: \
52  HDF5##CPPName(::hid_t id) : HDF5ID<HDF5##CPPName>(id) {} \
53  \
54  static void close(::hid_t id) { ::H5##CName##close(id); } \
55  };
56 
57 namespace vsmc
58 {
59 
60 namespace internal
61 {
62 
63 template <typename Derived>
64 class HDF5ID
65 {
66  public:
67  HDF5ID(::hid_t id) : id_(id) {}
68 
70  {
71  if (good())
72  Derived::close(id_);
73  }
74 
75  ::hid_t id() const { return id_; }
76 
77  bool good() const { return id_ >= 0; }
78 
79  bool operator!() const { return !good(); }
80 
81  explicit operator bool() const { return good(); }
82 
83  private:
84  ::hid_t id_;
85 }; // class HDFID
86 
92 
93 template <typename T>
95 {
96  public:
97  template <typename InputIter>
98  HDF5StoreDataPtr(std::size_t n, InputIter first) : ptr_(nullptr)
99  {
100  set(n, first, std::is_convertible<InputIter, const T *>());
101  }
102 
103  const T *get() const { return ptr_ == nullptr ? data_.data() : ptr_; }
104 
105  private:
106  Vector<T> data_;
107  const T *ptr_;
108 
109  template <typename InputIter>
110  void set(std::size_t, InputIter first, std::true_type)
111  {
112  ptr_ = static_cast<const T *>(first);
113  }
114 
115  template <typename InputIter>
116  void set(std::size_t n, InputIter first, std::false_type)
117  {
118  data_.resize(n);
119  std::copy_n(first, n, data_.begin());
120  }
121 }; // class HDF5StoreDataPtr
122 
123 inline void hdf5_dim(
124  MatrixLayout layout, std::size_t nrow, std::size_t ncol, ::hsize_t *dim)
125 {
126  if (layout == RowMajor) {
127  dim[0] = nrow;
128  dim[1] = ncol;
129  }
130  if (layout == ColMajor) {
131  dim[0] = ncol;
132  dim[1] = nrow;
133  }
134 }
135 
136 template <typename IntType>
137 inline bool hdf5_use_int(std::size_t n, IntType *r, std::false_type)
138 {
139  if (sizeof(int) > sizeof(IntType))
140  return true;
141 
142  bool flag = true;
143  for (std::size_t i = 0; i != n; ++i) {
144  if (r[i] > std::numeric_limits<int>::max()) {
145  flag = false;
146  break;
147  }
148  }
149 
150  return flag;
151 }
152 
153 template <typename IntType>
154 inline bool hdf5_use_int(std::size_t n, IntType *r, std::true_type)
155 {
156  if (sizeof(int) > sizeof(IntType))
157  return true;
158 
159  bool flag = true;
160  for (std::size_t i = 0; i != n; ++i) {
161  if (r[i] < std::numeric_limits<int>::min()) {
162  flag = false;
163  break;
164  }
165  if (r[i] > std::numeric_limits<int>::max()) {
166  flag = false;
167  break;
168  }
169  }
170 
171  return flag;
172 }
173 
174 inline ::hid_t hdf5_datafile(
175  const std::string &filename, bool append, bool read_only)
176 {
177  if (!append)
178  return ::H5Fcreate(
179  filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
180 
181  unsigned flag = 0;
182  if (read_only)
183  flag = H5F_ACC_RDONLY;
184  else
185  flag = H5F_ACC_RDWR;
186 
187  return ::H5Fopen(filename.c_str(), flag, H5P_DEFAULT);
188 }
189 
190 } // namespace vsmc::internal
191 
194 template <typename>
195 inline ::hid_t hdf5_datatype()
196 {
197  return -1;
198 }
199 
202 template <>
203 inline ::hid_t hdf5_datatype<char>()
204 {
205  return ::H5Tcopy(H5T_NATIVE_CHAR);
206 }
207 
210 template <>
212 {
213  return ::H5Tcopy(H5T_NATIVE_SCHAR);
214 }
215 
218 template <>
220 {
221  return ::H5Tcopy(H5T_NATIVE_UCHAR);
222 }
223 
226 template <>
227 inline ::hid_t hdf5_datatype<short>()
228 {
229  return ::H5Tcopy(H5T_NATIVE_SHORT);
230 }
231 
234 template <>
236 {
237  return ::H5Tcopy(H5T_NATIVE_UCHAR);
238 }
239 
242 template <>
243 inline ::hid_t hdf5_datatype<int>()
244 {
245  return ::H5Tcopy(H5T_NATIVE_INT);
246 }
247 
250 template <>
252 {
253  return ::H5Tcopy(H5T_NATIVE_UINT);
254 }
255 
258 template <>
259 inline ::hid_t hdf5_datatype<long>()
260 {
261  return ::H5Tcopy(H5T_NATIVE_LONG);
262 }
263 
266 template <>
268 {
269  return ::H5Tcopy(H5T_NATIVE_ULONG);
270 }
271 
274 template <>
275 inline ::hid_t hdf5_datatype<long long>()
276 {
277  return ::H5Tcopy(H5T_NATIVE_LLONG);
278 }
279 
282 template <>
284 {
285  return ::H5Tcopy(H5T_NATIVE_ULLONG);
286 }
287 
290 template <>
291 inline ::hid_t hdf5_datatype<float>()
292 {
293  return ::H5Tcopy(H5T_NATIVE_FLOAT);
294 }
295 
298 template <>
299 inline ::hid_t hdf5_datatype<double>()
300 {
301  return ::H5Tcopy(H5T_NATIVE_DOUBLE);
302 }
303 
306 template <>
308 {
309  return ::H5Tcopy(H5T_NATIVE_LDOUBLE);
310 }
311 
314 inline std::size_t hdf5load_size(
315  const std::string &filename, const std::string &dataname)
316 {
317  internal::HDF5File datafile(internal::hdf5_datafile(filename, true, true));
318  if (!datafile)
319  return 0;
320 
321  internal::HDF5DataSet dataset(
322  ::H5Dopen(datafile.id(), dataname.c_str(), H5P_DEFAULT));
323  if (!dataset)
324  return 0;
325 
326  internal::HDF5DataSpace dataspace(::H5Dget_space(dataset.id()));
327  if (!dataspace)
328  return 0;
329 
330  ::hssize_t n = ::H5Sget_simple_extent_npoints(dataspace.id());
331  if (n < 0)
332  return 0;
333 
334  return static_cast<std::size_t>(n);
335 }
336 
339 template <typename OutputIter>
340 inline OutputIter hdf5load(
341  const std::string &filename, const std::string &dataname, OutputIter first)
342 {
343  internal::HDF5File datafile(internal::hdf5_datafile(filename, true, true));
344  if (!datafile)
345  return first;
346 
347  internal::HDF5DataSet dataset(
348  ::H5Dopen(datafile.id(), dataname.c_str(), H5P_DEFAULT));
349  if (!dataset)
350  return first;
351 
352  internal::HDF5DataSpace dataspace(::H5Dget_space(dataset.id()));
353  if (!dataspace)
354  return first;
355 
356  ::hssize_t n = ::H5Sget_simple_extent_npoints(dataspace.id());
357  if (n < 0)
358  return first;
359 
360  using T = typename std::iterator_traits<OutputIter>::value_type;
361  std::size_t N = static_cast<std::size_t>(n);
362  ::herr_t err = 0;
363 
364  internal::HDF5DataType src_datatype(::H5Dget_type(dataset.id()));
365  if (!src_datatype)
366  return first;
367 
368  internal::HDF5DataType dst_datatype(hdf5_datatype<T>());
369  if (!dst_datatype)
370  return first;
371 
372  ::htri_t is_eq = ::H5Tequal(src_datatype.id(), dst_datatype.id());
373  if (is_eq < 0)
374  return first;
375 
376  std::size_t src_size = ::H5Tget_size(src_datatype.id());
377  std::size_t dst_size = ::H5Tget_size(dst_datatype.id());
378  std::size_t buf_size = std::max(src_size, dst_size);
379  std::size_t buf_rate =
380  buf_size / dst_size + (buf_size % dst_size == 0 ? 0 : 1);
381  Vector<T> buf(N * buf_rate);
382  err = ::H5Dread(dataset.id(), src_datatype.id(), H5S_ALL, H5S_ALL,
383  H5P_DEFAULT, buf.data());
384  if (err < 0)
385  return first;
386 
387  if (is_eq == 0) {
388  err = ::H5Tconvert(src_datatype.id(), dst_datatype.id(), N, buf.data(),
389  nullptr, H5P_DEFAULT);
390  if (err < 0)
391  return first;
392  }
393 
394  return std::copy_n(buf.begin(), N, first);
395 }
396 
398 template <typename T>
400  const std::string &filename, const std::string &dataname)
401 {
402  Vector<T> vector(hdf5load_size(filename, dataname));
403  hdf5load(filename, dataname, vector.data());
404 }
405 
408 inline void hdf5store(const std::string &filename)
409 {
410  internal::HDF5File datafile(
411  internal::hdf5_datafile(filename, false, false));
412 }
413 
416 inline void hdf5store(
417  const std::string &filename, const std::string dataname, bool append)
418 {
419  internal::HDF5File datafile(
420  internal::hdf5_datafile(filename, append, false));
421  if (datafile) {
422  internal::HDF5Group datagroup(::H5Gcreate2(datafile.id(),
423  dataname.c_str(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
424  }
425 }
426 
429 template <typename InputIter>
430 inline void hdf5store(std::size_t N, InputIter first,
431  const std::string &filename, const std::string &dataname, bool append)
432 {
433  using T = typename std::iterator_traits<InputIter>::value_type;
434 
435  if (N == 0)
436  return;
437 
438  internal::HDF5File datafile(
439  internal::hdf5_datafile(filename, append, false));
440  if (!datafile)
441  return;
442 
443  internal::HDF5DataType datatype(hdf5_datatype<T>());
444  if (!datatype)
445  return;
446 
447  ::hsize_t dim[1] = {N};
448  internal::HDF5DataSpace dataspace(::H5Screate_simple(1, dim, nullptr));
449  if (!dataspace)
450  return;
451 
452  internal::HDF5DataSet dataset(::H5Dcreate2(datafile.id(), dataname.c_str(),
453  datatype.id(), dataspace.id(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
454  if (!dataset)
455  return;
456 
457  internal::HDF5StoreDataPtr<T> dataptr(N, first);
458  ::H5Dwrite(dataset.id(), datatype.id(), H5S_ALL, H5S_ALL, H5P_DEFAULT,
459  dataptr.get());
460 }
461 
464 template <typename T, typename Alloc>
465 inline void hdf5store(const std::vector<T, Alloc> &vector,
466  const std::string &filename, const std::string &dataname, bool append)
467 {
468  hdf5store(vector.size(), vector.data(), filename, dataname, append);
469 }
470 
513 template <typename InputIter>
514 inline void hdf5store(MatrixLayout layout, std::size_t nrow, std::size_t ncol,
515  InputIter first, const std::string &filename, const std::string &dataname,
516  bool append)
517 {
518  using T = typename std::iterator_traits<InputIter>::value_type;
519 
520  if (nrow == 0 || ncol == 0)
521  return;
522 
523  internal::HDF5File datafile(
524  internal::hdf5_datafile(filename, append, false));
525  if (!datafile)
526  return;
527 
528  internal::HDF5DataType datatype(hdf5_datatype<T>());
529  if (!datatype)
530  return;
531 
532  ::hsize_t dim[2];
533  internal::hdf5_dim(layout, nrow, ncol, dim);
534  internal::HDF5DataSpace dataspace(::H5Screate_simple(2, dim, nullptr));
535  if (!dataspace)
536  return;
537 
538  internal::HDF5DataSet dataset(::H5Dcreate2(datafile.id(), dataname.c_str(),
539  datatype.id(), dataspace.id(), H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT));
540  if (!dataset)
541  return;
542 
543  internal::HDF5StoreDataPtr<T> dataptr(nrow * ncol, first);
544  ::H5Dwrite(dataset.id(), datatype.id(), H5S_ALL, H5S_ALL, H5P_DEFAULT,
545  dataptr.get());
546 }
547 
550 template <MatrixLayout Layout, std::size_t Dim, typename T>
551 inline void hdf5store(const StateMatrix<Layout, Dim, T> &state_matrix,
552  const std::string &filename, const std::string &dataname, bool append)
553 {
554  hdf5store(Layout, state_matrix.size(), state_matrix.dim(),
555  state_matrix.data(), filename, dataname, append);
556 }
557 
560 template <typename T>
561 inline void hdf5store(const Particle<T> &particle, const std::string &filename,
562  const std::string &dataname, bool append)
563 {
564  hdf5store(filename, dataname, append);
565  hdf5store(particle.state(), filename, dataname + "/State", true);
566  hdf5store(static_cast<std::size_t>(particle.weight().size()),
567  particle.weight().data(), filename, dataname + "/Weight", true);
568 }
569 
572 template <typename T>
573 inline void hdf5store(const Monitor<T> &monitor, const std::string &filename,
574  const std::string &dataname, bool append)
575 {
576  std::map<std::string, Vector<double>> df = monitor.summary();
577  hdf5store(filename, dataname, append);
578  for (const auto &v : df)
579  hdf5store(v.second, filename, dataname + "/" + v.first, append);
580 }
581 
584 template <typename T>
585 inline void hdf5store(const Sampler<T> &sampler, const std::string &filename,
586  const std::string &dataname, bool append)
587 {
588  std::map<std::string, Vector<double>> df = sampler.summary();
589  hdf5store(filename, dataname, append);
590  for (const auto &v : df)
591  hdf5store(v.second, filename, dataname + "/" + v.first, append);
592 }
593 
594 } // namespace vsmc
595 
596 #endif // VSMC_UTILITY_HDF5_HPP
#define VSMC_DEFINE_HDF5TYPE(CPPName, CName)
Definition: hdf5.hpp:48
Definition: monitor.hpp:48
inline::hid_t hdf5_datatype< long long >()
HDF5 data type specialization for long long.
Definition: hdf5.hpp:275
Particle class representing the whole particle set.
Definition: particle.hpp:83
state_type & state()
Read and write access to the state collection object.
Definition: particle.hpp:168
MatrixLayout
Matrix layout.
Definition: defines.hpp:51
std::size_t hdf5load_size(const std::string &filename, const std::string &dataname)
The number of elements in HDF5 data.
Definition: hdf5.hpp:314
inline::hid_t hdf5_datatype< long double >()
HDF5 data type specialization for long double.
Definition: hdf5.hpp:307
weight_type & weight()
Read and write access to the weight collection object.
Definition: particle.hpp:174
std::map< std::string, Vector< double > > summary() const
Summary of monitor history.
Definition: monitor.hpp:209
inline::hid_t hdf5_datatype< unsigned short >()
HDF5 data type specialization for unsigned short.
Definition: hdf5.hpp:235
void hdf5store(const std::string &filename)
Create a new HDF5 file.
Definition: hdf5.hpp:408
inline::hid_t hdf5_datatype< signed char >()
HDF5 data type specialization for signed char.
Definition: hdf5.hpp:211
bool operator!() const
Definition: hdf5.hpp:79
inline::hid_t hdf5_datatype< unsigned int >()
HDF5 data type specialization for unsigned int.
Definition: hdf5.hpp:251
inline::hid_t hdf5_datatype< float >()
HDF5 data type specialization for float.
Definition: hdf5.hpp:291
inline::hid_t hdf5_datatype< short >()
HDF5 data type specialization for short.
Definition: hdf5.hpp:227
HDF5StoreDataPtr(std::size_t n, InputIter first)
Definition: hdf5.hpp:98
const T * get() const
Definition: hdf5.hpp:103
::hid_t id() const
Definition: hdf5.hpp:75
inline::hid_t hdf5_datatype< char >()
HDF5 data type specialization for char.
Definition: hdf5.hpp:203
bool hdf5_use_int(std::size_t n, IntType *r, std::false_type)
Definition: hdf5.hpp:137
HDF5ID(::hid_t id)
Definition: hdf5.hpp:67
inline::hid_t hdf5_datatype< double >()
HDF5 data type specialization for double.
Definition: hdf5.hpp:299
bool good() const
Definition: hdf5.hpp:77
std::map< std::string, Vector< double > > summary() const
Summary of sampler history.
Definition: sampler.hpp:341
void hdf5_dim(MatrixLayout layout, std::size_t nrow, std::size_t ncol,::hsize_t *dim)
Definition: hdf5.hpp:123
inline::hid_t hdf5_datatype< unsigned long long >()
HDF5 data type specialization for unsigned long.
Definition: hdf5.hpp:283
Monitor for Monte Carlo integration.
Definition: monitor.hpp:62
inline::hid_t hdf5_datafile(const std::string &filename, bool append, bool read_only)
Definition: hdf5.hpp:174
SMC Sampler.
Definition: sampler.hpp:99
inline::hid_t hdf5_datatype< int >()
HDF5 data type specialization for int.
Definition: hdf5.hpp:243
inline::hid_t hdf5_datatype< long >()
HDF5 data type specialization for long.
Definition: hdf5.hpp:259
inline::hid_t hdf5_datatype< unsigned char >()
HDF5 data type specialization for unsigned char.
Definition: hdf5.hpp:219
inline::hid_t hdf5_datatype()
HDF5 data type.
Definition: hdf5.hpp:195
inline::hid_t hdf5_datatype< unsigned long >()
HDF5 data type specialization for unsigned long.
Definition: hdf5.hpp:267
OutputIter hdf5load(const std::string &filename, const std::string &dataname, OutputIter first)
Load HDF5 data.
Definition: hdf5.hpp:340