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