1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2015-2016.
4 // Distributed under the Boost Software License, Version 1.0.
5 // (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // See http://www.boost.org/libs/move for documentation.
10 //////////////////////////////////////////////////////////////////////////////
12 #include <cstdlib> //std::srand
13 #include <algorithm> //std::stable_sort, std::make|sort_heap, std::random_shuffle
14 #include <cstdio> //std::printf
15 #include <iostream> //std::cout
17 #include <boost/config.hpp>
19 #include <boost/move/unique_ptr.hpp>
20 #include <boost/timer/timer.hpp>
22 using boost::timer::cpu_timer
;
23 using boost::timer::cpu_times
;
24 using boost::timer::nanosecond_type
;
26 #include "order_type.hpp"
27 #include "random_shuffle.hpp"
29 //#define BOOST_MOVE_ADAPTIVE_SORT_STATS
30 //#define BOOST_MOVE_ADAPTIVE_SORT_INVARIANTS
31 void print_stats(const char *str
, boost::ulong_long_type element_count
)
33 std::printf("%sCmp:%7.03f Cpy:%8.03f\n", str
, double(order_perf_type::num_compare
)/element_count
, double(order_perf_type::num_copy
)/element_count
);
37 #include <boost/move/algo/adaptive_sort.hpp>
38 #include <boost/move/algo/detail/merge_sort.hpp>
39 #include <boost/move/algo/detail/pdqsort.hpp>
40 #include <boost/move/algo/detail/heap_sort.hpp>
41 #include <boost/move/core.hpp>
44 void generate_elements(T elements
[], std::size_t element_count
, std::size_t key_reps
[], std::size_t key_len
)
47 for(std::size_t i
= 0; i
< (key_len
? key_len
: element_count
); ++i
){
50 for(std::size_t i
=0; i
< element_count
; ++i
){
51 std::size_t key
= key_len
? (i
% key_len
) : i
;
54 ::random_shuffle(elements
, elements
+ element_count
);
55 ::random_shuffle(elements
, elements
+ element_count
);
56 ::random_shuffle(elements
, elements
+ element_count
);
57 for(std::size_t i
= 0; i
< element_count
; ++i
){
58 elements
[i
].val
= key_reps
[elements
[i
].key
]++;
62 template<class T
, class Compare
>
63 void adaptive_sort_buffered(T
*elements
, std::size_t element_count
, Compare comp
, std::size_t BufLen
)
65 boost::movelib::unique_ptr
<char[]> mem(new char[sizeof(T
)*BufLen
]);
66 boost::movelib::adaptive_sort(elements
, elements
+ element_count
, comp
, reinterpret_cast<T
*>(mem
.get()), BufLen
);
69 template<class T
, class Compare
>
70 void merge_sort_buffered(T
*elements
, std::size_t element_count
, Compare comp
)
72 boost::movelib::unique_ptr
<char[]> mem(new char[sizeof(T
)*((element_count
+1)/2)]);
73 boost::movelib::merge_sort(elements
, elements
+ element_count
, comp
, reinterpret_cast<T
*>(mem
.get()));
93 const char *AlgoNames
[] = { "MergeSort "
107 BOOST_STATIC_ASSERT((sizeof(AlgoNames
)/sizeof(*AlgoNames
)) == MaxSort
);
110 bool measure_algo(T
*elements
, std::size_t key_reps
[], std::size_t element_count
, std::size_t key_len
, unsigned alg
, nanosecond_type
&prev_clock
)
112 generate_elements(elements
, element_count
, key_reps
, key_len
);
114 std::printf("%s ", AlgoNames
[alg
]);
115 order_perf_type::num_compare
=0;
116 order_perf_type::num_copy
=0;
117 order_perf_type::num_elements
= element_count
;
123 merge_sort_buffered(elements
, element_count
, order_type_less());
126 std::stable_sort(elements
,elements
+element_count
,order_type_less());
129 boost::movelib::pdqsort(elements
,elements
+element_count
,order_type_less());
132 std::sort(elements
,elements
+element_count
,order_type_less());
135 boost::movelib::adaptive_sort(elements
, elements
+element_count
, order_type_less());
137 case SqrtHAdaptiveSort
:
138 adaptive_sort_buffered( elements
, element_count
, order_type_less()
139 , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count
)/2+1);
141 case SqrtAdaptiveSort
:
142 adaptive_sort_buffered( elements
, element_count
, order_type_less()
143 , boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count
));
145 case Sqrt2AdaptiveSort
:
146 adaptive_sort_buffered( elements
, element_count
, order_type_less()
147 , 2*boost::movelib::detail_adaptive::ceil_sqrt_multiple(element_count
));
149 case QuartAdaptiveSort
:
150 adaptive_sort_buffered( elements
, element_count
, order_type_less()
151 , (element_count
-1)/4+1);
153 case InplaceStableSort
:
154 boost::movelib::inplace_stable_sort(elements
, elements
+element_count
, order_type_less());
157 boost::movelib::detail_adaptive::slow_stable_sort(elements
, elements
+element_count
, order_type_less());
160 boost::movelib::heap_sort(elements
, elements
+element_count
, order_type_less());
161 boost::movelib::heap_sort((order_move_type
*)0, (order_move_type
*)0, order_type_less());
167 if(order_perf_type::num_elements
== element_count
){
168 std::printf(" Tmp Ok ");
170 std::printf(" Tmp KO ");
172 nanosecond_type new_clock
= timer
.elapsed().wall
;
174 //std::cout << "Cmp:" << order_perf_type::num_compare << " Cpy:" << order_perf_type::num_copy; //for old compilers without ll size argument
175 std::printf("Cmp:%7.03f Cpy:%8.03f", double(order_perf_type::num_compare
)/element_count
, double(order_perf_type::num_copy
)/element_count
);
177 double time
= double(new_clock
);
179 const char *units
= "ns";
180 if(time
>= 1000000000.0){
181 time
/= 1000000000.0;
184 else if(time
>= 1000000.0){
188 else if(time
>= 1000.0){
193 std::printf(" %6.02f%s (%6.02f)\n"
196 , prev_clock
? double(new_clock
)/double(prev_clock
): 1.0);
197 prev_clock
= new_clock
;
198 bool res
= is_order_type_ordered(elements
, element_count
, alg
!= HeapSort
&& alg
!= PdQsort
&& alg
!= StdSort
);
203 bool measure_all(std::size_t L
, std::size_t NK
)
205 boost::movelib::unique_ptr
<T
[]> pdata(new T
[L
]);
206 boost::movelib::unique_ptr
<std::size_t[]> pkeys(new std::size_t[NK
? NK
: L
]);
208 std::size_t *Keys
= pkeys
.get();
209 std::printf("\n - - N: %u, NK: %u - -\n", (unsigned)L
, (unsigned)NK
);
211 nanosecond_type prev_clock
= 0;
212 nanosecond_type back_clock
;
214 res
= res
&& measure_algo(A
,Keys
,L
,NK
,MergeSort
, prev_clock
);
215 back_clock
= prev_clock
;
217 prev_clock
= back_clock
;
218 res
= res
&& measure_algo(A
,Keys
,L
,NK
,StableSort
, prev_clock
);
220 prev_clock
= back_clock
;
221 res
= res
&& measure_algo(A
,Keys
,L
,NK
,PdQsort
, prev_clock
);
223 prev_clock
= back_clock
;
224 res
= res
&& measure_algo(A
,Keys
,L
,NK
,StdSort
, prev_clock
);
226 prev_clock
= back_clock
;
227 res
= res
&& measure_algo(A
,Keys
,L
,NK
,HeapSort
, prev_clock
);
229 prev_clock
= back_clock
;
230 res
= res
&& measure_algo(A
,Keys
,L
,NK
,QuartAdaptiveSort
, prev_clock
);
232 prev_clock
= back_clock
;
233 res
= res
&& measure_algo(A
,Keys
,L
,NK
,Sqrt2AdaptiveSort
, prev_clock
);
235 prev_clock
= back_clock
;
236 res
= res
&& measure_algo(A
,Keys
,L
,NK
,SqrtAdaptiveSort
, prev_clock
);
238 prev_clock
= back_clock
;
239 res
= res
&& measure_algo(A
,Keys
,L
,NK
,SqrtHAdaptiveSort
, prev_clock
);
241 prev_clock
= back_clock
;
242 res
= res
&& measure_algo(A
,Keys
,L
,NK
,AdaptiveSort
, prev_clock
);
244 prev_clock
= back_clock
;
245 res
= res
&& measure_algo(A
,Keys
,L
,NK
,InplaceStableSort
, prev_clock
);
247 //prev_clock = back_clock;
248 //res = res && measure_algo(A,Keys,L,NK,SlowStableSort, prev_clock);
255 //Undef it to run the long test
256 #define BENCH_SORT_SHORT
257 #define BENCH_SORT_UNIQUE_VALUES
261 #ifndef BENCH_SORT_UNIQUE_VALUES
262 measure_all
<order_perf_type
>(101,1);
263 measure_all
<order_perf_type
>(101,7);
264 measure_all
<order_perf_type
>(101,31);
266 measure_all
<order_perf_type
>(101,0);
269 #ifndef BENCH_SORT_UNIQUE_VALUES
270 measure_all
<order_perf_type
>(1101,1);
271 measure_all
<order_perf_type
>(1001,7);
272 measure_all
<order_perf_type
>(1001,31);
273 measure_all
<order_perf_type
>(1001,127);
274 measure_all
<order_perf_type
>(1001,511);
276 measure_all
<order_perf_type
>(1001,0);
278 #ifndef BENCH_SORT_SHORT
279 #ifndef BENCH_SORT_UNIQUE_VALUES
280 measure_all
<order_perf_type
>(10001,65);
281 measure_all
<order_perf_type
>(10001,255);
282 measure_all
<order_perf_type
>(10001,1023);
283 measure_all
<order_perf_type
>(10001,4095);
285 measure_all
<order_perf_type
>(10001,0);
288 #ifndef BENCH_SORT_UNIQUE_VALUES
289 measure_all
<order_perf_type
>(100001,511);
290 measure_all
<order_perf_type
>(100001,2047);
291 measure_all
<order_perf_type
>(100001,8191);
292 measure_all
<order_perf_type
>(100001,32767);
294 measure_all
<order_perf_type
>(100001,0);
298 #ifndef BENCH_SORT_UNIQUE_VALUES
299 measure_all
<order_perf_type
>(1000001,1);
300 measure_all
<order_perf_type
>(1000001,1024);
301 measure_all
<order_perf_type
>(1000001,32768);
302 measure_all
<order_perf_type
>(1000001,524287);
304 measure_all
<order_perf_type
>(1000001,0);
305 measure_all
<order_perf_type
>(1500001,0);
308 #endif //#ifndef BENCH_SORT_SHORT
310 //measure_all<order_perf_type>(100000001,0);