inner_product2.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2005-2006 Dan Marsden
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. #include <boost/array.hpp>
  8. #include <boost/timer.hpp>
  9. #include <boost/fusion/algorithm/iteration/accumulate.hpp>
  10. #include <boost/fusion/algorithm/transformation/transform.hpp>
  11. #include <boost/fusion/container/vector.hpp>
  12. #include <boost/fusion/algorithm/transformation/zip.hpp>
  13. #include <boost/fusion/sequence/intrinsic/at.hpp>
  14. #include <boost/fusion/adapted/array.hpp>
  15. #include <boost/fusion/sequence/intrinsic/at.hpp>
  16. #include <boost/type_traits/remove_reference.hpp>
  17. #include <algorithm>
  18. #include <numeric>
  19. #include <functional>
  20. #include <iostream>
  21. #include <cmath>
  22. #include <limits>
  23. #ifdef _MSC_VER
  24. // inline aggressively
  25. # pragma inline_recursion(on) // turn on inline recursion
  26. # pragma inline_depth(255) // max inline depth
  27. #endif
  28. int const REPEAT_COUNT = 10;
  29. double const duration = 0.5;
  30. namespace
  31. {
  32. struct poly_add
  33. {
  34. template<typename Sig>
  35. struct result;
  36. template<typename Lhs, typename Rhs>
  37. struct result<poly_add(Lhs, Rhs)>
  38. : boost::remove_reference<Lhs>
  39. {};
  40. template<typename Lhs, typename Rhs>
  41. Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
  42. {
  43. return lhs + rhs;
  44. }
  45. };
  46. struct poly_mult
  47. {
  48. template<typename Sig>
  49. struct result;
  50. template<typename Lhs, typename Rhs>
  51. struct result<poly_mult(Lhs, Rhs)>
  52. : boost::remove_reference<Lhs>
  53. {};
  54. template<typename Lhs, typename Rhs>
  55. Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
  56. {
  57. return lhs * rhs;
  58. }
  59. };
  60. template<int N>
  61. double time_for_std_inner_product(int& j)
  62. {
  63. boost::timer tim;
  64. int i = 0;
  65. long long iter = 65536;
  66. long long counter, repeats;
  67. double result = (std::numeric_limits<double>::max)();
  68. double runtime = 0;
  69. double run;
  70. boost::array<int, N> arr1;
  71. boost::array<int, N> arr2;
  72. std::generate(arr1.begin(), arr1.end(), rand);
  73. std::generate(arr2.begin(), arr2.end(), rand);
  74. do
  75. {
  76. tim.restart();
  77. for(counter = 0; counter < iter; ++counter)
  78. {
  79. i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
  80. static_cast<void>(i);
  81. }
  82. runtime = tim.elapsed();
  83. iter *= 2;
  84. } while(runtime < duration);
  85. iter /= 2;
  86. // repeat test and report least value for consistency:
  87. for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
  88. {
  89. tim.restart();
  90. for(counter = 0; counter < iter; ++counter)
  91. {
  92. i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
  93. j += i;
  94. }
  95. run = tim.elapsed();
  96. result = (std::min)(run, result);
  97. }
  98. std::cout << i << std::endl;
  99. return result / iter;
  100. }
  101. struct poly_combine
  102. {
  103. template<typename Sig>
  104. struct result;
  105. template<typename Lhs, typename Rhs>
  106. struct result<poly_combine(Lhs, Rhs)>
  107. : boost::remove_reference<Lhs>
  108. {};
  109. template<typename Lhs, typename Rhs>
  110. typename result<poly_combine(Lhs,Rhs)>::type
  111. operator()(const Lhs& lhs, const Rhs& rhs) const
  112. {
  113. return lhs + boost::fusion::at_c<0>(rhs) * boost::fusion::at_c<1>(rhs);
  114. }
  115. };
  116. template<int N>
  117. double time_for_fusion_inner_product2(int& j)
  118. {
  119. boost::timer tim;
  120. int i = 0;
  121. long long iter = 65536;
  122. long long counter, repeats;
  123. double result = (std::numeric_limits<double>::max)();
  124. double runtime = 0;
  125. double run;
  126. boost::array<int, N> arr1;
  127. boost::array<int, N> arr2;
  128. std::generate(arr1.begin(), arr1.end(), rand);
  129. std::generate(arr2.begin(), arr2.end(), rand);
  130. do
  131. {
  132. tim.restart();
  133. for(counter = 0; counter < iter; ++counter)
  134. {
  135. i = boost::fusion::accumulate(
  136. boost::fusion::zip(arr1, arr2), 0, poly_combine());
  137. static_cast<void>(i);
  138. }
  139. runtime = tim.elapsed();
  140. iter *= 2;
  141. } while(runtime < duration);
  142. iter /= 2;
  143. std::cout << iter << " iterations" << std::endl;
  144. // repeat test and report least value for consistency:
  145. for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
  146. {
  147. tim.restart();
  148. for(counter = 0; counter < iter; ++counter)
  149. {
  150. i = boost::fusion::accumulate(
  151. boost::fusion::zip(arr1, arr2), 0, poly_combine());
  152. j += i;
  153. }
  154. run = tim.elapsed();
  155. result = (std::min)(run, result);
  156. }
  157. std::cout << i << std::endl;
  158. return result / iter;
  159. }
  160. }
  161. int main()
  162. {
  163. int total = 0;
  164. int res;
  165. std::cout << "short inner_product std test " << time_for_std_inner_product<8>(res) << std::endl;
  166. total += res;
  167. std::cout << "short inner_product fusion 2 test " << time_for_fusion_inner_product2<8>(res) << std::endl;
  168. total += res;
  169. std::cout << "medium inner_product std test " << time_for_std_inner_product<64>(res) << std::endl;
  170. total += res;
  171. std::cout << "medium inner_product fusion 2 test " << time_for_fusion_inner_product2<64>(res) << std::endl;
  172. total += res;
  173. #if 0 // Leads to ICE with MSVC 8.0
  174. std::cout << "long inner_product std test " << time_for_std_inner_product<128>(res) << std::endl;
  175. total += res;
  176. std::cout << "long inner_product fusion 2 test " << time_for_fusion_inner_product2<128>(res) << std::endl;
  177. total += res;
  178. #endif
  179. return total;
  180. }