benchmark_objects.cpp 18 KB

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