@@ -73,15 +73,13 @@ struct statistics {
73
73
};
74
74
75
75
template <typename T, typename Sorter>
76
- statistics run (T* data, const T* const copy, T* out, size_t size, Sorter sorter,
77
- size_t iterations, const std::string &algoname,
78
- bool reset_out = true ) {
79
- progress_bar bar (iterations + 1 , algoname);
76
+ void run (T* data, const T* const copy, T* out, size_t size, Sorter sorter,
77
+ size_t iterations, statistics& stats, progress_bar &bar,
78
+ bool reset_out = true ) {
80
79
// warmup
81
80
sorter (data, out, size);
82
81
++bar;
83
82
84
- statistics stats;
85
83
Timer timer;
86
84
for (size_t it = 0 ; it < iterations; ++it) {
87
85
// reset data and timer
@@ -95,61 +93,83 @@ statistics run(T* data, const T* const copy, T* out, size_t size, Sorter sorter,
95
93
stats.push (timer.get ());
96
94
++bar;
97
95
}
98
- bar.undraw ();
99
- return stats;
100
96
}
101
97
102
98
template <typename T, typename Generator>
103
- size_t benchmark (size_t size, size_t iterations, Generator generator,
104
- const std::string &name, std::ofstream *stat_stream) {
99
+ size_t benchmark (size_t size, Generator generator, const std::string &name,
100
+ size_t outer_its, size_t inner_its,
101
+ std::ofstream *stat_stream) {
105
102
T *data = new T[size],
106
103
*out = new T[size],
107
104
*copy = new T[size];
108
105
106
+ // Number of iterations
107
+ if (outer_its == static_cast <size_t >(-1 )) {
108
+ if (size < (1 <<16 )) outer_its = 100 ;
109
+ else if (size < (1 <<18 )) outer_its = 50 ;
110
+ else if (size < (1 <<20 )) outer_its = 25 ;
111
+ else if (size < (1 <<24 )) outer_its = 10 ;
112
+ else outer_its = 5 ;
113
+ }
114
+ if (inner_its == static_cast <size_t >(-1 )) {
115
+ inner_its = 10 ;
116
+ }
117
+
118
+ // the label maker
119
+ auto bar_label = [&](size_t it) {
120
+ return name + " (" + std::to_string (it + 1 ) + " /" +
121
+ std::to_string (outer_its) + " ): " ;
122
+ };
123
+
124
+ progress_bar bar (2 * outer_its * (inner_its + 1 ), bar_label (0 ));
109
125
Timer timer;
110
- // Generate random numbers as input
111
- size = generator (data, size);
112
126
113
- // create a copy to be able to sort it multiple times
114
- std::copy (data, data+size, copy);
115
- double t_generate = timer.get_and_reset ();
127
+ double t_generate (0.0 ), t_verify (0.0 );
128
+ bool incorrect = false ;
129
+ statistics t_ssssort, t_stdsort;
130
+ for (size_t it = 0 ; it < outer_its; ++it) {
131
+ bar.set_extra (bar_label (it));
132
+ // Generate random numbers as input
133
+ timer.reset ();
134
+ size = generator (data, size);
116
135
117
- // Number of iterations
118
- if (iterations == static_cast <size_t >(-1 )) {
119
- if (size < (1 <<16 )) iterations = 1000 ;
120
- else if (size < (1 <<18 )) iterations = 500 ;
121
- else if (size < (1 <<20 )) iterations = 250 ;
122
- else if (size < (1 <<24 )) iterations = 100 ;
123
- else iterations = 50 ;
124
- }
136
+ // create a copy to be able to sort it multiple times
137
+ std::copy (data, data+size, copy);
138
+ t_generate += timer.get_and_reset ();
125
139
126
- // 1. Super Scalar Sample Sort
127
- auto t_ssssort = run (data, copy, out, size,
128
- [](T* data, T* out, size_t size)
129
- { ssssort::ssssort (data, data + size, out); },
130
- iterations, " ssssort: " );
140
+ // Sorting algorithms have their own time tracking
141
+ // 1. Super Scalar Sample Sort
142
+ run (data, copy, out, size,
143
+ [](T* data, T* out, size_t size)
144
+ { ssssort::ssssort (data, data + size, out); },
145
+ inner_its, t_ssssort, bar);
131
146
132
- // 2. std::sort
133
- auto t_stdsort = run (data, copy, out, size,
134
- [](T* data, T* /* ignored*/ , size_t size)
135
- { std::sort (data, data + size); },
136
- iterations, " std::sort: " , false );
147
+ // 2. std::sort
148
+ run (data, copy, out, size,
149
+ [](T* data, T* /* ignored*/ , size_t size)
150
+ { std::sort (data, data + size); },
151
+ inner_its, t_stdsort, bar , false );
137
152
138
153
139
- // verify
140
- timer.reset ();
141
- bool incorrect = !std::is_sorted (out, out + size);
142
- if (incorrect) {
143
- std::cerr << " Output data isn't sorted" << std::endl;
144
- }
145
- for (size_t i = 0 ; i < size; ++i) {
146
- incorrect |= (out[i] != data[i]);
147
- if (debug && out[i] != data[i]) {
148
- std::cerr << " Err at pos " << i << " expected " << data[i]
149
- << " got " << out[i] << std::endl;
154
+ // verify
155
+ timer.reset ();
156
+ bool it_incorrect = !std::is_sorted (out, out + size);
157
+ if (it_incorrect) {
158
+ std::cerr << " Output data isn't sorted" << std::endl;
150
159
}
160
+ for (size_t i = 0 ; i < size; ++i) {
161
+ it_incorrect |= (out[i] != data[i]);
162
+ if (debug && out[i] != data[i]) {
163
+ std::cerr << " Err at pos " << i << " expected " << data[i]
164
+ << " got " << out[i] << std::endl;
165
+ }
166
+ }
167
+ incorrect |= it_incorrect;
168
+ t_verify += timer.get_and_reset ();
169
+
151
170
}
152
- double t_verify = timer.get_and_reset ();
171
+
172
+ bar.undraw ();
153
173
154
174
delete[] out;
155
175
delete[] data;
@@ -159,7 +179,7 @@ size_t benchmark(size_t size, size_t iterations, Generator generator,
159
179
output << " RESULT algo=ssssort"
160
180
<< " name=" << name
161
181
<< " size=" << size
162
- << " iters=" << iterations
182
+ << " iters=" << outer_its << " * " << inner_its
163
183
<< " time=" << t_ssssort.avg ()
164
184
<< " stddev=" << t_ssssort.stddev ()
165
185
<< " t_gen=" << t_generate
@@ -169,7 +189,7 @@ size_t benchmark(size_t size, size_t iterations, Generator generator,
169
189
<< " RESULT algo=stdsort"
170
190
<< " name=" << name
171
191
<< " size=" << size
172
- << " iters=" << iterations
192
+ << " iters=" << outer_its << " * " << inner_its
173
193
<< " time=" << t_stdsort.avg ()
174
194
<< " stddev=" << t_stdsort.stddev ()
175
195
<< " t_gen=" << t_generate
@@ -186,33 +206,35 @@ size_t benchmark(size_t size, size_t iterations, Generator generator,
186
206
187
207
template <typename T, typename Generator>
188
208
void benchmark_generator (Generator generator, const std::string &name,
189
- size_t iterations, std::ofstream *stat_stream,
190
- size_t max_log_size = 27 ) {
209
+ const size_t outer_its, const size_t inner_its,
210
+ std::ofstream *stat_stream,
211
+ const size_t max_log_size = 27 ) {
191
212
auto wrapped_generator = [generator](auto data, size_t size) {
192
213
generator (data, size);
193
214
return size;
194
215
};
195
216
196
217
// warmup
197
- benchmark<T>(1 <<10 , 10 , wrapped_generator, " warmup" , nullptr );
218
+ benchmark<T>(1 <<10 , wrapped_generator, " warmup" , 1 , 10 , nullptr );
198
219
199
220
for (size_t log_size = 10 ; log_size < max_log_size; ++log_size) {
200
221
size_t size = 1 << log_size;
201
- benchmark<T>(size, iterations, wrapped_generator, name, stat_stream);
222
+ benchmark<T>(size, wrapped_generator, name, outer_its, inner_its , stat_stream);
202
223
}
203
224
}
204
225
205
226
206
227
template <typename T, typename Generator>
207
228
void sized_benchmark_generator (Generator generator, const std::string &name,
208
- size_t iterations, std::ofstream *stat_stream,
209
- size_t max_log_size = 27 ) {
229
+ const size_t outer_its, const size_t inner_its,
230
+ std::ofstream *stat_stream,
231
+ const size_t max_log_size = 27 ) {
210
232
// warmup
211
- benchmark<T>(1 <<10 , 10 , generator, " warmup" , nullptr );
233
+ benchmark<T>(1 <<10 , 10 , generator, " warmup" , 0 , nullptr );
212
234
213
235
for (size_t log_size = 10 ; log_size < max_log_size; ++log_size) {
214
236
size_t size = 1 << log_size;
215
- auto last_size = benchmark<T>(size, iterations, generator, name, stat_stream);
237
+ size_t last_size = benchmark<T>(size, generator, name, outer_its, inner_its , stat_stream);
216
238
if (last_size < size) break ;
217
239
}
218
240
}
0 commit comments