• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 2001-2011 Joel de Guzman
3     Copyright (c) 2005-2006 Dan Marsden
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ==============================================================================*/
8 #include <boost/array.hpp>
9 #include <boost/timer.hpp>
10 
11 #include <boost/fusion/algorithm/iteration/accumulate.hpp>
12 #include <boost/fusion/algorithm/transformation/transform.hpp>
13 #include <boost/fusion/container/vector.hpp>
14 #include <boost/fusion/algorithm/transformation/zip.hpp>
15 #include <boost/fusion/sequence/intrinsic/at.hpp>
16 #include <boost/fusion/adapted/array.hpp>
17 
18 #include <boost/type_traits/remove_reference.hpp>
19 
20 #include <algorithm>
21 #include <numeric>
22 #include <functional>
23 #include <iostream>
24 #include <cmath>
25 #include <limits>
26 
27 #ifdef _MSC_VER
28 // inline aggressively
29 # pragma inline_recursion(on) // turn on inline recursion
30 # pragma inline_depth(255)    // max inline depth
31 #endif
32 
33 int const REPEAT_COUNT = 10;
34 
35 double const duration = 0.5;
36 
37 namespace
38 {
39     template<int N>
time_for_std_accumulate(int & j)40     double time_for_std_accumulate(int& j)
41     {
42         boost::timer tim;
43         int i = 0;
44         long long iter = 65536;
45         long long counter, repeats;
46         double result = (std::numeric_limits<double>::max)();
47         double runtime = 0;
48         double run;
49         boost::array<int, N> arr;
50         std::generate(arr.begin(), arr.end(), rand);
51         do
52         {
53             tim.restart();
54             for(counter = 0; counter < iter; ++counter)
55             {
56                 i = std::accumulate(arr.begin(), arr.end(), 0);
57                 static_cast<void>(i);
58             }
59             runtime = tim.elapsed();
60             iter *= 2;
61         } while(runtime < duration);
62         iter /= 2;
63 
64         // repeat test and report least value for consistency:
65         for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
66         {
67             tim.restart();
68             for(counter = 0; counter < iter; ++counter)
69             {
70                 i = std::accumulate(arr.begin(), arr.end(), 0);
71                 j += i;
72             }
73             run = tim.elapsed();
74             result = (std::min)(run, result);
75         }
76         std::cout << i << std::endl;
77         return result / iter;
78     }
79 
80     struct poly_add
81     {
82         template<typename Sig>
83         struct result;
84 
85         template<typename Lhs, typename Rhs>
86         struct result<poly_add(Lhs,Rhs)>
87             : boost::remove_reference<Lhs>
88         {};
89 
90         template<typename Lhs, typename Rhs>
operator ()__anonb2d8de380111::poly_add91         Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
92         {
93             return lhs + rhs;
94         }
95     };
96 
97     struct poly_mult
98     {
99         template<typename Sig>
100         struct result;
101 
102         template<typename Lhs, typename Rhs>
103         struct result<poly_mult(Lhs, Rhs)>
104             : boost::remove_reference<Lhs>
105         {};
106 
107         template<typename Lhs, typename Rhs>
operator ()__anonb2d8de380111::poly_mult108         Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
109         {
110             return lhs * rhs;
111         }
112     };
113 
114     template<int N>
time_for_fusion_accumulate(int & j)115     double time_for_fusion_accumulate(int& j)
116     {
117         boost::timer tim;
118         int i = 0;
119         long long iter = 65536;
120         long long counter, repeats;
121         double result = (std::numeric_limits<double>::max)();
122         double runtime = 0;
123         double run;
124         boost::array<int, N> arr;
125         std::generate(arr.begin(), arr.end(), rand);
126         do
127         {
128             tim.restart();
129             for(counter = 0; counter < iter; ++counter)
130             {
131                 i = boost::fusion::accumulate(arr, 0, poly_add());
132                 static_cast<void>(i);
133             }
134             runtime = tim.elapsed();
135             iter *= 2;
136         } while(runtime < duration);
137         iter /= 2;
138 
139         std::cout << iter << " iterations" << std::endl;
140 
141         // repeat test and report least value for consistency:
142         for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
143         {
144             tim.restart();
145             for(counter = 0; counter < iter; ++counter)
146             {
147                 i = boost::fusion::accumulate(arr, 0, poly_add());
148                 j += i;
149             }
150             run = tim.elapsed();
151             result = (std::min)(run, result);
152             std::cout << ".";
153             std::cout.flush();
154         }
155         std::cout << i << std::endl;
156         return result / iter;
157     }
158 
159 #if 0
160     template<int N>
161     double time_for_std_inner_product(int& j)
162     {
163         boost::timer tim;
164         int i = 0;
165         long long iter = 65536;
166         long long counter, repeats;
167         double result = (std::numeric_limits<double>::max)();
168         double runtime = 0;
169         double run;
170         boost::array<int, N> arr1;
171         boost::array<int, N> arr2;
172         std::generate(arr1.begin(), arr1.end(), rand);
173         std::generate(arr2.begin(), arr2.end(), rand);
174         do
175         {
176             tim.restart();
177             for(counter = 0; counter < iter; ++counter)
178             {
179                 i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
180                 static_cast<void>(i);
181             }
182             runtime = tim.elapsed();
183             iter *= 2;
184         } while(runtime < duration);
185         iter /= 2;
186 
187         // repeat test and report least value for consistency:
188         for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
189         {
190             tim.restart();
191             for(counter = 0; counter < iter; ++counter)
192             {
193                 i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
194                 j += i;
195             }
196             run = tim.elapsed();
197             result = (std::min)(run, result);
198         }
199         std::cout << i << std::endl;
200         return result / iter;
201     }
202 
203     template<int N>
204     double time_for_fusion_inner_product(int& j)
205     {
206         boost::timer tim;
207         int i = 0;
208         long long iter = 65536;
209         long long counter, repeats;
210         double result = (std::numeric_limits<double>::max)();
211         double runtime = 0;
212         double run;
213         boost::array<int, N> arr1;
214         boost::array<int, N> arr2;
215         std::generate(arr1.begin(), arr1.end(), rand);
216         std::generate(arr2.begin(), arr2.end(), rand);
217         do
218         {
219             tim.restart();
220             for(counter = 0; counter < iter; ++counter)
221             {
222                 i = boost::fusion::accumulate(
223                     boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add());
224                 static_cast<void>(i);
225             }
226             runtime = tim.elapsed();
227             iter *= 2;
228         } while(runtime < duration);
229         iter /= 2;
230 
231         // repeat test and report least value for consistency:
232         for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
233         {
234             tim.restart();
235             for(counter = 0; counter < iter; ++counter)
236             {
237                 i = boost::fusion::accumulate(
238                     boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add());
239                 j += i;
240             }
241             run = tim.elapsed();
242             result = (std::min)(run, result);
243         }
244         std::cout << i << std::endl;
245         return result / iter;
246     }
247 
248     struct poly_combine
249     {
250         template<typename Lhs, typename Rhs>
251         struct result
252         {
253             typedef Lhs type;
254         };
255 
256         template<typename Lhs, typename Rhs>
257         typename result<Lhs,Rhs>::type
258         operator()(const Lhs& lhs, const Rhs& rhs) const
259         {
260             return lhs + boost::fusion::at_c<0>(rhs) * boost::fusion::at_c<1>(rhs);
261         }
262     };
263 
264     template<int N>
265     double time_for_fusion_inner_product2(int& j)
266     {
267         boost::timer tim;
268         int i = 0;
269         long long iter = 65536;
270         long long counter, repeats;
271         double result = (std::numeric_limits<double>::max)();
272         double runtime = 0;
273         double run;
274         boost::array<int, N> arr1;
275         boost::array<int, N> arr2;
276         std::generate(arr1.begin(), arr1.end(), rand);
277         std::generate(arr2.begin(), arr2.end(), rand);
278         do
279         {
280             tim.restart();
281             for(counter = 0; counter < iter; ++counter)
282             {
283                 i = boost::fusion::accumulate(
284                     boost::fusion::zip(arr1, arr2), 0, poly_combine());
285                 static_cast<void>(i);
286             }
287             runtime = tim.elapsed();
288             iter *= 2;
289         } while(runtime < duration);
290         iter /= 2;
291 
292         std::cout << iter << " iterations" << std::endl;
293 
294         // repeat test and report least value for consistency:
295         for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
296         {
297             tim.restart();
298             for(counter = 0; counter < iter; ++counter)
299             {
300                 i = boost::fusion::accumulate(
301                     boost::fusion::zip(arr1, arr2), 0, poly_combine());
302                 j += i;
303             }
304             run = tim.elapsed();
305             result = (std::min)(run, result);
306         }
307         std::cout << i << std::endl;
308         return result / iter;
309     }
310 #endif
311 }
312 
main()313 int main()
314 {
315     int total = 0;
316     int res;
317     std::cout << "short accumulate std test " << time_for_std_accumulate<8>(res) << std::endl;
318     total += res;
319     std::cout << "short accumulate fusion test " << time_for_fusion_accumulate<8>(res) << std::endl;
320     total += res;
321 
322     std::cout << "medium accumulate std test " << time_for_std_accumulate<64>(res) << std::endl;
323     total += res;
324     std::cout << "medium accumulate fusion test " << time_for_fusion_accumulate<64>(res) << std::endl;
325     total += res;
326 
327     std::cout << "long accumulate std test " << time_for_std_accumulate<128>(res) << std::endl;
328     total += res;
329     std::cout << "long accumulate fusion test " << time_for_fusion_accumulate<128>(res) << std::endl;
330     total += res;
331 
332 #if 0
333     std::cout << "short inner_product std test " << time_for_std_inner_product<8>(res) << std::endl;
334     total += res;
335     std::cout << "short inner_product fusion test " << time_for_fusion_inner_product<8>(res) << std::endl;
336     total += res;
337     std::cout << "short inner_product fusion 2 test " << time_for_fusion_inner_product2<8>(res) << std::endl;
338     total += res;
339 
340     std::cout << "medium inner_product std test " << time_for_std_inner_product<64>(res) << std::endl;
341     total += res;
342     std::cout << "medium inner_product fusion test " << time_for_fusion_inner_product<64>(res) << std::endl;
343     total += res;
344     std::cout << "medium inner_product fusion 2 test " << time_for_fusion_inner_product2<64>(res) << std::endl;
345     total += res;
346 
347 
348     std::cout << "long inner_product std test " << time_for_std_inner_product<128>(res) << std::endl;
349     total += res;
350     std::cout << "long inner_product fusion test " << time_for_fusion_inner_product<128>(res) << std::endl;
351     total += res;
352     std::cout << "long inner_product fusion 2 test " << time_for_fusion_inner_product2<128>(res) << std::endl;
353     total += res;
354 #endif
355 
356     return total;
357 }
358