From 50e7b2c933140ea3d60c2d4e5c63ffcf6c4acdea Mon Sep 17 00:00:00 2001 From: Tobias Schwinger Date: Thu, 15 Feb 2007 23:20:27 +0000 Subject: [PATCH] adds benchmark for functional components - draft version [SVN r36962] --- example/performance/Jamfile | 2 + example/performance/functional.cpp | 328 +++++++++++++++++++++++++++++ 2 files changed, 330 insertions(+) create mode 100644 example/performance/functional.cpp diff --git a/example/performance/Jamfile b/example/performance/Jamfile index 53d5ec5f..3b8c8ffc 100644 --- a/example/performance/Jamfile +++ b/example/performance/Jamfile @@ -16,3 +16,5 @@ exe inner_product2 : inner_product2.cpp ; exe sequence_efficiency : sequence_efficiency.cpp ; +exe functional : functional.cpp ; + diff --git a/example/performance/functional.cpp b/example/performance/functional.cpp new file mode 100644 index 00000000..a4d5056b --- /dev/null +++ b/example/performance/functional.cpp @@ -0,0 +1,328 @@ +/*============================================================================= + Copyright (c) 2001-2006 Joel de Guzman + Copyright (c) 2006-2007 Tobias Schwinger + + Use modification and distribution are subject to 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 = 3; + +double const duration = 0.125; + + +namespace +{ + struct fused_sum + { + template + int operator()(Seq const & seq) const + { + int state = 0; + return boost::fusion::fold(seq, state, sum_op()); + } + + template struct result + { + typedef int type; + }; + + private: + + struct sum_op + { + template + int operator()(T const & elem, int value) const + { + return value + sizeof(T) * elem; + } + + template + int operator()(T & elem, int value) const + { + elem += sizeof(T); + return value; + } + + template struct result + { + typedef int type; + }; + }; + }; + + struct unfused_sum + { + inline int operator()() const + { + return 0; + } + template + inline int operator()(T0 const & a0) const + { + return a0; + } + template + inline int operator()(T0 const & a0, T1 const & a1) const + { + return a0 + a1; + } + template + inline int operator()(T0 const & a0, T1 const & a1, T2 a2) const + { + return a0 + a1 + a2; + } + template + inline int operator()(T0 const & a0, T1 const & a1, T2 const & a2, T3 const & a3) const + { + return a0 + a1 + a2 + a3; + } + + template + struct result + { + typedef int type; + }; + }; + + template + double call_unfused(F const & func, int & j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits::max)(); + double runtime = 0; + double run; + do + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i += func(); + i += func(0); + i += func(0,1); + i += func(0,1,2); + i += func(0,1,2,3); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = func(); j += i; + i = func(0); j += i; + i = func(0,1); j += i; + i = func(0,1,2); j += i; + i = func(0,1,2,3); j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + return result / iter; + } + + template + double call_fused_ra(F const & func, int & j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits::max)(); + double runtime = 0; + double run; + do + { + boost::fusion::vector<> v0; + boost::fusion::vector v1(0); + boost::fusion::vector v2(0,1); + boost::fusion::vector v3(0,1,2); + boost::fusion::vector v4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i += func(v0); + i += func(v1); + i += func(v2); + i += func(v3); + i += func(v4); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + boost::fusion::vector<> v0; + boost::fusion::vector v1(0); + boost::fusion::vector v2(0,1); + boost::fusion::vector v3(0,1,2); + boost::fusion::vector v4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = func(v0); j += i; + i = func(v1); j += i; + i = func(v2); j += i; + i = func(v3); j += i; + i = func(v4); j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + return result / iter; + } + + template + double call_fused(F const & func, int & j) + { + boost::timer tim; + int i = 0; + long long iter = 65536; + long long counter, repeats; + double result = (std::numeric_limits::max)(); + double runtime = 0; + double run; + do + { + boost::fusion::list<> l0; + boost::fusion::list l1(0); + boost::fusion::list l2(0,1); + boost::fusion::list l3(0,1,2); + boost::fusion::list l4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i += func(l0); + i += func(l1); + i += func(l2); + i += func(l3); + i += func(l4); + } + runtime = tim.elapsed(); + iter *= 2; + } while(runtime < duration); + iter /= 2; + + for(repeats = 0; repeats < REPEAT_COUNT; ++repeats) + { + boost::fusion::list<> l0; + boost::fusion::list l1(0); + boost::fusion::list l2(0,1); + boost::fusion::list l3(0,1,2); + boost::fusion::list l4(0,1,2,3); + tim.restart(); + for(counter = 0; counter < iter; ++counter) + { + i = func(l0); j += i; + i = func(l1); j += i; + i = func(l2); j += i; + i = func(l3); j += i; + i = func(l4); j += i; + } + run = tim.elapsed(); + result = (std::min)(run, result); + } + return result / iter; + } +} + +int main() +{ + int total = 0; + int res; + typedef fused_sum F; + typedef unfused_sum U; + + std::cout << "Compiler: " << BOOST_COMPILER << std::endl; + std::cout << std::endl << "Unfused adapters:" << std::endl; + { + F f; + std::cout << "F /* a fused function object */ " << call_fused_ra(f,res) << std::endl; + total += res; + } + { + F f; + std::cout << "without random access " << call_fused(f,res) << std::endl; + total += res; + } + { + typedef boost::fusion::vector s; + boost::fusion::unfused_typed f; + std::cout << "unfused_typed " << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::fusion::unfused_rvalue_args f; + std::cout << "unfused_rvalue_args " << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::fusion::unfused_generic f; + std::cout << "unfused_generic " << call_unfused(f,res) << std::endl; + total += res; + } + std::cout << std::endl << "Fused adapters:" << std::endl; + { + unfused_sum f; + std::cout << "U /* an unfused function object */ " << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::fusion::fused_function_object f; + std::cout << "fused_function_object " << call_fused_ra(f,res) << std::endl; + total += res; + } + { + boost::fusion::fused_function_object f; + std::cout << "without random access " << call_fused(f,res) << std::endl; + total += res; + } + std::cout << std::endl << "Loopback:" << std::endl; + { + typedef boost::fusion::vector s; + boost::fusion::unfused_typed< boost::fusion::fused_function_object, s > f; + std::cout << "unfused_typed,s > " << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::fusion::unfused_rvalue_args< boost::fusion::fused_function_object > f; + std::cout << "unfused_rvalue_args > " << call_unfused(f,res) << std::endl; + total += res; + } + { + boost::fusion::unfused_generic< boost::fusion::fused_function_object > f; + std::cout << "unfused_generic > " << call_unfused(f,res) << std::endl; + total += res; + } + return total; +}