gem5  v22.1.0.0
hdf5.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016-2019 Arm Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met: redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer;
18  * redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in the
20  * documentation and/or other materials provided with the distribution;
21  * neither the name of the copyright holders nor the names of its
22  * contributors may be used to endorse or promote products derived from
23  * this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 #include "base/stats/hdf5.hh"
39 
40 #include "base/logging.hh"
41 #include "base/stats/info.hh"
42 #include "base/trace.hh"
43 #include "debug/Stats.hh"
44 
45 namespace gem5
46 {
47 
51 template<typename T>
52 bool emptyStrings(const T &labels)
53 {
54  for (const auto &s : labels) {
55  if (!s.empty())
56  return false;
57  }
58  return true;
59 }
60 
61 
62 GEM5_DEPRECATED_NAMESPACE(Stats, statistics);
63 namespace statistics
64 {
65 
66 Hdf5::Hdf5(const std::string &file, unsigned chunking,
67  bool desc, bool formulas)
68  : fname(file), timeChunk(chunking),
69  enableDescriptions(desc), enableFormula(formulas),
70  dumpCount(0)
71 {
72  // Tell the library not to print exceptions by default. There are
73  // cases where we rely on exceptions to determine if we need to
74  // create a node or if we can just open it.
75  H5::Exception::dontPrint();
76 }
77 
79 {
80 }
81 
82 
83 void
85 {
86  h5File = H5::H5File(fname,
87  // Truncate the file if this is the first dump
88  dumpCount > 0 ? H5F_ACC_RDWR : H5F_ACC_TRUNC);
89  path.push(h5File.openGroup("/"));
90 }
91 
92 void
94 {
95  assert(valid());
96 
97  dumpCount++;
98 }
99 
100 bool
101 Hdf5::valid() const
102 {
103  return true;
104 }
105 
106 
107 void
108 Hdf5::beginGroup(const char *name)
109 {
110  auto base = path.top();
111 
112  // Try to open an existing stat group corresponding to the
113  // name. Create it if it doesn't exist.
114  H5::Group group;
115  try {
116  group = base.openGroup(name);
117  } catch (const H5::FileIException& e) {
118  group = base.createGroup(name);
119  } catch (const H5::GroupIException& e) {
120  group = base.createGroup(name);
121  }
122 
123  path.push(group);
124 }
125 
126 void
128 {
129  assert(!path.empty());
130  path.pop();
131 }
132 
133 void
135 {
136  // Since this stat is a scalar, we need 1-dimensional value in the
137  // stat file. The Hdf5::appendStat helper will populate the size
138  // of the first dimension (time).
139  hsize_t fdims[1] = { 0, };
140  double data[1] = { info.result(), };
141 
142  appendStat(info, 1, fdims, data);
143 }
144 
145 void
147 {
148  appendVectorInfo(info);
149 }
150 
151 void
152 Hdf5::visit(const DistInfo &info)
153 {
154  warn_once("HDF5 stat files don't support distributions.\n");
155 }
156 
157 void
159 {
160  warn_once("HDF5 stat files don't support vector distributions.\n");
161 }
162 
163 void
165 {
166  // Request a 3-dimensional stat, the first dimension will be
167  // populated by the Hdf5::appendStat() helper. The remaining two
168  // dimensions correspond to the stat instance.
169  hsize_t fdims[3] = { 0, info.x, info.y };
170  H5::DataSet data_set = appendStat(info, 3, fdims, info.cvec.data());
171 
172  if (dumpCount == 0) {
173  if (!info.subnames.empty() && !emptyStrings(info.subnames))
174  addMetaData(data_set, "subnames", info.subnames);
175 
176  if (!info.y_subnames.empty() && !emptyStrings(info.y_subnames))
177  addMetaData(data_set, "y_subnames", info.y_subnames);
178 
179  if (!info.subdescs.empty() && !emptyStrings(info.subdescs))
180  addMetaData(data_set, "subdescs", info.subdescs);
181  }
182 }
183 
184 void
186 {
187  if (!enableFormula)
188  return;
189 
190  H5::DataSet data_set = appendVectorInfo(info);
191 
192  if (dumpCount == 0)
193  addMetaData(data_set, "equation", info.str());
194 }
195 
196 void
198 {
199  warn_once("HDF5 stat files don't support sparse histograms.\n");
200 }
201 
202 H5::DataSet
204 {
205  const VResult &vr(info.result());
206  // Request a 2-dimensional stat, the first dimension will be
207  // populated by the Hdf5::appendStat() helper. The remaining
208  // dimension correspond to the stat instance.
209  hsize_t fdims[2] = { 0, vr.size() };
210  H5::DataSet data_set = appendStat(info, 2, fdims, vr.data());
211 
212  if (dumpCount == 0) {
213  if (!info.subnames.empty() && !emptyStrings(info.subnames))
214  addMetaData(data_set, "subnames", info.subnames);
215 
216  if (!info.subdescs.empty() && !emptyStrings(info.subdescs))
217  addMetaData(data_set, "subdescs", info.subdescs);
218  }
219 
220  return data_set;
221 }
222 
223 H5::DataSet
224 Hdf5::appendStat(const Info &info, int rank, hsize_t *dims, const double *data)
225 {
226  H5::Group group = path.top();
227  H5::DataSet data_set;
228  H5::DataSpace fspace;
229 
230  dims[0] = dumpCount + 1;
231 
232  if (dumpCount > 0) {
233  // Get the existing stat if we have already dumped this stat
234  // before.
235  data_set = group.openDataSet(info.name);
236  data_set.extend(dims);
237  fspace = data_set.getSpace();
238  } else {
239  // We don't have the stat already, create it.
240 
241  H5::DSetCreatPropList props;
242 
243  // Setup max dimensions based on the requested file dimensions
244  std::vector<hsize_t> max_dims(rank);
245  std::copy(dims, dims + rank, max_dims.begin());
246  max_dims[0] = H5S_UNLIMITED;
247 
248  // Setup chunking
249  std::vector<hsize_t> chunk_dims(rank);
250  std::copy(dims, dims + rank, chunk_dims.begin());
251  chunk_dims[0] = timeChunk;
252  props.setChunk(rank, chunk_dims.data());
253 
254  // Enable compression
255  props.setDeflate(1);
256 
257  fspace = H5::DataSpace(rank, dims, max_dims.data());
258  try {
259  DPRINTF(Stats, "Creating dataset %s in group %s\n",
260  info.name, group.getObjnameByIdx(group.getId()));
261  data_set = group.createDataSet(info.name,
262  H5::PredType::NATIVE_DOUBLE, fspace, props);
263  } catch (const H5::Exception &e) {
264  std::string err = "Failed creating H5::DataSet " + info.name + "; ";
265  err += e.getDetailMsg() + " in " + e.getFuncName();
266  // Rethrow std exception so that it's passed on to the Python world
267  throw std::runtime_error(err);
268  }
269 
270  if (enableDescriptions && !info.desc.empty()) {
271  addMetaData(data_set, "description", info.desc);
272  }
273  }
274 
275  // The first dimension is time which isn't included in data.
276  dims[0] = 1;
277  H5::DataSpace mspace(rank, dims);
278  std::vector<hsize_t> foffset(rank, 0);
279  foffset[0] = dumpCount;
280 
281  fspace.selectHyperslab(H5S_SELECT_SET, dims, foffset.data());
282  data_set.write(data, H5::PredType::NATIVE_DOUBLE, mspace, fspace);
283 
284  return data_set;
285 }
286 
287 void
288 Hdf5::addMetaData(H5::DataSet &loc, const char *name,
289  const std::vector<const char *> &values)
290 {
291  H5::StrType type(H5::PredType::C_S1, H5T_VARIABLE);
292  hsize_t dims[1] = { values.size(), };
293  H5::DataSpace space(1, dims);
294  H5::Attribute attribute = loc.createAttribute(name, type, space);
295  attribute.write(type, values.data());
296 }
297 
298 void
299 Hdf5::addMetaData(H5::DataSet &loc, const char *name,
300  const std::vector<std::string> &values)
301 {
302  std::vector<const char *> cstrs(values.size());
303  for (int i = 0; i < values.size(); ++i)
304  cstrs[i] = values[i].c_str();
305 
306  addMetaData(loc, name, cstrs);
307 }
308 
309 void
310 Hdf5::addMetaData(H5::DataSet &loc, const char *name,
311  const std::string &value)
312 {
313  H5::StrType type(H5::PredType::C_S1, value.length() + 1);
314  hsize_t dims[1] = { 1, };
315  H5::DataSpace space(1, dims);
316  H5::Attribute attribute = loc.createAttribute(name, type, space);
317  attribute.write(type, value.c_str());
318 }
319 
320 void
321 Hdf5::addMetaData(H5::DataSet &loc, const char *name, double value)
322 {
323  hsize_t dims[1] = { 1, };
324  H5::DataSpace space(1, dims);
325  H5::Attribute attribute = loc.createAttribute(
326  name, H5::PredType::NATIVE_DOUBLE, space);
327  attribute.write(H5::PredType::NATIVE_DOUBLE, &value);
328 }
329 
330 
331 std::unique_ptr<Output>
332 initHDF5(const std::string &filename, unsigned chunking,
333  bool desc, bool formulas)
334 {
335  return std::unique_ptr<Output>(
336  new Hdf5(simout.resolve(filename), chunking, desc, formulas));
337 }
338 
339 }; // namespace statistics
340 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
std::string resolve(const std::string &name) const
Returns relative file names prepended with name of this directory.
Definition: output.cc:204
virtual std::string str() const =0
H5::DataSet appendStat(const Info &info, int rank, hsize_t *dims, const double *data)
Helper function to append an n-dimensional double stat to the file.
Definition: hdf5.cc:224
bool valid() const override
Definition: hdf5.cc:101
unsigned dumpCount
Definition: hdf5.hh:153
const bool enableFormula
Definition: hdf5.hh:149
const bool enableDescriptions
Definition: hdf5.hh:148
const std::string fname
Definition: hdf5.hh:146
void addMetaData(H5::DataSet &loc, const char *name, const std::vector< const char * > &values)
Helper function to add a string vector attribute to a stat.
Definition: hdf5.cc:288
std::stack< H5::Group > path
Definition: hdf5.hh:151
void end() override
Definition: hdf5.cc:93
H5::H5File h5File
Definition: hdf5.hh:154
H5::DataSet appendVectorInfo(const VectorInfo &info)
Helper function to append vector stats and set their metadata.
Definition: hdf5.cc:203
void begin() override
Definition: hdf5.cc:84
void endGroup() override
Definition: hdf5.cc:127
void visit(const ScalarInfo &info) override
Definition: hdf5.cc:134
const hsize_t timeChunk
Definition: hdf5.hh:147
void beginGroup(const char *name) override
Definition: hdf5.cc:108
std::string name
The name of the stat.
Definition: info.hh:84
std::string desc
The description of the stat.
Definition: info.hh:90
virtual Result result() const =0
std::vector< std::string > subdescs
Definition: info.hh:231
std::vector< std::string > y_subnames
Definition: info.hh:232
std::vector< std::string > subnames
Names and descriptions of subfields.
Definition: info.hh:230
VCounter cvec
Local storage for the entry values, used for printing.
Definition: info.hh:238
virtual const VResult & result() const =0
std::vector< std::string > subdescs
Definition: info.hh:189
std::vector< std::string > subnames
Names and descriptions of subfields.
Definition: info.hh:188
#define warn_once(...)
Definition: logging.hh:250
Bitfield< 6 > err
Definition: misc_types.hh:809
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 9 > e
Definition: misc_types.hh:65
Bitfield< 1 > s
Definition: pagetable.hh:64
Bitfield< 51, 12 > base
Definition: pagetable.hh:141
std::unique_ptr< Output > initHDF5(const std::string &filename, unsigned chunking, bool desc, bool formulas)
Definition: hdf5.cc:332
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
bool emptyStrings(const T &labels)
Check if all strings in a container are empty.
Definition: hdf5.cc:52
OutputDirectory simout
Definition: output.cc:62
GEM5_DEPRECATED_NAMESPACE(GuestABI, guest_abi)
const std::string & name()
Definition: trace.cc:49

Generated on Wed Dec 21 2022 10:22:29 for gem5 by doxygen 1.9.1