benchmark_objects.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. //----------------------------------------------------------------------------
  2. /// @file benchmark_objects.cpp
  3. /// @brief Benchmark of several sort methods with different objects
  4. ///
  5. /// @author Copyright (c) 2016 Francisco José Tapia (fjtapia@gmail.com )\n
  6. /// Distributed under the Boost Software License, Version 1.0.\n
  7. /// ( See accompanying file LICENSE_1_0.txt or copy at
  8. /// http://www.boost.org/LICENSE_1_0.txt )
  9. ///
  10. /// This program use for comparison purposes, the Threading Building
  11. /// Blocks which license is the GNU General Public License, version 2
  12. /// as published by the Free Software Foundation.
  13. ///
  14. /// @version 0.1
  15. ///
  16. /// @remarks
  17. //-----------------------------------------------------------------------------
  18. #include <algorithm>
  19. #include <iostream>
  20. #include <iomanip>
  21. #include <random>
  22. #include <stdlib.h>
  23. #include <vector>
  24. #include <boost/sort/common/time_measure.hpp>
  25. #include <boost/sort/common/file_vector.hpp>
  26. #include "boost/sort/common/int_array.hpp"
  27. #include <boost/sort/sort.hpp>
  28. #define NELEM 100000000
  29. #define NMAXSTRING 10000000
  30. using namespace std;
  31. namespace bsort = boost::sort;
  32. namespace bsc = bsort::common;
  33. using bsc::time_point;
  34. using bsc::now;
  35. using bsc::subtract_time;
  36. using bsc::fill_vector_uint64;
  37. using bsc::write_file_uint64;
  38. using bsc::int_array;
  39. using bsc::H_comp;
  40. using bsc::L_comp;
  41. using bsort::flat_stable_sort;
  42. using bsort::spinsort;
  43. using bsort::spreadsort::spreadsort;
  44. using bsort::pdqsort;
  45. template <class IA>
  46. void Generator_random(uint64_t N);
  47. template <class IA>
  48. void Generator_sorted(uint64_t N);
  49. template <class IA>
  50. void Generator_sorted_end(uint64_t N, size_t n_last );
  51. template <class IA>
  52. void Generator_sorted_middle(uint64_t N, size_t n_last );
  53. template <class IA>
  54. void Generator_reverse_sorted(uint64_t N);
  55. template <class IA>
  56. void Generator_reverse_sorted_end(uint64_t N, size_t n_last );
  57. template <class IA>
  58. void Generator_reverse_sorted_middle(uint64_t N, size_t n_last );
  59. template < class IA >
  60. struct H_rightshift {
  61. inline uint64_t operator()(const IA& A1, unsigned offset) {
  62. return A1.counter() >> offset;
  63. }
  64. };
  65. template < class IA >
  66. struct L_rightshift {
  67. inline uint64_t operator()(const IA& A1, unsigned offset) {
  68. return A1.M[0] >> offset;
  69. }
  70. };
  71. template <class IA, class rightshift, class compare>
  72. int Test(std::vector<IA> &B, rightshift shift, compare comp, std::vector<double> & V );
  73. template <class IA>
  74. void Test_size ( uint64_t N);
  75. void Print_vectors ( std::vector<double> & V1, std::vector<double> & V2);
  76. int main(int argc, char *argv[])
  77. {
  78. cout << "\n\n";
  79. cout << "************************************************************\n";
  80. cout << "** **\n";
  81. cout << "** B O O S T S O R T **\n";
  82. cout << "** **\n";
  83. cout << "** O B J E C T S B E N C H M A R K **\n";
  84. cout << "** **\n";
  85. cout << "************************************************************\n";
  86. cout << std::endl;
  87. cout << "=============================================================\n";
  88. cout << "= OBJECT COMPARISON =\n";
  89. cout << "= --------------------- =\n";
  90. cout << "= =\n";
  91. cout << "= The objects are arrays of 64 bits numbers =\n";
  92. cout << "= They are compared in two ways : =\n";
  93. cout << "= (H) Heavy : The comparison is the sum of all the numbers =\n";
  94. cout << "= of the array =\n";
  95. cout << "= (L) Light : The comparison is with the first element of =\n";
  96. cout << "= the array, as a key =\n";
  97. cout << "= =\n";
  98. cout << "============================================================\n";
  99. cout << "\n\n";
  100. //-----------------------------------------------------------------------
  101. // I N T _ A R R A Y < 1 >
  102. //-----------------------------------------------------------------------
  103. cout << "************************************************************\n";
  104. cout << "** **\n";
  105. cout << " "<<NELEM<<" OBJECTS UINT64_T [1]\n";
  106. cout << "** **\n";
  107. cout << "************************************************************\n";
  108. Test_size<int_array<1> >(NELEM);
  109. //-----------------------------------------------------------------------
  110. // I N T _ A R R A Y < 4 >
  111. //-----------------------------------------------------------------------
  112. cout << "************************************************************\n";
  113. cout << "** **\n";
  114. cout << " "<<(NELEM >>2)<<" OBJECTS UINT64_T [4]\n";
  115. cout << "** **\n";
  116. cout << "************************************************************\n";
  117. Test_size<int_array<4> >(NELEM >> 2);
  118. //-----------------------------------------------------------------------
  119. // I N T _ A R R A Y < 8 >
  120. //-----------------------------------------------------------------------
  121. cout << "************************************************************\n";
  122. cout << "** **\n";
  123. cout << " "<<(NELEM >>3)<<" OBJECTS UINT64_T [8]\n";
  124. cout << "** **\n";
  125. cout << "************************************************************\n";
  126. Test_size<int_array<8> >(NELEM >> 3);
  127. //-----------------------------------------------------------------------
  128. // I N T _ A R R A Y < 1 6 >
  129. //-----------------------------------------------------------------------
  130. cout << "************************************************************\n";
  131. cout << "** **\n";
  132. cout << " "<<(NELEM >>4)<<" OBJECTS UINT64_T [16]\n";
  133. cout << "** **\n";
  134. cout << "************************************************************\n";
  135. Test_size<int_array<16> >(NELEM >> 4);
  136. //-----------------------------------------------------------------------
  137. // I N T _ A R R A Y < 6 4 >
  138. //-----------------------------------------------------------------------
  139. cout << "************************************************************\n";
  140. cout << "** **\n";
  141. cout << " "<< (NELEM >>6)<<" OBJECTS UINT64_T [64]\n";
  142. cout << "** **\n";
  143. cout << "************************************************************\n";
  144. Test_size<int_array<64> >(NELEM >> 6);
  145. return 0;
  146. }
  147. template <class IA>
  148. void Test_size ( uint64_t N)
  149. {
  150. cout<<"\n";
  151. cout<<"[ 1 ] std::sort [ 2 ] pdqsort [ 3 ] std::stable_sort \n";
  152. cout<<"[ 4 ] spinsort [ 5 ] flat_stable_sort [ 6 ] spreadsort\n\n";
  153. cout << " | [ 1 ] | [ 2 ] | [ 3 ] |";
  154. cout << " [ 4 ] | [ 5 ] | [ 6 ] |\n";
  155. //cout << " | | | |";
  156. //cout << " | | |\n";
  157. cout << " | H L | H L | H L |";
  158. cout << " H L | H L | H L |\n";
  159. cout << "--------------------+-----------+-----------+-----------+";
  160. cout << "-----------+-----------+-----------+\n";
  161. std::string empty_line = " | | |"
  162. " | | | |\n";
  163. cout<<"random |";
  164. Generator_random<IA>(N);
  165. cout<<empty_line;
  166. cout<<"sorted |";
  167. Generator_sorted<IA>(N);
  168. cout<<"sorted + 0.1% end |";
  169. Generator_sorted_end<IA>(N, N / 1000);
  170. cout<<"sorted + 1% end |";
  171. Generator_sorted_end<IA>(N, N / 100);
  172. cout<<"sorted + 10% end |";
  173. Generator_sorted_end<IA>(N, N / 10);
  174. cout<<empty_line;
  175. cout<<"sorted + 0.1% mid |";
  176. Generator_sorted_middle<IA>(N, N / 1000);
  177. cout<<"sorted + 1% mid |";
  178. Generator_sorted_middle<IA>(N, N / 100);
  179. cout<<"sorted + 10% mid |";
  180. Generator_sorted_middle<IA>(N, N / 10);
  181. cout<<empty_line;
  182. cout<<"reverse sorted |";
  183. Generator_reverse_sorted<IA>(N);
  184. cout<<"rv sorted + 0.1% end|";
  185. Generator_reverse_sorted_end<IA>(N, N / 1000);
  186. cout<<"rv sorted + 1% end|";
  187. Generator_reverse_sorted_end<IA>(N, N / 100);
  188. cout<<"rv sorted + 10% end|";
  189. Generator_reverse_sorted_end<IA>(N, N / 10);
  190. cout<<empty_line;
  191. cout<<"rv sorted + 0.1% mid|";
  192. Generator_reverse_sorted_middle<IA>(N, N / 1000);
  193. cout<<"rv sorted + 1% mid|";
  194. Generator_reverse_sorted_middle<IA>(N, N / 100);
  195. cout<<"rv sorted + 10% mid|";
  196. Generator_reverse_sorted_middle<IA>(N, N / 10);
  197. cout<< "--------------------+-----------+-----------+-----------+";
  198. cout << "-----------+-----------+-----------+\n";
  199. cout<<endl<<endl<<endl;
  200. }
  201. void Print_vectors ( std::vector<double> & V1, std::vector<double> & V2)
  202. {
  203. assert ( V1.size() == V2.size());
  204. std::cout<<std::setprecision(2)<<std::fixed;
  205. for ( uint32_t i =0 ; i < V1.size() ; ++i)
  206. { std::cout<<std::right<<std::setw(5)<<V1[i]<<" ";
  207. std::cout<<std::right<<std::setw(5)<<V2[i]<<"|";
  208. };
  209. std::cout<<std::endl;
  210. }
  211. template <class IA>
  212. void Generator_random(uint64_t N)
  213. {
  214. bsc::uint64_file_generator gen("input.bin");
  215. vector<IA> A;
  216. A.reserve(N);
  217. std::vector<double> V1, V2 ;
  218. gen.reset();
  219. A.clear();
  220. for (uint32_t i = 0; i < N; i++) A.emplace_back(IA::generate(gen));
  221. Test(A, H_rightshift<IA>(), H_comp<IA>(), V1);
  222. Test(A, L_rightshift<IA>(), L_comp<IA>(), V2);
  223. Print_vectors ( V1, V2 ) ;
  224. };
  225. template <class IA>
  226. void Generator_sorted(uint64_t N)
  227. {
  228. bsc::uint64_file_generator gen("input.bin");
  229. vector<IA> A;
  230. A.reserve(N);
  231. std::vector<double> V1, V2 ;
  232. gen.reset();
  233. A.clear();
  234. for (uint32_t i = 0; i < N; i++) A.emplace_back(IA::generate(gen));
  235. std::sort( A.begin() , A.end(),H_comp<IA>() );
  236. Test(A, H_rightshift<IA>(), H_comp<IA>(), V1);
  237. std::sort( A.begin() , A.end(),L_comp<IA>() );
  238. Test(A, L_rightshift<IA>(), L_comp<IA>(), V2);
  239. Print_vectors ( V1, V2 ) ;
  240. };
  241. template <class IA>
  242. void Generator_sorted_end(uint64_t N, size_t n_last )
  243. {
  244. bsc::uint64_file_generator gen("input.bin");
  245. vector<IA> A;
  246. A.reserve(N);
  247. std::vector<double> V1, V2 ;
  248. gen.reset();
  249. A.clear();
  250. for (uint32_t i = 0; i < (N + n_last); i++)
  251. A.emplace_back(IA::generate(gen));
  252. std::sort ( A.begin() , A.begin() + N ,H_comp<IA>());
  253. Test(A, H_rightshift<IA>(), H_comp<IA>(),V1);
  254. std::sort ( A.begin() , A.begin() + N ,L_comp<IA>());
  255. Test(A, L_rightshift<IA>(), L_comp<IA>(), V2);
  256. Print_vectors ( V1, V2 ) ;
  257. };
  258. template <class IA>
  259. void Generator_sorted_middle(uint64_t N, size_t n_last )
  260. {
  261. bsc::uint64_file_generator gen("input.bin");
  262. std::vector<double> V1, V2 ;
  263. vector<IA> A;
  264. A.reserve(N + n_last);
  265. { A.clear() ;
  266. gen.reset();
  267. vector<IA> B, C;
  268. C.reserve(N + n_last);
  269. B.reserve ( n_last);
  270. for (uint32_t i = 0; i < (N + n_last); i++)
  271. C.emplace_back(IA::generate(gen));
  272. for ( size_t i = N ; i < C.size() ; ++i)
  273. B.push_back ( std::move ( C[i]));
  274. C.resize ( N);
  275. std::sort ( C.begin() , C.end() ,H_comp<IA>());
  276. size_t step = N /n_last ;
  277. size_t pos = 0 ;
  278. for ( size_t i =0 ; i < B.size() ; ++i)
  279. { A.push_back ( B[i]);
  280. for ( size_t k = 0 ; k < step ; ++k )
  281. A.push_back ( C[pos++] );
  282. };
  283. while ( pos < C.size() )
  284. A.push_back ( C[pos++]);
  285. };
  286. Test(A, H_rightshift<IA>(), H_comp<IA>(), V1);
  287. { A.clear() ;
  288. gen.reset();
  289. vector<IA> B,C;
  290. C.reserve(N + n_last);
  291. B.reserve ( n_last);
  292. for (uint32_t i = 0; i < (N + n_last); i++)
  293. C.emplace_back(IA::generate(gen));
  294. for ( size_t i = N ; i < C.size() ; ++i)
  295. B.push_back ( std::move ( C[i]));
  296. C.resize ( N);
  297. std::sort ( C.begin() , C.end() ,L_comp<IA>());
  298. size_t step = N /n_last ;
  299. size_t pos = 0 ;
  300. for ( size_t i =0 ; i < B.size() ; ++i)
  301. { A.push_back ( B[i]);
  302. for ( size_t k = 0 ; k < step ; ++k )
  303. A.push_back ( C[pos++] );
  304. };
  305. while ( pos < C.size() )
  306. A.push_back ( C[pos++]);
  307. };
  308. Test(A, L_rightshift<IA>(), L_comp<IA>(), V2);
  309. Print_vectors ( V1, V2 ) ;
  310. };
  311. template <class IA>
  312. void Generator_reverse_sorted(uint64_t N)
  313. {
  314. bsc::uint64_file_generator gen("input.bin");
  315. vector<IA> A;
  316. A.reserve(N);
  317. std::vector<double> V1, V2 ;
  318. gen.reset();
  319. A.clear();
  320. for (uint32_t i = 0; i < N; i++) A.emplace_back(IA::generate(gen));
  321. std::sort( A.begin() , A.end(),H_comp<IA>() );
  322. for ( size_t i = 0; i < (A.size() >>1) ; ++i)
  323. std::swap ( A[i], A[A.size() - i -1 ]);
  324. Test(A, H_rightshift<IA>(), H_comp<IA>(), V1);
  325. std::sort( A.begin() , A.end(),L_comp<IA>() );
  326. for ( size_t i = 0; i < (A.size() >>1) ; ++i)
  327. std::swap ( A[i], A[A.size() - i -1 ]);
  328. Test(A, L_rightshift<IA>(), L_comp<IA>(), V2);
  329. Print_vectors ( V1, V2 ) ;
  330. };
  331. template <class IA>
  332. void Generator_reverse_sorted_end(uint64_t N, size_t n_last )
  333. {
  334. bsc::uint64_file_generator gen("input.bin");
  335. vector<IA> A;
  336. A.reserve(N);
  337. std::vector<double> V1, V2 ;
  338. gen.reset();
  339. A.clear();
  340. for (uint32_t i = 0; i < (N + n_last); i++)
  341. A.emplace_back(IA::generate(gen));
  342. std::sort ( A.begin() , A.begin() + N ,H_comp<IA>());
  343. for ( size_t i =0 ; i < (N>>1); ++i)
  344. std::swap ( A[i], A[N-1-i]);
  345. Test(A, H_rightshift<IA>(), H_comp<IA>(), V1);
  346. std::sort ( A.begin() , A.begin() + N ,L_comp<IA>());
  347. for ( size_t i =0 ; i < (N>>1); ++i)
  348. std::swap ( A[i], A[N-1-i]);
  349. Test(A, L_rightshift<IA>(), L_comp<IA>(), V2);
  350. Print_vectors ( V1, V2 ) ;
  351. };
  352. template <class IA>
  353. void Generator_reverse_sorted_middle(uint64_t N, size_t n_last )
  354. {
  355. bsc::uint64_file_generator gen("input.bin");
  356. std::vector<double> V1, V2 ;
  357. vector<IA> A;
  358. A.reserve(N + n_last);
  359. { A.clear() ;
  360. gen.reset();
  361. vector<IA> B,C;
  362. C.reserve(N + n_last);
  363. B.reserve ( n_last);
  364. for (uint32_t i = 0; i < (N + n_last); i++)
  365. C.emplace_back(IA::generate(gen));
  366. for ( size_t i = N ; i < C.size() ; ++i)
  367. B.push_back ( std::move ( C[i]));
  368. C.resize ( N);
  369. std::sort ( C.begin() , C.end() ,H_comp<IA>());
  370. for ( size_t i =0 ; i < (N>>1); ++i)
  371. std::swap ( C[i], C[N-1-i]);
  372. size_t step = N /n_last ;
  373. size_t pos = 0 ;
  374. for ( size_t i =0 ; i < B.size() ; ++i)
  375. { A.push_back ( B[i]);
  376. for ( size_t k = 0 ; k < step ; ++k )
  377. A.push_back ( C[pos++ ] );
  378. };
  379. while ( pos < C.size() )
  380. A.push_back ( C[pos++]);
  381. };
  382. Test(A, H_rightshift<IA>(), H_comp<IA>(), V1);
  383. { A.clear() ;
  384. gen.reset();
  385. vector<IA> B,C;
  386. C.reserve(N + n_last);
  387. B.reserve ( n_last);
  388. for (uint32_t i = 0; i < (N + n_last); i++)
  389. C.emplace_back(IA::generate(gen));
  390. for ( size_t i = N ; i < C.size() ; ++i)
  391. B.push_back ( std::move ( C[i]));
  392. C.resize ( N);
  393. std::sort ( C.begin() , C.end() ,L_comp<IA>());
  394. for ( size_t i =0 ; i < (N>>1); ++i)
  395. std::swap ( C[i], C[N-1-i]);
  396. size_t step = N /n_last ;
  397. size_t pos = 0 ;
  398. for ( size_t i =0 ; i < B.size() ; ++i)
  399. { A.push_back ( B[i]);
  400. for ( size_t k = 0 ; k < step ; ++k )
  401. A.push_back ( C[pos++ ] );
  402. };
  403. while ( pos < C.size() )
  404. A.push_back ( C[pos++]);
  405. };
  406. Test(A, L_rightshift<IA>(), L_comp<IA>(), V2);
  407. Print_vectors ( V1, V2 ) ;
  408. };
  409. template<class IA, class rightshift, class compare>
  410. int Test (std::vector<IA> &B, rightshift shift, compare comp,std::vector<double> &V)
  411. { //---------------------------- begin --------------------------------
  412. double duration;
  413. time_point start, finish;
  414. std::vector<IA> A (B);
  415. V.clear() ;
  416. //--------------------------------------------------------------------
  417. A = B;
  418. start = now ();
  419. std::sort (A.begin (), A.end (), comp);
  420. finish = now ();
  421. duration = subtract_time (finish, start);
  422. V.push_back (duration);
  423. A = B;
  424. start = now ();
  425. pdqsort (A.begin (), A.end (), comp);
  426. finish = now ();
  427. duration = subtract_time (finish, start);
  428. V.push_back (duration);
  429. A = B;
  430. start = now ();
  431. std::stable_sort (A.begin (), A.end (), comp);
  432. finish = now ();
  433. duration = subtract_time (finish, start);
  434. V.push_back (duration);
  435. A = B;
  436. start = now ();
  437. spinsort (A.begin (), A.end (), comp);
  438. finish = now ();
  439. duration = subtract_time (finish, start);
  440. V.push_back (duration);
  441. A = B;
  442. start = now ();
  443. flat_stable_sort (A.begin (), A.end (), comp);
  444. finish = now ();
  445. duration = subtract_time (finish, start);
  446. V.push_back (duration);
  447. A = B;
  448. start = now ();
  449. boost::sort::spreadsort::integer_sort (A.begin (), A.end (), shift, comp);
  450. finish = now ();
  451. duration = subtract_time (finish, start);
  452. V.push_back (duration);
  453. return 0;
  454. };