[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] (no subject)
From: |
Greg Chicares |
Subject: |
[lmi-commits] (no subject) |
Date: |
Thu, 23 Jun 2016 16:18:40 +0000 (UTC) |
branch: master
commit 32261b1da0d423a48cff63d7b77b174b658b19b3
Author: Gregory W. Chicares <address@hidden>
Date: Thu Jun 23 03:14:52 2016 +0000
Use values unknowable at compile time in currency timing test
The purpose of this timing test is to indicate, however roughly, how
the currency class might perform in lmi's account-value calculations.
Those calculations involve mostly additive operations on values that
are unknowable at compile time, so similarly unknowable values are
in effect created for this unit test by using 'volatile'.
Care has been taken to avoid overflow. In an intermediate version not
committed, overflow rapidly occurred, and the test seemed to indicate
that floating point is terribly slow, but it actually measured the
speed of arithmetic on infinities.
No particular conclusion about the speed of integer versus floating-
point arithmetic should be drawn from the present test. It is better
to view do_some_arithmetic() as a testing sandbox where experiments
are easily designed. For example, temporarily commenting out the sole
line that requires floating-point math changes the results from this:
double : 2.158e-003 s = 2158439 ns, mean of 100 iterations
amount_type: 9.247e-004 s = 924663 ns, mean of 100 iterations
currency : 9.323e-004 s = 932337 ns, mean of 100 iterations
to this on the same machine:
double : 1.700e-002 s = 17002284 ns, mean of 59 iterations
amount_type: 3.043e-002 s = 30434984 ns, mean of 33 iterations
currency : 7.711e-002 s = 77105835 ns, mean of 13 iterations
Furthermore, the generated code can easily be examined thus:
--quiet currency_test
(gdb) b do_some_arithmetic<currency>
(gdb) r
Breakpoint 1, do_some_arithmetic<currency> (t=...)
(gdb) disas
and compared to corresponding code for native types.
---
currency_test.cpp | 109 ++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 96 insertions(+), 13 deletions(-)
diff --git a/currency_test.cpp b/currency_test.cpp
index 2bb3cbb..b3320f5 100644
--- a/currency_test.cpp
+++ b/currency_test.cpp
@@ -26,6 +26,7 @@
#include "test_tools.hpp"
#include "timer.hpp"
+#include <cmath> // std::floor()
#include <limits>
#include <sstream>
#include <stdexcept>
@@ -35,6 +36,19 @@ class currency_test
public:
static void test();
+ /// An arbitrary amount that is quasi-volatile.
+ ///
+ /// The return type is 'T', not 'T volatile'. Instantiations are
+ /// written so that the value returned cannot be computed at
+ /// compile time and calculations involving it therefore cannot
+ /// be eliminated by optimization.
+ ///
+ /// This function template is a member so that its specialization
+ /// for class currency can call a private constructor.
+
+ template<typename T>
+ static T arbitrary_amount();
+
private:
static void test_ctors();
static void test_accessors();
@@ -177,22 +191,91 @@ void currency_test::test_streams()
#undef TEST_ROUNDTRIP
}
+template<>
+double currency_test::arbitrary_amount<double>()
+{
+ double volatile z(1.23);
+ return z;
+}
+
+template<>
+currency::amount_type currency_test::arbitrary_amount<currency::amount_type>()
+{
+ currency::amount_type volatile z(123);
+ return z;
+}
+
+/// An arbitrary currency amount that is quasi-volatile.
+///
+/// The local currency::amount_type variable is volatile, but the
+/// currency object returned is not volatile. It can't be, because
+/// class currency is not "volatile-correct", and there's no present
+/// need to make it so.
+///
+/// However, the currency value represented by the object returned is
+/// "volatile" in the sense that the compiler cannot presume to know
+/// it, so it can't be precomputed at compile time, and calculations
+/// involving it cannot be optimized into oblivion.
+
+template<>
+currency currency_test::arbitrary_amount<currency>()
+{
+ currency::amount_type volatile z(123);
+ return currency(z);
+}
+
+template<typename T>
+inline double convert_to_double(T t)
+{
+ return t;
+}
+
+template<>
+inline double convert_to_double(currency c)
+{
+ return c.value();
+}
+
+template<typename T>
+inline T convert_from_double(double d)
+{
+ return d;
+}
+
+template<>
+inline currency convert_from_double<currency>(double d)
+{
+ return currency::from_value(d);
+}
+
template<typename T>
void do_some_arithmetic(T t)
{
- T u(t);
- t += u;
- t += t;
- t -= u;
- t = t - u;
- u = t;
- T volatile v(t);
+ T a(currency_test::arbitrary_amount<T>());
+ T b(currency_test::arbitrary_amount<T>());
+ T c(currency_test::arbitrary_amount<T>());
+ T d(currency_test::arbitrary_amount<T>());
+ T e(currency_test::arbitrary_amount<T>());
+ T f(currency_test::arbitrary_amount<T>());
+
+ for(int j = 0; j < 1000; ++j)
+ {
+ T u(a + b);
+ t += u;
+ u += u;
+ t += u - c + d - e;
+ u += t - f;
+ u = convert_from_double<T>(std::floor(convert_to_double(u) * 1.03));
+ T volatile v(u);
+ }
+
+ T volatile w(t);
}
void mete_double()
{
- double d(1.23);
- for(int j = 0; j < 1000000; ++j)
+ double d(12345.67);
+ for(int j = 0; j < 1000; ++j)
{
do_some_arithmetic(d);
}
@@ -200,8 +283,8 @@ void mete_double()
void mete_amount_type()
{
- currency::amount_type a(123);
- for(int j = 0; j < 1000000; ++j)
+ currency::amount_type a(1234567);
+ for(int j = 0; j < 1000; ++j)
{
do_some_arithmetic(a);
}
@@ -209,8 +292,8 @@ void mete_amount_type()
void mete_currency()
{
- currency c(1, 23);
- for(int j = 0; j < 1000000; ++j)
+ currency c(12345, 67);
+ for(int j = 0; j < 1000; ++j)
{
do_some_arithmetic(c);
}