summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/fusion/example/performance/measure.hpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/fusion/example/performance/measure.hpp
parentInitial commit. (diff)
downloadceph-upstream.tar.xz
ceph-upstream.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/fusion/example/performance/measure.hpp')
-rw-r--r--src/boost/libs/fusion/example/performance/measure.hpp85
1 files changed, 85 insertions, 0 deletions
diff --git a/src/boost/libs/fusion/example/performance/measure.hpp b/src/boost/libs/fusion/example/performance/measure.hpp
new file mode 100644
index 00000000..72cd71ba
--- /dev/null
+++ b/src/boost/libs/fusion/example/performance/measure.hpp
@@ -0,0 +1,85 @@
+// 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)
+
+#if !defined(LIVE_CODE_TYPE)
+# define LIVE_CODE_TYPE int
+#endif
+
+#include <boost/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->sum;
+ }
+ }
+
+ // 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
+ boost::timer time;
+ hammer<Accumulator>(x, repeats); // This time, we'll measure
+ return time.elapsed() / repeats; // return the time of one iteration
+ }
+}