COMBINATORIAL_BLAS  1.3
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
psort_util.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2009, David Cheng, Viral B. Shah.
3 
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22 
23 #ifndef PSORT_UTIL_H
24 #define PSORT_UTIL_H
25 
26 #include <mpi.h>
27 #include <cassert>
28 #include <stdexcept>
29 #include <limits>
30 #include <cstdlib>
31 #include <iostream>
32 #include <iomanip>
33 #include <fstream>
34 #include <string>
35 #include <functional>
36 #include <iterator>
37 #include <numeric>
38 #include <algorithm>
39 #include <vector>
40 
41 #ifdef PSORTDEBUG
42 #define PSORT_DEBUG(_a) _a
43 #else
44 #define PSORT_DEBUG(_a)
45 #endif
46 
47 #include "psort_seqsort.h"
48 #include "psort_splitters.h"
49 #include "psort_alltoall.h"
50 #include "psort_merge.h"
51 
52 namespace vpsort {
53  using namespace std;
54 
55  static double psort_timing[10];
56 
57  template <typename _RandomAccessIter, typename _Compare>
58  bool is_sorted (_RandomAccessIter first,
59  _RandomAccessIter last,
60  _Compare comp,
61  MPI_Comm comm) {
62 
63  int nproc, rank;
64  MPI_Comm_size (comm, &nproc);
65  MPI_Comm_rank (comm, &rank);
66 
67  int not_sorted = 0;
68 
69  typedef typename iterator_traits<_RandomAccessIter>::pointer _IterType;
70  typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType;
71 
72  for (_IterType iter=first+1; iter<last; ++iter) {
73  if (comp(*(iter), *(iter-1)) == true) {
74  not_sorted = 1;
75  break;
76  }
77  }
78 
79  _ValueType *left_boundary = new _ValueType[nproc];
80  _ValueType *right_boundary = new _ValueType[nproc];
81 
82  _ValueType left = *first;
83  MPI_Allgather (&left, sizeof (_ValueType), MPI_CHAR,
84  left_boundary, sizeof (_ValueType), MPI_CHAR,
85  comm);
86 
87  _ValueType right = *(last-1);
88  MPI_Allgather (&right, sizeof (_ValueType), MPI_CHAR,
89  right_boundary, sizeof (_ValueType), MPI_CHAR,
90  comm);
91 
92  for (int i=0; i<nproc-1; ++i) {
93  if (comp(left_boundary[i+1], right_boundary[i]) == true) {
94  not_sorted = 1;
95  break;
96  }
97  }
98 
99  delete [] left_boundary;
100  delete [] right_boundary;
101 
102  int result[nproc];
103  MPI_Allgather (&not_sorted, 1, MPI_INT,
104  result, 1, MPI_INT, comm);
105 
106  int all_result = accumulate (result, result + nproc, 0);
107  if (all_result == 0)
108  return true;
109  else
110  return false;
111 
112  }
113 
114  template <typename _RandomAccessIter, typename _Compare>
115  bool is_sorted (_RandomAccessIter first,
116  _RandomAccessIter last,
117  MPI_Comm comm) {
118 
119  typedef typename iterator_traits<_RandomAccessIter>::value_type _ValueType;
120  return is_sorted (first, last, std::less<_ValueType>(), comm);
121  }
122 
123 
124  static void progress (int rank, int step, char *s, MPI_Comm comm) {
125  MPI_Barrier (comm);
126  psort_timing[step] = MPI_Wtime ();
127  if (rank == 0) {
128  PSORT_DEBUG (cout << step << ". " << s << endl;);
129  }
130  }
131 
132 
133  template <typename _Distance>
134  void print_perf_data (_Distance *dist, MPI_Comm comm) {
135 
136  STLSort stl_sort;
137  MedianSplit median_split;
138  OOPTreeMerge oop_tree_merge;
139 
140  print_perf_data (dist, stl_sort, median_split, oop_tree_merge, comm);
141  }
142 
143  template <typename _SeqSortType, typename _SplitType, typename _MergeType, typename _Distance>
144  void print_perf_data (_Distance *dist,
145  SeqSort<_SeqSortType> &mysort,
146  Split<_SplitType> &mysplit,
147  Merge<_MergeType> &mymerge,
148  MPI_Comm comm) {
149 
150  int rank, nproc;
151  MPI_Comm_size (comm, &nproc);
152  MPI_Comm_rank (comm, &rank);
153 
154  char **stage = new char*[5];
155  stage[1] = mysort.description();
156  stage[2] = mysplit.description();
157  stage[3] = "alltoall";
158  stage[4] = mymerge.description();
159 
160  if (rank == 0) cout << endl;
161  double rtime[5];
162  for (int i=1; i<=4; ++i) {
163  double time_i = psort_timing[i] - psort_timing[i-1];
164  if (rank == 0) {
165  cout << i << ". "
166  << setw(30) << left << stage[i]
167  << setw(10) << right << ": "
168  << setprecision(6) << time_i << " sec" << endl;
169  rtime[i] = time_i;
170  }
171  }
172 
173  long n_sort = 0L; for (int i=0; i<nproc; ++i) n_sort += dist[i];
174  double total_time = rtime[1] + rtime[2] + rtime[3] + rtime[4];
175  double mkeys_per_sec;
176  double mkeys_per_sec_proc;
177  if (rank == 0) {
178  mkeys_per_sec = ((n_sort * log2(n_sort)) / total_time) / 1e6;
179  mkeys_per_sec_proc = (((n_sort * log2(n_sort)) / total_time) / nproc) / 1e6;
180 
181  cout << setprecision(6) << endl;
182  cout << setw(33) << left << "* MKeys/sec"
183  << setw(10) << right << ": " << mkeys_per_sec << endl;
184  cout << setw(33) << left << "* MKeys/sec/proc"
185  << setw(10) << right << ": " << mkeys_per_sec_proc << endl;
186  cout << endl;
187  }
188 
189  if (rank == 0) {
190  ofstream results;
191  results.open ("./results", ios::app);
192 
193  results << mysort.description() << ", "
194  << mysplit.description() << ", "
195  << mymerge.description() << ", "
196  << nproc << ", "
197  << n_sort << ", "
198  << rtime[1] << ", "
199  << rtime[2] << ", "
200  << rtime[3] << ", "
201  << rtime[4] << ", "
202  << total_time << ", "
203  << mkeys_per_sec << ", "
204  << mkeys_per_sec_proc
205  << endl;
206 
207  results.close ();
208  }
209 
210  }
211 
212 
213  template <typename _SeqSortType, typename _Distance>
214  void print_perf_data_samplesort (_Distance *dist,
215  SeqSort<_SeqSortType> &mysort,
216  MPI_Comm comm) {
217 
218  int rank, nproc;
219  MPI_Comm_size (comm, &nproc);
220  MPI_Comm_rank (comm, &rank);
221 
222  char **stage = new char*[6];
223  stage[1] = "sample splitters";
224  stage[2] = "partition";
225  stage[3] = "alltoall";
226  stage[4] = mysort.description();
227  stage[5] = "adjust boundaries";
228 
229  if (rank == 0) cout << endl;
230  double rtime[6];
231  for (int i=1; i<=5; ++i) {
232  double time_i = psort_timing[i] - psort_timing[i-1];
233  if (rank == 0) {
234  cout << i << ". "
235  << setw(30) << left << stage[i]
236  << setw(10) << right << ": "
237  << setprecision(6) << time_i << " sec" << endl;
238  rtime[i] = time_i;
239  }
240  }
241 
242  long n_sort = 0L; for (int i=0; i<nproc; ++i) n_sort += dist[i];
243  double total_time = rtime[1] + rtime[2] + rtime[3] + rtime[4];
244  double mkeys_per_sec;
245  double mkeys_per_sec_proc;
246  if (rank == 0) {
247  mkeys_per_sec = ((n_sort * log2(n_sort)) / total_time) / 1e6;
248  mkeys_per_sec_proc = (((n_sort * log2(n_sort)) / total_time) / nproc) / 1e6;
249 
250  cout << setprecision(6) << endl;
251  cout << setw(33) << left << "* MKeys/sec"
252  << setw(10) << right << ": " << mkeys_per_sec << endl;
253  cout << setw(33) << left << "* MKeys/sec/proc"
254  << setw(10) << right << ": " << mkeys_per_sec_proc << endl;
255  cout << endl;
256  }
257 
258  if (rank == 0) {
259  ofstream results;
260  results.open ("./results", ios::app);
261 
262  results << "sample sort" << ", "
263  << mysort.description() << ", "
264  << nproc << ", "
265  << n_sort << ", "
266  << rtime[1] << ", "
267  << rtime[2] << ", "
268  << rtime[3] << ", "
269  << rtime[4] << ", "
270  << rtime[5] << ", "
271  << total_time << ", "
272  << mkeys_per_sec << ", "
273  << mkeys_per_sec_proc
274  << endl;
275 
276  results.close ();
277  }
278  }
279 
280 }
281 
282 
283 #endif /* PSORT_UTIL_H */