[kstars/skypoint_optimization_attempts] kstars: Profiling Code: Count trigonometric calls on dms, and profile them.
Akarsh Simha
akarsh at kde.org
Sun Sep 25 12:27:36 UTC 2016
Git commit a6782b5aa76ebeebbd328861504cb761e892ae97 by Akarsh Simha.
Committed on 24/09/2016 at 10:27.
Pushed by asimha into branch 'skypoint_optimization_attempts'.
Profiling Code: Count trigonometric calls on dms, and profile them.
Profiling code I: fraction of dms objects that have sin/cos called
This is profiling code to find out what fraction of dms objects hae
sin/cos called on them. This is useful to figure out if it makes sense
to cache sin/cos values in the constructor itself. It turns out that
this might not be a wise decision since the profiling results in at
least some context says that it can be as low as 25%:
[24 0:15:36 D] KStars::~KStars (186) - Constructed 68504224 dms
objects, of which 17021346 had trigonometric functions called on
them = 24.8471 %
In a different run, it was a bit higher, but still less than 50%.
This suggests that it might not be wise to compute and cache sin / cos
values upon construction
Profiling code II: determine how many trig calls on dms are redundant
The initial results of this profiling seem to be staggering! If the
simulation clock is running, so we are actually recomputing
coordinates, nearly 50% of trigonometric function calls seem to be
redundant! This might justify caching the values of sine and cosine
upon first computation within dms() itself. This will add a
conditional, which can lead to a potential branch mispredict, and some
extra stuff, so I'd guess ~ 20 CPU cycles; however, it would save an
expensive (~110 CPU cycles) trigonometric function computation almost
50% of the time. Given that a significant fraction (~27% under some
particular conditions) of KStars' time is spent on computing sine and
cosine, it might be well worth it to save these calls.
CCMAIL: kstars-devel at kde.org
M +19 -0 kstars/auxiliary/dms.cpp
M +85 -7 kstars/auxiliary/dms.h
M +9 -0 kstars/kstars.cpp
http://commits.kde.org/kstars/a6782b5aa76ebeebbd328861504cb761e892ae97
diff --git a/kstars/auxiliary/dms.cpp b/kstars/auxiliary/dms.cpp
index bf30535..be1de35 100644
--- a/kstars/auxiliary/dms.cpp
+++ b/kstars/auxiliary/dms.cpp
@@ -23,22 +23,41 @@
#include <cstdlib>
+#ifdef COUNT_DMS_SINCOS_CALLS
+long unsigned dms::dms_constructor_calls = 0;
+long unsigned dms::dms_with_sincos_called = 0;
+long unsigned dms::trig_function_calls = 0;
+long unsigned dms::redundant_trig_function_calls = 0;
+#endif
+
void dms::setD(const int &d, const int &m, const int &s, const int &ms) {
D = (double)abs(d) + ((double)m + ((double)s + (double)ms/1000.)/60.)/60.;
if (d<0) {D = -1.0*D;}
+#ifdef COUNT_DMS_SINCOS_CALLS
+ m_cosDirty = m_sinDirty = true;
+#endif
}
void dms::setH( const double &x ) {
setD( x*15.0 );
+#ifdef COUNT_DMS_SINCOS_CALLS
+ m_cosDirty = m_sinDirty = true;
+#endif
}
void dms::setH(const int &h, const int &m, const int &s, const int &ms) {
D = 15.0*((double)abs(h) + ((double)m + ((double)s + (double)ms/1000.)/60.)/60.);
if (h<0) {D = -1.0*D;}
+#ifdef COUNT_DMS_SINCOS_CALLS
+ m_cosDirty = m_sinDirty = true;
+#endif
}
void dms::setRadians( const double &Rad ) {
setD( Rad/DegToRad );
+#ifdef COUNT_DMS_SINCOS_CALLS
+ m_cosDirty = m_sinDirty = true;
+#endif
}
bool dms::setFromString( const QString &str, bool isDeg ) {
diff --git a/kstars/auxiliary/dms.h b/kstars/auxiliary/dms.h
index 8ff8e8c..28ce633 100644
--- a/kstars/auxiliary/dms.h
+++ b/kstars/auxiliary/dms.h
@@ -25,6 +25,7 @@
#include <cmath>
+#define COUNT_DMS_SINCOS_CALLS true
/** @class dms
* @short An angle, stored as degrees, but expressible in many ways.
@@ -43,7 +44,15 @@
class dms {
public:
/** Default constructor. */
- dms() : D( NaN::d ) {}
+ dms() : D( NaN::d )
+#ifdef COUNT_DMS_SINCOS_CALLS
+ , m_sinCosCalled(false), m_sinDirty( true ), m_cosDirty( true )
+#endif
+ {
+#ifdef COUNT_DMS_SINCOS_CALLS
+ ++dms_constructor_calls;
+#endif
+ }
/** @short Set the floating-point value of the angle according to the four integer arguments.
* @param d degree portion of angle (int). Defaults to zero.
@@ -51,14 +60,30 @@ public:
* @param s arcsecond portion of angle (int). Defaults to zero.
* @param ms arcsecond portion of angle (int). Defaults to zero.
*/
- explicit dms( const int &d, const int &m=0, const int &s=0, const int &ms=0 ) { setD( d, m, s, ms ); }
+ explicit dms( const int &d, const int &m=0, const int &s=0, const int &ms=0 )
+#ifdef COUNT_DMS_SINCOS_CALLS
+ : m_sinCosCalled(false), m_sinDirty( true ), m_cosDirty( true )
+#endif
+ { setD( d, m, s, ms );
+#ifdef COUNT_DMS_SINCOS_CALLS
+ ++dms_constructor_calls;
+#endif
+}
/** @short Construct an angle from a double value.
*
* Creates an angle whose value in Degrees is equal to the argument.
* @param x angle expressed as a floating-point number (in degrees)
*/
- explicit dms( const double &x ) : D(x) {}
+ explicit dms( const double &x ) : D(x)
+#ifdef COUNT_DMS_SINCOS_CALLS
+ , m_sinCosCalled(false), m_sinDirty( true ), m_cosDirty( true )
+#endif
+ {
+#ifdef COUNT_DMS_SINCOS_CALLS
+ ++dms_constructor_calls;
+#endif
+ }
/** @short Construct an angle from a string representation.
*
@@ -73,7 +98,15 @@ public:
* @param isDeg if true, value is in degrees; if false, value is in hours.
* @sa setFromString()
*/
- explicit dms( const QString &s, bool isDeg=true ) { setFromString( s, isDeg ); }
+ explicit dms( const QString &s, bool isDeg=true )
+#ifdef COUNT_DMS_SINCOS_CALLS
+ : m_sinCosCalled(false), m_sinDirty( true ), m_cosDirty( true )
+#endif
+ { setFromString( s, isDeg );
+#ifdef COUNT_DMS_SINCOS_CALLS
+ ++dms_constructor_calls;
+#endif
+ }
/** @return integer degrees portion of the angle
*/
@@ -128,7 +161,11 @@ public:
/** Sets floating-point value of angle, in degrees.
* @param x new angle (double)
*/
- void setD( const double &x ) { D = x; }
+ void setD( const double &x ) {
+#ifdef COUNT_DMS_SINCOS_CALLS
+ m_sinDirty = m_cosDirty = true;
+#endif
+ D = x; }
/** @short Sets floating-point value of angle, in degrees.
*
@@ -195,14 +232,32 @@ public:
* @return the Sine of the angle.
* @sa cos()
*/
- double sin() const { return ::sin(D*DegToRad); }
+ double sin() const {
+#ifdef COUNT_DMS_SINCOS_CALLS
+ if( !m_sinCosCalled ) { m_sinCosCalled = true; ++dms_with_sincos_called; }
+ if( m_sinDirty )
+ m_sinDirty = false;
+ else
+ ++redundant_trig_function_calls;
+ ++trig_function_calls;
+#endif
+ return ::sin(D*DegToRad); }
/** @short Compute the Angle's Cosine.
*
* @return the Cosine of the angle.
* @sa sin()
*/
- double cos() const { return ::cos(D*DegToRad); }
+ double cos() const {
+#ifdef COUNT_DMS_SINCOS_CALLS
+ if( !m_sinCosCalled ) { m_sinCosCalled = true; ++dms_with_sincos_called; }
+ if( m_cosDirty )
+ m_cosDirty = false;
+ else
+ ++redundant_trig_function_calls;
+ ++trig_function_calls;
+#endif
+ return ::cos(D*DegToRad); }
/** @short Express the angle in radians.
* @return the angle in radians (double)
@@ -261,8 +316,17 @@ public:
static dms fromString(const QString & s, bool deg);
dms operator - () { return dms(-D); }
+#ifdef COUNT_DMS_SINCOS_CALLS
+ static long unsigned dms_constructor_calls; // counts number of DMS constructor calls
+ static long unsigned dms_with_sincos_called;
+ static long unsigned trig_function_calls; // total number of trig function calls
+ static long unsigned redundant_trig_function_calls; // counts number of redundant trig function calls
+#endif
private:
double D;
+#ifdef COUNT_DMS_SINCOS_CALLS
+ mutable bool m_sinDirty, m_cosDirty, m_sinCosCalled;
+#endif
friend dms operator+(dms, dms);
friend dms operator-(dms, dms);
@@ -294,6 +358,20 @@ inline void dms::SinCos(double& s, double& c) const {
s = ::sin( radians() );
c = ::cos( radians() );
#endif
+#ifdef COUNT_DMS_SINCOS_CALLS
+ if( !m_sinCosCalled ) { m_sinCosCalled = true; ++dms_with_sincos_called; }
+ if( m_sinDirty )
+ m_sinDirty = false;
+ else
+ ++redundant_trig_function_calls;
+
+ if( m_cosDirty )
+ m_cosDirty = false;
+ else
+ ++redundant_trig_function_calls;
+
+ trig_function_calls += 2;
+#endif
}
/** Overloaded equality operator */
diff --git a/kstars/kstars.cpp b/kstars/kstars.cpp
index d8ca2df..f4076f8 100644
--- a/kstars/kstars.cpp
+++ b/kstars/kstars.cpp
@@ -42,6 +42,9 @@
#include "observinglist.h"
//#include "whatsinteresting/wiview.h"
+// For profiling only
+#include "auxiliary/dms.h"
+
#include "kstarsadaptor.h"
#include <config-kstars.h>
@@ -173,6 +176,12 @@ KStars::~KStars()
QSqlDatabase::removeDatabase("userdb");
QSqlDatabase::removeDatabase("skydb");
+
+#ifdef COUNT_DMS_SINCOS_CALLS
+ qDebug() << "Constructed " << dms::dms_constructor_calls << " dms objects, of which " << dms::dms_with_sincos_called << " had trigonometric functions called on them = " << ( float( dms::dms_with_sincos_called ) / float( dms::dms_constructor_calls ) ) * 100. << "%";
+ qDebug() << "Of the " << dms::trig_function_calls << " calls to sin/cos/sincos on dms objects, " << dms::redundant_trig_function_calls << " were redundant = " << ( ( float( dms::redundant_trig_function_calls ) / float( dms::trig_function_calls ) ) * 100. ) << "%";
+#endif
+
}
void KStars::clearCachedFindDialog() {
More information about the Kstars-devel
mailing list