Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r55067 - trunk/libs/spirit/benchmarks
From: joel_at_[hidden]
Date: 2009-07-21 12:40:19


Author: djowel
Date: 2009-07-21 12:40:19 EDT (Tue, 21 Jul 2009)
New Revision: 55067
URL: http://svn.boost.org/trac/boost/changeset/55067

Log:
standardized benchmark scaffolding
Added:
   trunk/libs/spirit/benchmarks/boiler_plate.cpp (contents, props changed)
   trunk/libs/spirit/benchmarks/measure.hpp (contents, props changed)

Added: trunk/libs/spirit/benchmarks/boiler_plate.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/benchmarks/boiler_plate.cpp 2009-07-21 12:40:19 EDT (Tue, 21 Jul 2009)
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Copyright (c) 2001-2009 Joel de Guzman
+
+ 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 "measure.hpp"
+#include <iostream>
+
+namespace
+{
+ struct f
+ {
+ typedef int type;
+
+ void operator()(int x)
+ {
+ this->val ^= x; // here is where you put code that you want
+ // to benchmark. Make sure it returns something.
+ // Anything.
+ }
+
+ int val; // this is where the value is accumulated
+ };
+}
+
+int main()
+{
+ int result;
+ double base_time;
+ int ret = test::benchmark<f>::test(result, base_time);
+
+ std::cout
+ << "f accumulated result: "
+ << result
+ << std::endl
+ << "f time: "
+ << base_time
+ << std::endl;
+
+ return ret;
+}

Added: trunk/libs/spirit/benchmarks/measure.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/benchmarks/measure.hpp 2009-07-21 12:40:19 EDT (Tue, 21 Jul 2009)
@@ -0,0 +1,121 @@
+// Copyright David Abrahams, Matthias Troyer, Michael Gauckler
+// 2005. 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)
+
+#ifdef _MSC_VER
+// inline aggressively
+# pragma inline_recursion(on) // turn on inline recursion
+# pragma inline_depth(255) // max inline depth
+# define _SECURE_SCL 0
+#endif
+
+#if !defined(LIVE_CODE_TYPE)
+# define LIVE_CODE_TYPE int
+#endif
+
+#include "high_resolution_timer.hpp"
+
+namespace test
+{
+ // This value is required to ensure that a smart compiler's dead
+ // code elimination doesn't optimize away anything we're testing.
+ // We'll use it to compute the return code of the executable to make
+ // sure it's needed.
+ LIVE_CODE_TYPE live_code;
+
+ // Call objects of the given Accumulator type repeatedly with x as
+ // an argument.
+ template <class Accumulator, class Arg>
+ void hammer(Arg const& x, long const repeats)
+ {
+ // Strategy: because the sum in an accumulator after each call
+ // depends on the previous value of the sum, the CPU's pipeline
+ // might be stalled while waiting for the previous addition to
+ // complete. Therefore, we allocate an array of accumulators,
+ // and update them in sequence, so that there's no dependency
+ // between adjacent addition operations.
+ //
+ // Additionally, if there were only one accumulator, the
+ // compiler or CPU might decide to update the value in a
+ // register rather that writing it back to memory. we want each
+ // operation to at least update the L1 cache. *** Note: This
+ // concern is specific to the particular application at which
+ // we're targeting the test. ***
+
+ // This has to be at least as large as the number of
+ // simultaneous accumulations that can be executing in the
+ // compiler pipeline. A safe number here is larger than the
+ // machine's maximum pipeline depth. If you want to test the L2
+ // or L3 cache, or main memory, you can increase the size of
+ // this array. 1024 is an upper limit on the pipeline depth of
+ // current vector machines.
+ const std::size_t number_of_accumulators = 1024;
+ live_code = 0; // reset to zero
+
+ Accumulator a[number_of_accumulators];
+
+ for (long iteration = 0; iteration < repeats; ++iteration)
+ {
+ for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap)
+ {
+ (*ap)(x);
+ }
+ }
+
+ // Accumulate all the partial sums to avoid dead code
+ // elimination.
+ for (Accumulator* ap = a; ap < a + number_of_accumulators; ++ap)
+ {
+ live_code += ap->val;
+ }
+ }
+
+ // Measure the time required to hammer accumulators of the given
+ // type with the argument x.
+ template <class Accumulator, class T>
+ double measure(T const& x, long const repeats)
+ {
+ // Hammer accumulators a couple of times to ensure the
+ // instruction cache is full of our test code, and that we don't
+ // measure the cost of a page fault for accessing the data page
+ // containing the memory where the accumulators will be
+ // allocated
+ hammer<Accumulator>(x, repeats);
+ hammer<Accumulator>(x, repeats);
+
+ // Now start a timer
+ util::high_resolution_timer time;
+ hammer<Accumulator>(x, repeats); // This time, we'll measure
+ return time.elapsed() / repeats; // return the time of one iteration
+ }
+
+ template <typename Accumulator, int Repeats = 100>
+ struct benchmark
+ {
+ static int test(typename Accumulator::type& result, double& base_time)
+ {
+ std::cout.setf(std::ios::scientific);
+
+ // first decide how many repetitions to measure
+ long repeats = Repeats;
+ double measured = 0;
+ while (measured < 2.0 && repeats <= 10000000)
+ {
+ repeats *= 10;
+ util::high_resolution_timer time;
+ test::hammer<Accumulator>(0, repeats);
+ measured = time.elapsed();
+ }
+
+ test::measure<Accumulator>(1, 1);
+ result = test::live_code;
+ base_time = test::measure<Accumulator>(1, repeats);
+
+ // This is ultimately responsible for preventing all the test code
+ // from being optimized away. Change this to return 0 and you
+ // unplug the whole test's life support system.
+ return test::live_code != 0;
+ }
+ };
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk