functional.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2006-2007 Tobias Schwinger
  4. Use modification and distribution are subject to the Boost Software
  5. License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. http://www.boost.org/LICENSE_1_0.txt).
  7. ==============================================================================*/
  8. #include <boost/fusion/container/list.hpp>
  9. #include <boost/fusion/container/vector.hpp>
  10. #include <boost/fusion/algorithm/iteration/fold.hpp>
  11. #include <boost/fusion/functional/adapter/unfused.hpp>
  12. #include <boost/fusion/functional/adapter/fused_function_object.hpp>
  13. #include <boost/functional/forward_adapter.hpp>
  14. #include <boost/functional/lightweight_forward_adapter.hpp>
  15. #include <boost/utility/result_of.hpp>
  16. #include <boost/config.hpp>
  17. #include <boost/timer.hpp>
  18. #include <algorithm>
  19. #include <iostream>
  20. #ifdef _MSC_VER
  21. // inline aggressively
  22. # pragma inline_recursion(on) // turn on inline recursion
  23. # pragma inline_depth(255) // max inline depth
  24. #endif
  25. int const REPEAT_COUNT = 3;
  26. double const duration = 0.125;
  27. namespace
  28. {
  29. struct fused_sum
  30. {
  31. template <typename Seq>
  32. int operator()(Seq const & seq) const
  33. {
  34. int state = 0;
  35. return boost::fusion::fold(seq, state, sum_op());
  36. }
  37. typedef int result_type;
  38. private:
  39. struct sum_op
  40. {
  41. template <typename T>
  42. int operator()(T const & elem, int value) const
  43. {
  44. return value + sizeof(T) * elem;
  45. }
  46. template <typename T>
  47. int operator()(T & elem, int value) const
  48. {
  49. elem += sizeof(T);
  50. return value;
  51. }
  52. typedef int result_type;
  53. };
  54. };
  55. struct unfused_sum
  56. {
  57. inline int operator()() const
  58. {
  59. return 0;
  60. }
  61. template<typename T0>
  62. inline int operator()(T0 const & a0) const
  63. {
  64. return a0;
  65. }
  66. template<typename T0, typename T1>
  67. inline int operator()(T0 const & a0, T1 const & a1) const
  68. {
  69. return a0 + a1;
  70. }
  71. template<typename T0, typename T1, typename T2>
  72. inline int operator()(T0 const & a0, T1 const & a1, T2 a2) const
  73. {
  74. return a0 + a1 + a2;
  75. }
  76. template<typename T0, typename T1, typename T2, typename T3>
  77. inline int operator()(T0 const & a0, T1 const & a1, T2 const & a2, T3 const & a3) const
  78. {
  79. return a0 + a1 + a2 + a3;
  80. }
  81. typedef int result_type;
  82. };
  83. template<typename F>
  84. double call_unfused(F const & func, int & j)
  85. {
  86. boost::timer tim;
  87. int i = 0;
  88. long long iter = 65536;
  89. long long counter, repeats;
  90. double result = (std::numeric_limits<double>::max)();
  91. double runtime = 0;
  92. double run;
  93. do
  94. {
  95. tim.restart();
  96. for(counter = 0; counter < iter; ++counter)
  97. {
  98. i += func();
  99. i += func(0);
  100. i += func(0,1);
  101. i += func(0,1,2);
  102. i += func(0,1,2,3);
  103. }
  104. runtime = tim.elapsed();
  105. iter *= 2;
  106. } while(runtime < duration);
  107. iter /= 2;
  108. for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
  109. {
  110. tim.restart();
  111. for(counter = 0; counter < iter; ++counter)
  112. {
  113. i = func(); j += i;
  114. i = func(0); j += i;
  115. i = func(0,1); j += i;
  116. i = func(0,1,2); j += i;
  117. i = func(0,1,2,3); j += i;
  118. }
  119. run = tim.elapsed();
  120. result = (std::min)(run, result);
  121. }
  122. return result / iter;
  123. }
  124. template<typename F>
  125. double call_fused_ra(F const & func, int & j)
  126. {
  127. boost::timer tim;
  128. int i = 0;
  129. long long iter = 65536;
  130. long long counter, repeats;
  131. double result = (std::numeric_limits<double>::max)();
  132. double runtime = 0;
  133. double run;
  134. do
  135. {
  136. boost::fusion::vector<> v0;
  137. boost::fusion::vector<int> v1(0);
  138. boost::fusion::vector<int,int> v2(0,1);
  139. boost::fusion::vector<int,int,int> v3(0,1,2);
  140. boost::fusion::vector<int,int,int,int> v4(0,1,2,3);
  141. tim.restart();
  142. for(counter = 0; counter < iter; ++counter)
  143. {
  144. i += func(v0);
  145. i += func(v1);
  146. i += func(v2);
  147. i += func(v3);
  148. i += func(v4);
  149. }
  150. runtime = tim.elapsed();
  151. iter *= 2;
  152. } while(runtime < duration);
  153. iter /= 2;
  154. for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
  155. {
  156. boost::fusion::vector<> v0;
  157. boost::fusion::vector<int> v1(0);
  158. boost::fusion::vector<int,int> v2(0,1);
  159. boost::fusion::vector<int,int,int> v3(0,1,2);
  160. boost::fusion::vector<int,int,int,int> v4(0,1,2,3);
  161. tim.restart();
  162. for(counter = 0; counter < iter; ++counter)
  163. {
  164. i = func(v0); j += i;
  165. i = func(v1); j += i;
  166. i = func(v2); j += i;
  167. i = func(v3); j += i;
  168. i = func(v4); j += i;
  169. }
  170. run = tim.elapsed();
  171. result = (std::min)(run, result);
  172. }
  173. return result / iter;
  174. }
  175. template<typename F>
  176. double call_fused(F const & func, int & j)
  177. {
  178. boost::timer tim;
  179. int i = 0;
  180. long long iter = 65536;
  181. long long counter, repeats;
  182. double result = (std::numeric_limits<double>::max)();
  183. double runtime = 0;
  184. double run;
  185. do
  186. {
  187. boost::fusion::list<> l0;
  188. boost::fusion::list<int> l1(0);
  189. boost::fusion::list<int,int> l2(0,1);
  190. boost::fusion::list<int,int,int> l3(0,1,2);
  191. boost::fusion::list<int,int,int,int> l4(0,1,2,3);
  192. tim.restart();
  193. for(counter = 0; counter < iter; ++counter)
  194. {
  195. i += func(l0);
  196. i += func(l1);
  197. i += func(l2);
  198. i += func(l3);
  199. i += func(l4);
  200. }
  201. runtime = tim.elapsed();
  202. iter *= 2;
  203. } while(runtime < duration);
  204. iter /= 2;
  205. for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
  206. {
  207. boost::fusion::list<> l0;
  208. boost::fusion::list<int> l1(0);
  209. boost::fusion::list<int,int> l2(0,1);
  210. boost::fusion::list<int,int,int> l3(0,1,2);
  211. boost::fusion::list<int,int,int,int> l4(0,1,2,3);
  212. tim.restart();
  213. for(counter = 0; counter < iter; ++counter)
  214. {
  215. i = func(l0); j += i;
  216. i = func(l1); j += i;
  217. i = func(l2); j += i;
  218. i = func(l3); j += i;
  219. i = func(l4); j += i;
  220. }
  221. run = tim.elapsed();
  222. result = (std::min)(run, result);
  223. }
  224. return result / iter;
  225. }
  226. }
  227. int main()
  228. {
  229. int total = 0;
  230. int res;
  231. typedef fused_sum F;
  232. typedef unfused_sum U;
  233. std::cout << "Compiler: " << BOOST_COMPILER << std::endl;
  234. std::cout << std::endl << "Unfused adapters:" << std::endl;
  235. {
  236. F f;
  237. std::cout << "F /* a fused function object */ " << call_fused_ra(f,res) << std::endl;
  238. total += res;
  239. }
  240. {
  241. F f;
  242. std::cout << "without random access " << call_fused(f,res) << std::endl;
  243. total += res;
  244. }
  245. {
  246. boost::lightweight_forward_adapter< boost::fusion::unfused<F> > f;
  247. std::cout << "lightweight_forward_adapter< unfused<F> > " << call_unfused(f,res) << std::endl;
  248. total += res;
  249. }
  250. {
  251. boost::forward_adapter< boost::fusion::unfused<F> > f;
  252. std::cout << "forward_adapter< unfused<F> > " << call_unfused(f,res) << std::endl;
  253. total += res;
  254. }
  255. std::cout << std::endl << "Fused adapters:" << std::endl;
  256. {
  257. unfused_sum f;
  258. std::cout << "U /* an unfused function object */ " << call_unfused(f,res) << std::endl;
  259. total += res;
  260. }
  261. {
  262. boost::fusion::fused_function_object<U> f;
  263. std::cout << "fused_function_object<U> " << call_fused_ra(f,res) << std::endl;
  264. total += res;
  265. }
  266. {
  267. boost::fusion::fused_function_object<U> f;
  268. std::cout << "without random access " << call_fused(f,res) << std::endl;
  269. total += res;
  270. }
  271. {
  272. boost::lightweight_forward_adapter< boost::fusion::unfused< boost::fusion::fused_function_object<U> > > f;
  273. std::cout << "lightweight_forward_adapter< unfused<fused_function_object<U> > >" << call_unfused(f,res) << std::endl;
  274. total += res;
  275. }
  276. {
  277. boost::forward_adapter< boost::fusion::unfused< boost::fusion::fused_function_object<U> > > f;
  278. std::cout << "forward_adapter< unfused<fused_function_object<U> > > " << call_unfused(f,res) << std::endl;
  279. total += res;
  280. }
  281. return total;
  282. }