|
Re: Fusion-ifying proto parse trees: msg#00035parsers.spirit.devel
Joel de Guzman wrote: Joel de Guzman wrote: Hi again, I'm befuddled. To get a deterministic result from the accumulator, I simply placed an un-timed for_each_s call at the top and printed the result: template<typename T> double time_for_each_s(T const &t) { int i = 0; boost::fusion::for_each_s(t, accumulator(i)); std::cout << i << std::endl; ... Now, I get (VC7.1): Short test ... 80 80 80 Fusion list time : 4.64916e-009 Non-segmented proto time : 5.00679e-009 Segmented proto time : 4.88758e-009 Long test ... 480 480 480 Fusion list time : 1.06215e-007 Non-segmented proto time : 6.11305e-007 Segmented proto time : 1.60217e-007 I can't help but think that the VC7.1 optimizer is playing some crazy tricks on us and giving us skewed results. See attached. Can someone explain what's happening? Also, is it a good idea to get the least timed value? result = (std::min)(run, result); In that case, we will not get the averaging effect when we simply accumulate the result: result += run; ... If done this way, we get yet different results. Oh my... benchmarking is such a black art! Regards, -- Joel de Guzman http://www.boost-consulting.com http://spirit.sf.net /*============================================================================= Copyright (c) 2006 Eric Niebler Use, modification and distribution is 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) ==============================================================================*/ #define BOOST_PROTO_FUSION_V2 #define FUSION_MAX_LIST_SIZE 25 #define FUSION_MAX_VECTOR_SIZE 25 #ifdef _MSC_VER // inline aggressively # pragma inline_recursion(on) // turn on inline recursion # pragma inline_depth(255) // max inline depth #endif #include <iostream> #include <boost/timer.hpp> #include <boost/fusion/sequence.hpp> #include <boost/xpressive/proto/fusion.hpp> #include <boost/fusion/sequence/container/list.hpp> #include <boost/fusion/sequence/container/vector.hpp> #include "./for_each_s.hpp" #include "./segmented_proto.hpp" #define THE_SEQUENCE list //~ #define THE_SEQUENCE vector namespace test { using boost::proto::lit; using boost::proto::unary_op; using boost::proto::noop_tag; using boost::proto::arg; struct accumulator { accumulator(int &i_) : i(i_) {} template<typename T> void operator()(T const &t) const { this->i += arg(t); } int &i; }; int const REPEAT_COUNT = 10; template<typename T> double time_for_each_s(T const &t) { int i = 0; boost::fusion::for_each_s(t, accumulator(i)); std::cout << i << std::endl; boost::timer tim; long long iter = 65536; long long counter, repeats; double result = 0; double run; do { tim.restart(); for(counter = 0; counter < iter; ++counter) { boost::fusion::for_each_s(t, accumulator(i)); } result = tim.elapsed(); iter *= 2; } while(result < 0.5); 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) { boost::fusion::for_each_s(t, accumulator(i)); } run = tim.elapsed(); result = (std::min)(run, result); } return result / iter; } #define EXPR1 (lit(3) >> 42) >> (lit(6) >> 29) #define EXPR2 EXPR1 >> EXPR1 >> EXPR1 >> EXPR1 >> EXPR1 >> EXPR1 void test_short() { typedef unary_op<int, noop_tag> T; boost::fusion::THE_SEQUENCE<T,T,T,T> const l( lit(3),lit(42),lit(6),lit(29)); double list_time = time_for_each_s( l ); double non_segmented_time = time_for_each_s( EXPR1 ); double segmented_time = time_for_each_s( make_segmented_view( EXPR1 ) ); std::cout << "Fusion list time : " << list_time << std::endl; std::cout << "Non-segmented proto time : " << non_segmented_time << std::endl; std::cout << "Segmented proto time : " << segmented_time << std::endl; } void test_long() { typedef unary_op<int, noop_tag> T; boost::fusion::THE_SEQUENCE<T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T,T> const l( lit(3),lit(42),lit(6),lit(29) ,lit(3),lit(42),lit(6),lit(29) ,lit(3),lit(42),lit(6),lit(29) ,lit(3),lit(42),lit(6),lit(29) ,lit(3),lit(42),lit(6),lit(29) ,lit(3),lit(42),lit(6),lit(29)); double list_time = time_for_each_s( l ); double non_segmented_time = time_for_each_s( EXPR2 ); double segmented_time = time_for_each_s( make_segmented_view( EXPR2 ) ); std::cout << "Fusion list time : " << list_time << std::endl; std::cout << "Non-segmented proto time : " << non_segmented_time << std::endl; std::cout << "Segmented proto time : " << segmented_time << std::endl; } } int main() { std::cout << "Short test ... \n"; test::test_short(); std::cout << "Long test ... \n"; test::test_long(); return 0; } |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | Re: further thoughts on adaptive parse algorithms: 00035, Tobias Schwinger |
|---|---|
| Next by Date: | Re: Fusion-ifying proto parse trees: 00035, Eric Niebler |
| Previous by Thread: | Re: Fusion-ifying proto parse treesi: 00035, Joel de Guzman |
| Next by Thread: | Re: Fusion-ifying proto parse trees: 00035, Eric Niebler |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |