DASH  0.3.0
main.cpp
1 
6 #include <libdash.h>
7 #include <iostream>
8 #include <iomanip>
9 #include <string>
10 
11 using std::cout;
12 using std::endl;
13 using std::setw;
14 using std::setprecision;
15 
16 typedef dash::util::Timer<
17  dash::util::TimeMeasure::Clock
18  > Timer;
19 
22 
23 typedef struct benchmark_params_t {
24  int reps;
25  int rounds;
27 
28 typedef struct measurement_t {
29  std::string testcase;
30  double time_total_s;
31 } measurement;
32 
33 void print_measurement_header();
34 void print_measurement_record(
35  const bench_cfg_params & cfg_params,
37  const benchmark_params & params);
38 
39 benchmark_params parse_args(int argc, char * argv[]);
40 
41 void print_params(
42  const dash::util::BenchmarkParams & bench_cfg,
43  const benchmark_params & params);
44 
45 
46 measurement evaluate(
47  int reps,
48  std::string testcase,
49  benchmark_params params);
50 
51 typedef struct {
52  float min, max;
53 } minmax_t;
54 
55 static void minmax_fn(const void *invec, void *inoutvec, size_t, void *)
56 {
57  const minmax_t* minmax_in = static_cast<const minmax_t*>(invec);
58  minmax_t* minmax_out = static_cast<minmax_t*>(inoutvec);
59 
60  if (minmax_in->min < minmax_out->min) {
61  minmax_out->min = minmax_in->min;
62  }
63 
64  if (minmax_in->max > minmax_out->max) {
65  minmax_out->max = minmax_in->max;
66  }
67 }
68 
69 template<typename T>
70 static void minmax_lambda(const void *invec, void *inoutvec, size_t, void *userdata)
71 {
72  const minmax_t* minmax_in = static_cast<const minmax_t*>(invec);
73  minmax_t* minmax_out = static_cast<minmax_t*>(inoutvec);
74  T& fn = *static_cast<T*>(userdata);
75  *minmax_out = fn(*minmax_in, *minmax_out);
76 }
77 
78 int main(int argc, char** argv)
79 {
80  dash::init(&argc, &argv);
81 
82  Timer::Calibrate(0);
83 
84  measurement res;
85 
86  dash::util::BenchmarkParams bench_params("bench.13.allreduce");
87  bench_params.print_header();
88  bench_params.print_pinning();
89 
90  benchmark_params params = parse_args(argc, argv);
91  auto bench_cfg = bench_params.config();
92 
93  print_params(bench_params, params);
94  print_measurement_header();
95 
96  int multiplier = 1;
97  int round = 0;
98  std::array<std::string, 5> testcases {{
99  "dart_allreduce.minmax",
100  "dart_allreduce.min",
101  "dart_allreduce.shared",
102  "dart_allreduce.custom",
103  "dart_allreduce.lambda"
104  }};
105 
106  while(round < params.rounds) {
107  for(auto testcase : testcases){
108  res = evaluate(params.reps, testcase, params);
109  print_measurement_record(bench_cfg, res, params);
110  }
111  round++;
112  }
113 
114  if (dash::myid() == 0) {
115  cout << "Benchmark finished" << endl;
116  }
117 
118  dash::finalize();
119  return 0;
120 }
121 
122 measurement evaluate(int reps, std::string testcase, benchmark_params params)
123 {
124  measurement mes;
125 
126  auto r = dash::myid();
127 
128 
129  float lmin = r;
130  float lmax = 1000000 - r;
131 
132  auto ts_tot_start = Timer::Now();
133 
134  for (int i = 0; i < reps; i++) {
135  if (testcase == "dart_allreduce.minmax") {
136  std::array<float, 2> min_max_in{lmin, lmax};
137  std::array<float, 2> min_max_out{};
139  &min_max_in, // send buffer
140  &min_max_out, // receive buffer
141  2, // buffer size
143  DART_OP_MINMAX, // operation
144  dash::Team::All().dart_id() // team
145  );
146  }
147  else if (testcase == "dart_allreduce.min") {
148  std::array<float, 2> min_max_in{lmin, lmax};
149  std::array<float, 2> min_max_out{};
151  &min_max_in, // send buffer
152  &min_max_out, // receive buffer
153  1, // buffer size
155  DART_OP_MIN, // operation
156  dash::Team::All().dart_id() // team
157  );
159  &min_max_in[1], // send buffer
160  &min_max_out[1], // receive buffer
161  1, // buffer size
163  DART_OP_MAX, // operation
164  dash::Team::All().dart_id() // team
165  );
166  }
167  else if (testcase == "dart_allreduce.shared") {
168  using value_t = float;
169  using shared_t = dash::Shared<dash::Atomic<float>>;
170 
171  auto& team = dash::Team::All();
172  shared_t g_min(std::numeric_limits<value_t>::max(), dash::team_unit_t{0}, team);
173  shared_t g_max(std::numeric_limits<value_t>::min(), dash::team_unit_t{0}, team);
174 
175  auto const start_min = static_cast<value_t>(g_min.get());
176  auto const start_max = static_cast<value_t>(g_max.get());
177 
178  team.barrier();
179 
180  g_min.get().fetch_op(dash::min<value_t>(), 0);
181  g_max.get().fetch_op(dash::max<value_t>(), std::numeric_limits<value_t>::max());
182 
183  team.barrier();
184  } else if (testcase == "dart_allreduce.custom") {
185  minmax_t min_max_in{lmin, lmax};
186  minmax_t min_max_out{};
187  dart_datatype_t new_type;
188  dart_operation_t new_op;
189  dart_type_create_custom(sizeof(minmax_t), &new_type);
191  &minmax_fn, NULL, true, new_type, true, &new_op);
193  &min_max_in, // send buffer
194  &min_max_out, // receive buffer
195  1, // buffer size
196  new_type, // data type
197  new_op, // operation
198  dash::Team::All().dart_id() // team
199  );
200  dart_type_destroy(&new_type);
201  dart_op_destroy(&new_op);
202  } else if (testcase == "dart_allreduce.lambda") {
203  minmax_t min_max_in{lmin, lmax};
204  minmax_t min_max_out{};
205  dart_datatype_t new_type;
206  dart_operation_t new_op;
207  dart_type_create_custom(sizeof(minmax_t), &new_type);
208  auto fn = [](const minmax_t &a, const minmax_t &b){
209  minmax_t res = b;
210  if (a.min < res.min) {
211  res.min = a.min;
212  }
213  if (a.max > res.max) {
214  res.max = a.max;
215  }
216  return res;
217  };
219  &minmax_lambda<decltype(fn)>, &fn, true, new_type, true, &new_op);
221  &min_max_in, // send buffer
222  &min_max_out, // receive buffer
223  1, // buffer size
224  new_type, // data type
225  new_op, // operation
226  dash::Team::All().dart_id() // team
227  );
228  dart_type_destroy(&new_type);
229  dart_op_destroy(&new_op);
230  }
231  }
232 
233  mes.time_total_s = Timer::ElapsedSince(ts_tot_start) / (double)reps / 1E6;
234  mes.testcase = testcase;
235  return mes;
236 }
237 
238 void print_measurement_header()
239 {
240  if (dash::myid() == 0) {
241  cout << std::right
242  << std::setw( 5) << "units" << ","
243  << std::setw( 9) << "mpi.impl" << ","
244  << std::setw(30) << "impl" << ","
245  << std::setw( 8) << "total.s"
246  << endl;
247  }
248 }
249 
250 void print_measurement_record(
251  const bench_cfg_params & cfg_params,
253  const benchmark_params & params)
254 {
255  if (dash::myid() == 0) {
256  std::string mpi_impl = dash__toxstr(DASH_MPI_IMPL_ID);
257  auto mes = measurement;
258  cout << std::right
259  << std::setw(5) << dash::size() << ","
260  << std::setw(9) << mpi_impl << ","
261  << std::fixed << setprecision(2) << setw(30) << mes.testcase << ","
262  << std::fixed << setprecision(8) << setw(12) << mes.time_total_s
263  << endl;
264  }
265 }
266 
267 benchmark_params parse_args(int argc, char * argv[])
268 {
269  benchmark_params params;
270  params.reps = 100;
271  params.rounds = 10;
272 
273  for (auto i = 1; i < argc; i += 2) {
274  std::string flag = argv[i];
275  if (flag == "-r") {
276  params.reps = atoi(argv[i+1]);
277  }
278  if (flag == "-n") {
279  params.rounds = atoi(argv[i+1]);
280  }
281  }
282  return params;
283 }
284 
285 void print_params(
286  const dash::util::BenchmarkParams & bench_cfg,
287  const benchmark_params & params)
288 {
289  if (dash::myid() != 0) {
290  return;
291  }
292 
293  bench_cfg.print_section_start("Runtime arguments");
294  bench_cfg.print_param("-r", "repetitions per round", params.reps);
295  bench_cfg.print_param("-n", "rounds", params.rounds);
296  bench_cfg.print_section_end();
297 }
global_unit_t myid()
Shortcut to query the global unit ID of the calling unit.
size_t size()
Return the number of units in the global team.
dart_ret_t dart_op_destroy(dart_operation_t *op)
Destroy a operation object created through dart_op_create and set op to DART_OP_UNDEFINED.
intptr_t dart_datatype_t
Raw data types supported by the DART interface.
Definition: dart_types.h:121
Maximum.
Definition: dart_types.h:75
void finalize()
Finalize the DASH library and the underlying runtime system.
dart_ret_t dart_type_destroy(dart_datatype_t *dart_type)
Destroy a data type that was previously created using dart_type_create_strided or dart_type_create_in...
Reduce operands to their maximum value.
Definition: Operation.h:144
dart_ret_t dart_allreduce(const void *sendbuf, void *recvbuf, size_t nelem, dart_datatype_t dtype, dart_operation_t op, dart_team_t team)
DART Equivalent to MPI allreduce.
Minimum and Maximum.
Definition: dart_types.h:77
dart_ret_t dart_type_create_custom(size_t num_bytes, dart_datatype_t *newtype)
Create a custom data type of size num_bytes bytes.
Type trait for mapping to DART data types.
Definition: Types.h:96
struct dash::unit_id< dash::local_unit, dart_team_unit_t > team_unit_t
Unit ID to use for team-local IDs.
Definition: Types.h:319
Shared access to a value in global memory across a team.
Definition: Shared.h:23
static Team & All()
The invariant Team instance containing all available units.
Definition: Team.h:213
void init(int *argc, char ***argv)
Initialize the DASH library and the underlying runtime system.
dart_ret_t dart_op_create(dart_operator_t op, void *userdata, bool commute, dart_datatype_t dtype, bool dtype_is_tmp, dart_operation_t *new_op)
Create a new operation new_op that can be used in collective reduction operations, i.e., dart_reduce, dart_allreduce.
Minimum.
Definition: dart_types.h:73