lmi-commits
[Top][All Lists]
Advanced

[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);
         }



reply via email to

[Prev in Thread] Current Thread [Next in Thread]