libSplash
ParallelDomainCollector.cpp
1 
23 #include "splash/basetypes/basetypes.hpp"
24 
25 #include "splash/ParallelDomainCollector.hpp"
26 #include "splash/AttributeInfo.hpp"
27 #include "splash/core/DCParallelDataSet.hpp"
28 #include "splash/core/logging.hpp"
29 
30 namespace splash
31 {
32 
33  std::string ParallelDomainCollector::getExceptionString(std::string func,
34  std::string msg, const char *info)
35  {
36  std::stringstream full_msg;
37  full_msg << "Exception for ParallelDomainCollector::" << func <<
38  ": " << msg;
39 
40  if (info != NULL)
41  full_msg << " (" << info << ")";
42 
43  return full_msg.str();
44  }
45 
46  void ParallelDomainCollector::writeDomainAttributes(
47  int32_t id,
48  const char *name,
49  DomDataClass dataClass,
50  const Domain localDomain,
51  const Domain globalDomain)
52  {
53  ColTypeInt32 int_t;
54  ColTypeDim dim_t;
55  writeAttribute(id, int_t, name, DOMCOL_ATTR_CLASS, &dataClass);
56  writeAttribute(id, dim_t, name, DOMCOL_ATTR_SIZE, localDomain.getSize().getPointer());
57  writeAttribute(id, dim_t, name, DOMCOL_ATTR_OFFSET, localDomain.getOffset().getPointer());
58  writeAttribute(id, dim_t, name, DOMCOL_ATTR_GLOBAL_SIZE, globalDomain.getSize().getPointer());
59  writeAttribute(id, dim_t, name, DOMCOL_ATTR_GLOBAL_OFFSET, globalDomain.getOffset().getPointer());
60  }
61 
63  const Dimensions topology, uint32_t maxFileHandles) :
64  ParallelDataCollector(comm, info, topology, maxFileHandles)
65  {
66  }
67 
69  {
70  }
71 
73  const char* name)
74  throw (DCException)
75  {
76  if (this->fileStatus == FST_CLOSED)
77  throw DCException(getExceptionString("getGlobalDomain",
78  "this access is not permitted", NULL));
79 
80  Domain domain;
81 
82  readAttributeInfo(id, name, DOMCOL_ATTR_GLOBAL_SIZE).read(domain.getSize().getPointer(), domain.getSize().getSize());
83  readAttributeInfo(id, name, DOMCOL_ATTR_GLOBAL_OFFSET).read(domain.getOffset().getPointer(), domain.getOffset().getSize());
84 
85  return domain;
86  }
87 
89  const char* name)
90  throw (DCException)
91  {
92  if (this->fileStatus == FST_CLOSED)
93  throw DCException(getExceptionString("getLocalDomain",
94  "this access is not permitted", NULL));
95 
96  Domain domain;
97 
98  readAttributeInfo(id, name, DOMCOL_ATTR_SIZE).read(domain.getSize().getPointer(), domain.getSize().getSize());
99  readAttributeInfo(id, name, DOMCOL_ATTR_OFFSET).read(domain.getOffset().getPointer(), domain.getOffset().getSize());
100 
101  return domain;
102  }
103 
104  bool ParallelDomainCollector::readDomainDataForRank(
105  DataContainer *dataContainer,
106  DomDataClass *dataClass,
107  int32_t id,
108  const char* name,
109  const Domain requestDomain,
110  bool lazyLoad)
111  throw (DCException)
112  {
113  Domain local_client_domain = getLocalDomain(id, name);
114  Domain global_client_domain = getGlobalDomain(id, name);
115 
116  Domain client_domain(
117  local_client_domain.getOffset() + global_client_domain.getOffset(),
118  local_client_domain.getSize());
119 
120  Dimensions data_elements;
121  read(id, name, data_elements, NULL);
122 
123  DomDataClass tmp_data_class = UndefinedType;
124  readAttributeInfo(id, name, DOMCOL_ATTR_CLASS).read(&tmp_data_class, sizeof(tmp_data_class));
125 
126  if (tmp_data_class == GridType && data_elements != client_domain.getSize())
127  throw DCException(getExceptionString("readDomainDataForRank",
128  "Number of data elements must match domain size for Grid data.", NULL));
129 
130  if (*dataClass == UndefinedType)
131  {
132  *dataClass = tmp_data_class;
133  } else
134  if (tmp_data_class != *dataClass)
135  {
136  throw DCException(getExceptionString("readDomainDataForRank",
137  "Data classes in files are inconsistent!", NULL));
138  }
139 
140  log_msg(3, "clientdom. = %s", client_domain.toString().c_str());
141  log_msg(3, "requestdom. = %s", requestDomain.toString().c_str());
142 
143  // test on intersection and add new DomainData to the container if necessary
144  if ((requestDomain.getSize().getScalarSize() > 0) && !Domain::testIntersection(requestDomain, client_domain))
145  return false;
146 
147  // Poly data has no internal grid structure,
148  // so the whole chunk has to be read and is added to the DataContainer.
149  if (*dataClass == PolyType)
150  {
151  log_msg(3, "dataclass = Poly");
152  if (data_elements.getScalarSize() > 0)
153  {
154  std::stringstream group_id_name;
155  group_id_name << SDC_GROUP_DATA << "/" << id;
156  std::string group_id_string = group_id_name.str();
157 
158  hid_t group_id = H5Gopen(handles.get(id), group_id_string.c_str(), H5P_DEFAULT);
159  if (group_id < 0)
160  throw DCException(getExceptionString("readDomainDataForRank",
161  "group not found", group_id_string.c_str()));
162 
163  size_t datatype_size = 0;
164  DCDataType dc_datatype = DCDT_UNKNOWN;
165 
166  try
167  {
168  DCParallelDataSet tmp_dataset(name);
169  tmp_dataset.open(group_id);
170 
171  datatype_size = tmp_dataset.getDataTypeSize();
172  dc_datatype = tmp_dataset.getDCDataType();
173 
174  tmp_dataset.close();
175  } catch (const DCException& e)
176  {
177  H5Gclose(group_id);
178  throw e;
179  }
180 
181  H5Gclose(group_id);
182 
183  DomainData *client_data = new DomainData(client_domain,
184  data_elements, datatype_size, dc_datatype);
185 
186  if (lazyLoad)
187  {
188  client_data->setLoadingReference(*dataClass,
189  handles.get(id), id, name,
190  data_elements,
191  Dimensions(0, 0, 0),
192  Dimensions(0, 0, 0),
193  Dimensions(0, 0, 0));
194  } else
195  {
196  Dimensions elements_read;
197  uint32_t src_rank = 0;
198  readCompleteDataSet(handles.get(id), id, name,
199  data_elements,
200  Dimensions(0, 0, 0),
201  Dimensions(0, 0, 0),
202  elements_read,
203  src_rank,
204  client_data->getData());
205 
206  if (!(elements_read == data_elements))
207  throw DCException(getExceptionString("readDomainDataForRank",
208  "Sizes are not equal but should be (1).", NULL));
209  }
210 
211  dataContainer->add(client_data);
212  } else
213  {
214  log_msg(3, "skipping entry with 0 elements");
215  }
216  } else
217  // For Grid data, only the subchunk is read into its target position
218  // in the destination buffer.
219  if (*dataClass == GridType)
220  {
221  log_msg(3, "dataclass = Grid");
222 
223  // When the first intersection is found, the whole destination
224  // buffer is allocated and added to the container.
225  if (dataContainer->getNumSubdomains() == 0)
226  {
227  std::stringstream group_id_name;
228  group_id_name << SDC_GROUP_DATA << "/" << id;
229  std::string group_id_string = group_id_name.str();
230 
231  hid_t group_id = H5Gopen(handles.get(id), group_id_string.c_str(), H5P_DEFAULT);
232  if (group_id < 0)
233  throw DCException(getExceptionString("readDomainDataForRank",
234  "group not found", group_id_string.c_str()));
235 
236  size_t datatype_size = 0;
237  DCDataType dc_datatype = DCDT_UNKNOWN;
238 
239  try
240  {
241  DCParallelDataSet tmp_dataset(name);
242  tmp_dataset.open(group_id);
243 
244  datatype_size = tmp_dataset.getDataTypeSize();
245  dc_datatype = tmp_dataset.getDCDataType();
246 
247  tmp_dataset.close();
248  } catch (const DCException& e)
249  {
250  H5Gclose(group_id);
251  throw e;
252  }
253 
254  H5Gclose(group_id);
255 
256  DomainData *target_data = new DomainData(
257  requestDomain, requestDomain.getSize(),
258  datatype_size, dc_datatype);
259 
260  dataContainer->add(target_data);
261  }
262 
263  // Compute the offsets and sizes for reading and
264  // writing this intersection.
265  Dimensions dst_offset(0, 0, 0);
266  Dimensions src_size(1, 1, 1);
267  Dimensions src_offset(0, 0, 0);
268 
269  Dimensions client_start = client_domain.getOffset();
270  Dimensions client_size = client_domain.getSize();
271 
272  size_t ndims = getNDims(handles.get(id), id, name);
273 
274  const Dimensions request_offset = requestDomain.getOffset();
275  const Dimensions request_size = requestDomain.getSize();
276  for (uint32_t i = 0; i < ndims; ++i)
277  {
278  dst_offset[i] = std::max((int64_t) client_domain.getOffset()[i] -
279  (int64_t) request_offset[i], (int64_t) 0);
280 
281  if (request_offset[i] <= client_start[i])
282  {
283  src_offset[i] = 0;
284 
285  if (request_offset[i] + request_size[i] >= client_start[i] + client_size[i])
286  src_size[i] = client_size[i];
287  else
288  src_size[i] = request_offset[i] + request_size[i] - client_start[i];
289  } else
290  {
291  src_offset[i] = request_offset[i] - client_start[i];
292 
293  if (request_offset[i] + request_size[i] >= client_start[i] + client_size[i])
294  src_size[i] = client_size[i] - src_offset[i];
295  else
296  src_size[i] = request_offset[i] + request_size[i] -
297  (client_start[i] + src_offset[i]);
298  }
299  }
300 
301  log_msg(3,
302  "client_domain.getSize() = %s\n"
303  "data_elements = %s\n"
304  "dst_offset = %s\n"
305  "src_size = %s\n"
306  "src_offset = %s",
307  client_domain.getSize().toString().c_str(),
308  data_elements.toString().c_str(),
309  dst_offset.toString().c_str(),
310  src_size.toString().c_str(),
311  src_offset.toString().c_str());
312 
313  assert(src_size[0] <= requestDomain.getSize()[0]);
314  assert(src_size[1] <= requestDomain.getSize()[1]);
315  assert(src_size[2] <= requestDomain.getSize()[2]);
316 
317  // read intersecting partition into destination buffer
318  Dimensions elements_read(0, 0, 0);
319  uint32_t src_rank = 0;
320  {
321  readDataSet(handles.get(id), id, name,
322  dataContainer->getIndex(0)->getSize(),
323  dst_offset,
324  src_size,
325  src_offset,
326  elements_read,
327  src_rank,
328  dataContainer->getIndex(0)->getData());
329  }
330 
331  log_msg(3, "elements_read = %s", elements_read.toString().c_str());
332  bool read_success = true;
333 
334  if ((request_size.getScalarSize() == 0) && (elements_read.getScalarSize() != 0))
335  read_success = false;
336 
337  if ((request_size.getScalarSize() != 0) && (elements_read != src_size))
338  read_success = false;
339 
340  if (!read_success)
341  {
342  throw DCException(getExceptionString("readDomainDataForRank",
343  "Sizes are not equal but should be (2).", NULL));
344  }
345  }
346 
347  return true;
348  }
349 
351  const char* name,
352  const Domain requestDomain,
353  DomDataClass* dataClass,
354  bool lazyLoad)
355  throw (DCException)
356  {
357  if (fileStatus == FST_CLOSED)
358  throw DCException(getExceptionString("readDomain",
359  "this access is not permitted", NULL));
360 
361  DataContainer * data_container = new DataContainer();
362 
363  log_msg(3, "requestDomain = %s", requestDomain.toString().c_str());
364 
365  DomDataClass data_class = UndefinedType;
366 
367  readDomainDataForRank(data_container,
368  &data_class,
369  id,
370  name,
371  requestDomain,
372  lazyLoad);
373 
374  if (dataClass != NULL)
375  *dataClass = data_class;
376 
377  return data_container;
378  }
379 
381  throw (DCException)
382  {
383  if (domainData == NULL)
384  {
385  throw DCException(getExceptionString("readDomainLazy",
386  "Invalid parameter, DomainData must not be NULL", NULL));
387  }
388 
389  DomainH5Ref *loadingRef = domainData->getLoadingReference();
390  if (loadingRef == NULL)
391  {
392  throw DCException(getExceptionString("readDomainLazy",
393  "This DomainData does not allow lazy loading", NULL));
394  }
395 
396  if (loadingRef->dataClass == UndefinedType)
397  {
398  throw DCException(getExceptionString("readDomainLazy",
399  "DomainData has invalid data class", NULL));
400  }
401 
402  if (loadingRef->dataClass == PolyType)
403  {
404  Dimensions elements_read;
405  uint32_t src_rank = 0;
406  readDataSet(loadingRef->handle,
407  loadingRef->id,
408  loadingRef->name.c_str(),
409  loadingRef->dstBuffer,
410  loadingRef->dstOffset,
411  loadingRef->srcSize,
412  loadingRef->srcOffset,
413  elements_read,
414  src_rank,
415  domainData->getData());
416 
417  if (!(elements_read == loadingRef->dstBuffer))
418  throw DCException(getExceptionString("readDomainLazy",
419  "Sizes are not equal but should be (1).", NULL));
420 
421  } else
422  {
423 
424  throw DCException(getExceptionString("readDomainLazy",
425  "data class not supported", NULL));
426  }
427  }
428 
430  const CollectionType& type,
431  uint32_t ndims,
432  const Selection select,
433  const char* name,
434  const Domain /*localDomain*/,
435  const Domain globalDomain,
436  DomDataClass dataClass,
437  const void* buf)
438  throw (DCException)
439  {
440  Dimensions globalSize, globalOffset;
441  gatherMPIWrites(ndims, select.count, globalSize, globalOffset);
442 
443  writeDomain(id, globalSize, globalOffset,
444  type, ndims, select,
445  name, globalDomain, dataClass, buf);
446  }
447 
449  const Dimensions globalSize,
450  const Dimensions globalOffset,
451  const CollectionType& type,
452  uint32_t ndims,
453  const Selection select,
454  const char* name,
455  const Domain globalDomain,
456  DomDataClass dataClass,
457  const void* buf)
458  throw (DCException)
459  {
460  write(id, globalSize, globalOffset, type, ndims, select, name, buf);
461  Domain localDomain(Dimensions(0, 0, 0), globalDomain.getSize());
462 
463  writeDomainAttributes(id, name, dataClass, localDomain, globalDomain);
464  }
465 
467  const Dimensions globalSize,
468  uint32_t ndims,
469  const CollectionType& type,
470  const char* name,
471  const Domain globalDomain,
472  DomDataClass dataClass)
473  throw (DCException)
474  {
475  reserve(id, globalSize, ndims, type, name);
476  Domain localDomain(Dimensions(0, 0, 0), globalDomain.getSize());
477 
478  writeDomainAttributes(id, name, dataClass, localDomain, globalDomain);
479  }
480 
482  const Dimensions size,
483  Dimensions *globalSize,
484  Dimensions *globalOffset,
485  uint32_t ndims,
486  const CollectionType& type,
487  const char* name,
488  const Domain globalDomain,
489  DomDataClass dataClass)
490  throw (DCException)
491  {
492  reserve(id, size, globalSize, globalOffset, ndims, type, name);
493  Domain localDomain(Dimensions(0, 0, 0), globalDomain.getSize());
494 
495  writeDomainAttributes(id, name, dataClass, localDomain, globalDomain);
496  }
497 
498  void ParallelDomainCollector::appendDomain(int32_t id,
499  const CollectionType& type,
500  size_t count,
501  const char *name,
502  const Domain localDomain,
503  const Domain globalDomain,
504  const void *buf)
505  throw (DCException)
506  {
507  appendDomain(id, type, count, 0, 1, name, localDomain, globalDomain, buf);
508  }
509 
510  void ParallelDomainCollector::appendDomain(int32_t /*id*/,
511  const CollectionType& /*type*/,
512  size_t /*count*/,
513  size_t /*offset*/,
514  size_t /*striding*/,
515  const char* /*name*/,
516  const Domain /*localDomain*/,
517  const Domain /*globalDomain*/,
518  const void* /*buf*/)
519  throw (DCException)
520  {
521  throw DCException("This feature is not supported in ParallelDomainCollector. "
522  "Use ParallelDataCollector::append instead.");
523  }
524 
525 }
hsize_t * getPointer()
Definition: Dimensions.hpp:192
Domain getLocalDomain(int32_t id, const char *name)
std::string toString() const
Definition: Domain.hpp:142
Domain getGlobalDomain(int32_t id, const char *name)
std::string toString() const
Definition: Dimensions.hpp:181
void reserveDomain(int32_t id, const Dimensions globalSize, uint32_t ndims, const CollectionType &type, const char *name, const Domain domain, DomDataClass dataClass)
Dimensions & getOffset()
Definition: Domain.hpp:101
void setLoadingReference(int dataClass, hid_t handle, int32_t id, const char *name, const Dimensions dstBuffer, const Dimensions dstOffset, const Dimensions srcSize, const Dimensions srcOffset)
Definition: DomainData.hpp:153
size_t getScalarSize() const
Definition: Dimensions.hpp:219
Dimensions & getSize()
Definition: Domain.hpp:81
AttributeInfo readAttributeInfo(int32_t id, const char *dataName, const char *attrName, Dimensions *mpiPosition=NULL)
DomainData * getIndex(size_t index)
ParallelDomainCollector(MPI_Comm comm, MPI_Info info, const Dimensions topology, uint32_t maxFileHandles)
void write(int32_t id, const CollectionType &type, uint32_t rank, const Selection select, const char *name, const void *buf)
void add(DomainData *entry)
void read(int32_t id, const char *name, Dimensions &sizeRead, void *buf)
void readDomainLazy(DomainData *domainData)
static bool testIntersection(const Domain &d1, const Domain &d2)
Definition: Domain.hpp:156
EXTERN void log_msg(int level, const char *fmt,...)
Definition: logging.cpp:56
DataContainer * readDomain(int32_t id, const char *name, const Domain requestDomain, DomDataClass *dataClass, bool lazyLoad=false)
void reserve(int32_t id, const Dimensions globalSize, uint32_t rank, const CollectionType &type, const char *name)
static size_t getSize()
Definition: Dimensions.hpp:210
void writeAttribute(int32_t id, const CollectionType &type, const char *dataName, const char *attrName, const void *buf)
void read(const CollectionType &colType, void *buf)
void writeDomain(int32_t id, const CollectionType &type, uint32_t ndims, const Selection select, const char *name, const Domain localDomain, const Domain globalDomain, DomDataClass dataClass, const void *buf)