123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- /*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
- Copyright (c) 2005-2006 Dan Marsden
- Distributed under the Boost Software License, Version 1.0. (See accompanying
- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- ==============================================================================*/
- #include <boost/array.hpp>
- #include <boost/timer.hpp>
- #include <boost/fusion/algorithm/iteration/accumulate.hpp>
- #include <boost/fusion/algorithm/transformation/transform.hpp>
- #include <boost/fusion/container/vector.hpp>
- #include <boost/fusion/algorithm/transformation/zip.hpp>
- #include <boost/fusion/sequence/intrinsic/at.hpp>
- #include <boost/fusion/adapted/array.hpp>
- #include <boost/type_traits/remove_reference.hpp>
- #include <algorithm>
- #include <numeric>
- #include <functional>
- #include <iostream>
- #include <cmath>
- #include <limits>
- #ifdef _MSC_VER
- // inline aggressively
- # pragma inline_recursion(on) // turn on inline recursion
- # pragma inline_depth(255) // max inline depth
- #endif
- int const REPEAT_COUNT = 10;
- double const duration = 0.5;
- namespace
- {
- template<int N>
- double time_for_std_accumulate(int& j)
- {
- boost::timer tim;
- int i = 0;
- long long iter = 65536;
- long long counter, repeats;
- double result = (std::numeric_limits<double>::max)();
- double runtime = 0;
- double run;
- boost::array<int, N> arr;
- std::generate(arr.begin(), arr.end(), rand);
- do
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = std::accumulate(arr.begin(), arr.end(), 0);
- static_cast<void>(i);
- }
- runtime = tim.elapsed();
- iter *= 2;
- } while(runtime < duration);
- iter /= 2;
- // repeat test and report least value for consistency:
- for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = std::accumulate(arr.begin(), arr.end(), 0);
- j += i;
- }
- run = tim.elapsed();
- result = (std::min)(run, result);
- }
- std::cout << i << std::endl;
- return result / iter;
- }
- struct poly_add
- {
- template<typename Sig>
- struct result;
- template<typename Lhs, typename Rhs>
- struct result<poly_add(Lhs,Rhs)>
- : boost::remove_reference<Lhs>
- {};
- template<typename Lhs, typename Rhs>
- Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
- {
- return lhs + rhs;
- }
- };
- struct poly_mult
- {
- template<typename Sig>
- struct result;
- template<typename Lhs, typename Rhs>
- struct result<poly_mult(Lhs, Rhs)>
- : boost::remove_reference<Lhs>
- {};
- template<typename Lhs, typename Rhs>
- Lhs operator()(const Lhs& lhs, const Rhs& rhs) const
- {
- return lhs * rhs;
- }
- };
- template<int N>
- double time_for_fusion_accumulate(int& j)
- {
- boost::timer tim;
- int i = 0;
- long long iter = 65536;
- long long counter, repeats;
- double result = (std::numeric_limits<double>::max)();
- double runtime = 0;
- double run;
- boost::array<int, N> arr;
- std::generate(arr.begin(), arr.end(), rand);
- do
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = boost::fusion::accumulate(arr, 0, poly_add());
- static_cast<void>(i);
- }
- runtime = tim.elapsed();
- iter *= 2;
- } while(runtime < duration);
- iter /= 2;
- std::cout << iter << " iterations" << std::endl;
- // repeat test and report least value for consistency:
- for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = boost::fusion::accumulate(arr, 0, poly_add());
- j += i;
- }
- run = tim.elapsed();
- result = (std::min)(run, result);
- std::cout << ".";
- std::cout.flush();
- }
- std::cout << i << std::endl;
- return result / iter;
- }
- #if 0
- template<int N>
- double time_for_std_inner_product(int& j)
- {
- boost::timer tim;
- int i = 0;
- long long iter = 65536;
- long long counter, repeats;
- double result = (std::numeric_limits<double>::max)();
- double runtime = 0;
- double run;
- boost::array<int, N> arr1;
- boost::array<int, N> arr2;
- std::generate(arr1.begin(), arr1.end(), rand);
- std::generate(arr2.begin(), arr2.end(), rand);
- do
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
- static_cast<void>(i);
- }
- runtime = tim.elapsed();
- iter *= 2;
- } while(runtime < duration);
- iter /= 2;
- // repeat test and report least value for consistency:
- for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = std::inner_product(arr1.begin(), arr1.end(), arr2.begin(), 0);
- j += i;
- }
- run = tim.elapsed();
- result = (std::min)(run, result);
- }
- std::cout << i << std::endl;
- return result / iter;
- }
- template<int N>
- double time_for_fusion_inner_product(int& j)
- {
- boost::timer tim;
- int i = 0;
- long long iter = 65536;
- long long counter, repeats;
- double result = (std::numeric_limits<double>::max)();
- double runtime = 0;
- double run;
- boost::array<int, N> arr1;
- boost::array<int, N> arr2;
- std::generate(arr1.begin(), arr1.end(), rand);
- std::generate(arr2.begin(), arr2.end(), rand);
- do
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = boost::fusion::accumulate(
- boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add());
- static_cast<void>(i);
- }
- runtime = tim.elapsed();
- iter *= 2;
- } while(runtime < duration);
- iter /= 2;
- // repeat test and report least value for consistency:
- for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = boost::fusion::accumulate(
- boost::fusion::transform(arr1, arr2, poly_mult()), 0, poly_add());
- j += i;
- }
- run = tim.elapsed();
- result = (std::min)(run, result);
- }
- std::cout << i << std::endl;
- return result / iter;
- }
- struct poly_combine
- {
- template<typename Lhs, typename Rhs>
- struct result
- {
- typedef Lhs type;
- };
-
- template<typename Lhs, typename Rhs>
- typename result<Lhs,Rhs>::type
- operator()(const Lhs& lhs, const Rhs& rhs) const
- {
- return lhs + boost::fusion::at_c<0>(rhs) * boost::fusion::at_c<1>(rhs);
- }
- };
- template<int N>
- double time_for_fusion_inner_product2(int& j)
- {
- boost::timer tim;
- int i = 0;
- long long iter = 65536;
- long long counter, repeats;
- double result = (std::numeric_limits<double>::max)();
- double runtime = 0;
- double run;
- boost::array<int, N> arr1;
- boost::array<int, N> arr2;
- std::generate(arr1.begin(), arr1.end(), rand);
- std::generate(arr2.begin(), arr2.end(), rand);
- do
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = boost::fusion::accumulate(
- boost::fusion::zip(arr1, arr2), 0, poly_combine());
- static_cast<void>(i);
- }
- runtime = tim.elapsed();
- iter *= 2;
- } while(runtime < duration);
- iter /= 2;
- std::cout << iter << " iterations" << std::endl;
- // repeat test and report least value for consistency:
- for(repeats = 0; repeats < REPEAT_COUNT; ++repeats)
- {
- tim.restart();
- for(counter = 0; counter < iter; ++counter)
- {
- i = boost::fusion::accumulate(
- boost::fusion::zip(arr1, arr2), 0, poly_combine());
- j += i;
- }
- run = tim.elapsed();
- result = (std::min)(run, result);
- }
- std::cout << i << std::endl;
- return result / iter;
- }
- #endif
- }
- int main()
- {
- int total = 0;
- int res;
- std::cout << "short accumulate std test " << time_for_std_accumulate<8>(res) << std::endl;
- total += res;
- std::cout << "short accumulate fusion test " << time_for_fusion_accumulate<8>(res) << std::endl;
- total += res;
- std::cout << "medium accumulate std test " << time_for_std_accumulate<64>(res) << std::endl;
- total += res;
- std::cout << "medium accumulate fusion test " << time_for_fusion_accumulate<64>(res) << std::endl;
- total += res;
- std::cout << "long accumulate std test " << time_for_std_accumulate<128>(res) << std::endl;
- total += res;
- std::cout << "long accumulate fusion test " << time_for_fusion_accumulate<128>(res) << std::endl;
- total += res;
- #if 0
- std::cout << "short inner_product std test " << time_for_std_inner_product<8>(res) << std::endl;
- total += res;
- std::cout << "short inner_product fusion test " << time_for_fusion_inner_product<8>(res) << std::endl;
- total += res;
- std::cout << "short inner_product fusion 2 test " << time_for_fusion_inner_product2<8>(res) << std::endl;
- total += res;
- std::cout << "medium inner_product std test " << time_for_std_inner_product<64>(res) << std::endl;
- total += res;
- std::cout << "medium inner_product fusion test " << time_for_fusion_inner_product<64>(res) << std::endl;
- total += res;
- std::cout << "medium inner_product fusion 2 test " << time_for_fusion_inner_product2<64>(res) << std::endl;
- total += res;
- std::cout << "long inner_product std test " << time_for_std_inner_product<128>(res) << std::endl;
- total += res;
- std::cout << "long inner_product fusion test " << time_for_fusion_inner_product<128>(res) << std::endl;
- total += res;
- std::cout << "long inner_product fusion 2 test " << time_for_fusion_inner_product2<128>(res) << std::endl;
- total += res;
- #endif
- return total;
- }
|