openPMD-api
MPIBenchmarkReport.hpp
1 /* Copyright 2018-2021 Franz Poeschel
2  *
3  * This file is part of openPMD-api.
4  *
5  * openPMD-api is free software: you can redistribute it and/or modify
6  * it under the terms of of either the GNU General Public License or
7  * the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * openPMD-api is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License and the GNU Lesser General Public License
15  * for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * and the GNU Lesser General Public License along with openPMD-api.
19  * If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #pragma once
23 
24 #include "openPMD/config.hpp"
25 #if openPMD_HAVE_MPI
26 
27 #include "openPMD/Datatype.hpp"
28 #include "openPMD/Series.hpp"
29 
30 #include <map>
31 #include <tuple>
32 #include <vector>
33 #include <mpi.h>
34 #include "string.h"
35 
36 
37 namespace openPMD
38 {
43  template< typename Duration >
45  {
46  MPI_Comm communicator;
47 
48  MPIBenchmarkReport(MPI_Comm);
49 
53  std::map<
54  std::tuple<
55  int, // rank
56  std::string, // compression
57  uint8_t, // compression level
58  std::string, // extension
59  int, // thread size
60  Datatype,
61  typename decltype( Series::iterations )::key_type
62  >,
63  std::pair<
64  Duration,
65  Duration
66  >
68 
69  enum Selector
70  {
71  RANK = 0,
72  COMPRESSION,
73  COMPRESSION_LEVEL,
74  BACKEND,
75  NRANKS,
76  DTYPE,
77  ITERATIONS
78  };
79 
92  void addReport(
93  int rootThread,
94  std::string compression,
95  uint8_t level,
96  std::string extension,
97  int threadSize,
98  Datatype dt,
99  typename decltype( Series::iterations )::key_type iterations,
100  std::pair<
101  Duration,
102  Duration
103  > const & report
104  );
105 
117  std::pair<
118  Duration,
119  Duration
120  > getReport(
121  int rank,
122  std::string compression,
123  uint8_t level,
124  std::string extension,
125  int threadSize,
126  Datatype dt,
127  typename decltype( Series::iterations)::key_type iterations
128  );
129 
130  private:
131  template<
132  typename D,
133  typename Dummy = D
134  >
135  struct MPIDatatype
136  {
137  };
138 
139 
140  template< typename Dummy >
141  struct MPIDatatype<
142  char,
143  Dummy
144  >
145  {
146  MPI_Datatype dt = MPI_CHAR;
147  };
148  template< typename Dummy >
149  struct MPIDatatype<
150  unsigned char,
151  Dummy
152  >
153  {
154  MPI_Datatype dt = MPI_UNSIGNED_CHAR;
155  };
156  template< typename Dummy >
157  struct MPIDatatype<
158  short,
159  Dummy
160  >
161  {
162  MPI_Datatype dt = MPI_SHORT;
163  };
164  template< typename Dummy >
165  struct MPIDatatype<
166  int,
167  Dummy
168  >
169  {
170  MPI_Datatype dt = MPI_INT;
171  };
172  template< typename Dummy >
173  struct MPIDatatype<
174  long,
175  Dummy
176  >
177  {
178  MPI_Datatype dt = MPI_LONG;
179  };
180  template< typename Dummy >
181  struct MPIDatatype<
182  float,
183  Dummy
184  >
185  {
186  MPI_Datatype dt = MPI_FLOAT;
187  };
188  template< typename Dummy >
189  struct MPIDatatype<
190  double,
191  Dummy
192  >
193  {
194  MPI_Datatype dt = MPI_DOUBLE;
195  };
196  template< typename Dummy >
197  struct MPIDatatype<
198  unsigned short,
199  Dummy
200  >
201  {
202  MPI_Datatype dt = MPI_UNSIGNED_SHORT;
203  };
204  template< typename Dummy >
205  struct MPIDatatype<
206  unsigned int,
207  Dummy
208  >
209  {
210  MPI_Datatype dt = MPI_UNSIGNED;
211  };
212  template< typename Dummy >
213  struct MPIDatatype<
214  unsigned long,
215  Dummy
216  >
217  {
218  MPI_Datatype dt = MPI_UNSIGNED_LONG;
219  };
220  template< typename Dummy >
221  struct MPIDatatype<
222  long double,
223  Dummy
224  >
225  {
226  MPI_Datatype dt = MPI_LONG_DOUBLE;
227  };
228  template< typename Dummy >
229  struct MPIDatatype<
230  long long,
231  Dummy
232  >
233  {
234  MPI_Datatype dt = MPI_LONG_LONG_INT;
235  };
236 
237  MPIDatatype< typename Duration::rep > m_mpiDatatype;
238  MPI_Datatype mpiType = m_mpiDatatype.dt;
239  };
240 
241  // implementation
242 
243 
244  template< typename Duration >
246  int rootThread,
247  std::string compression,
248  uint8_t level,
249  std::string extension,
250  int threadSize,
251  Datatype dt,
252  typename decltype( Series::iterations )::key_type iterations,
253  std::pair<
254  Duration,
255  Duration
256  > const & report
257  )
258  {
259  using rep = typename Duration::rep;
260  //auto mpi_dt = MPIDatatype<rep>::dt;
261  int rank;
262  MPI_Comm_rank(
263  communicator,
264  &rank
265  );
266  int size;
267  MPI_Comm_size(
268  communicator,
269  &size
270  );
271  MPI_Comm restricted;
272  MPI_Comm_split(
273  communicator,
274  rank < threadSize ? 0 : MPI_UNDEFINED,
275  rank,
276  &restricted
277  );
278  rep readWrite[2];
279  if( rank < threadSize )
280  {
281  readWrite[0] =
282  report.first
283  .count( );
284  readWrite[1] =
285  report.second
286  .count( );
287  }
288  rep * recv = nullptr;
289  if( rank == rootThread )
290  {
291  recv = new rep[2 * threadSize];
292  }
293 
294  if( restricted != MPI_COMM_NULL )
295  {
296  MPI_Gather(
297  readWrite,
298  2, // should be 2 but doesnt work then..
299  this->mpiType,
300  recv,
301  2,
302  this->mpiType,
303  rootThread,
304  restricted
305  );
306  }
307 
308 
309  if( rank == rootThread )
310  {
311  for( int i = 0; i < threadSize; i++ )
312  {
313  Duration dWrite { recv[2 * i] };
314  Duration dRead { recv[2 * i + 1] };
315  this->durations
316  .emplace(
317  std::make_tuple(
318  i,
319  compression,
320  level,
321  extension,
322  threadSize,
323  dt,
324  iterations
325  ),
326  std::make_pair(
327  dWrite,
328  dRead
329  )
330  );
331  }
332  delete[] recv;
333  }
334  if( restricted != MPI_COMM_NULL )
335  {
336  MPI_Comm_free( &restricted );
337  }
338  }
339 
340  template< typename Duration >
342  communicator {comm}
343  {}
344 
345  template< typename Duration >
346  std::pair<
347  Duration,
348  Duration
350  int rank,
351  std::string compression,
352  uint8_t level,
353  std::string extension,
354  int threadSize,
355  Datatype dt,
356  typename decltype( Series::iterations )::key_type iterations
357  )
358  {
359  auto
360  it =
361  this->durations
362  .find(
363  std::make_tuple(
364  rank,
365  compression,
366  level,
367  extension,
368  threadSize,
369  dt,
370  iterations
371  )
372  );
373  if( it ==
374  this->durations
375  .end( ) )
376  {
377  throw std::runtime_error( "Requested report not found. (Reports are available on the root thread only)" );
378  }
379  else
380  {
381  return it->second;
382  }
383  }
384 
385 }
386 
387 #endif
openPMD::Datatype
Datatype
Concrete datatype of an object available at runtime.
Definition: Datatype.hpp:45
openPMD::MPIBenchmarkReport::addReport
void addReport(int rootThread, std::string compression, uint8_t level, std::string extension, int threadSize, Datatype dt, typename decltype(Series::iterations)::key_type iterations, std::pair< Duration, Duration > const &report)
Add results for a certain compression strategy and level.
Definition: MPIBenchmarkReport.hpp:245
openPMD::MPIBenchmarkReport::durations
std::map< std::tuple< int, std::string, uint8_t, std::string, int, Datatype, typename decltype(Series::iterations)::key_type >, std::pair< Duration, Duration > > durations
Time needed for writing and reading per compression strategy and level.
Definition: MPIBenchmarkReport.hpp:67
openPMD
Public definitions of openPMD-api.
Definition: Date.cpp:29
openPMD::MPIBenchmarkReport::getReport
std::pair< Duration, Duration > getReport(int rank, std::string compression, uint8_t level, std::string extension, int threadSize, Datatype dt, typename decltype(Series::iterations)::key_type iterations)
Retrieve the time measured for a certain compression strategy.
Definition: MPIBenchmarkReport.hpp:349
openPMD::MPIBenchmarkReport
The report for a single benchmark produced by <openPMD/benchmark/mpi/MPIBenchmark>.
Definition: MPIBenchmarkReport.hpp:44