W'bal use threads

.. to boost performance. Now will compute the integral
   in parallel and saves about 35% in elapsed time on a
   dual core processor.
This commit is contained in:
Mark Liversedge
2014-01-25 22:56:41 +00:00
parent 3c122d429c
commit f10e24857d
2 changed files with 79 additions and 47 deletions

View File

@@ -159,40 +159,31 @@ WPrime::setRide(RideFile *input)
TAU = int(TAU); // round it down
//qDebug()<<"data preparation took"<<time.elapsed();
// STEP 2: ITERATE OVER DATA TO CREATE W' DATA SERIES
// initialise with Wbal equal to W' and therefore 0 expenditure
double Wbal = WPRIME;
double Wexp = 0;
int u = 0;
// lets run forward from 0s to end of ride
minY = WPRIME;
maxY = WPRIME;
values.resize(last+1);
xvalues.resize(last+1);
QVector<double> myvalues(last+1);
int stop = last / 2;
WPrimeIntegrator a(inputArray, 0, stop, TAU);
WPrimeIntegrator b(inputArray, stop+1, last, TAU);
a.start();
b.start();
a.wait();
b.wait();
// sum values
for (int t=0; t<=last; t++) {
// for each value in the input array apply the decay
// and integrate across the target output, but lets
// bound it;
// input is 0 then don't bother adding lots of zeroes
// only integrate WprimeDecayPeriod into the future, as per the spreadsheet
// stop integrating when it has decayed to less than 0.1 watts (exponential sum)
xvalues[t] = double(t)/60.00f;
if (inputArray[t] <= 0) continue;
for (int i=0; i<WprimeDecayPeriod && t+i <= last; i++) {
double value = inputArray[t] * pow(E, -(double(i)/TAU));
// integrate
values[t+i] += value;
}
values[t] = a.output[t] + b.output[t];
xvalues[t] = double(t) / 60.00f;
}
// now subtract WPRIME and work out minimum etc
@@ -204,6 +195,8 @@ WPrime::setRide(RideFile *input)
if (value < minY) minY = value;
}
//qDebug()<<"compute W'bal curve took"<<time.elapsed();
// STEP 3: FIND MATCHES
// SMOOTH DATA SERIES
@@ -295,12 +288,15 @@ WPrime::PCP()
} while (cp <= 500);
PCP_ = cp;
return PCP_=cp;
}
int
WPrime::minForCP(int cp)
{
QTime time; // for profiling performance of the code
time.start();
// input array contains the actual W' expenditure
// and will also contain non-zero values
double tau;
@@ -325,46 +321,38 @@ WPrime::minForCP(int cp)
tau = int(tau); // round it down
//qDebug()<<"data preparation took"<<time.elapsed();
// STEP 2: ITERATE OVER DATA TO CREATE W' DATA SERIES
// initialise with Wbal equal to W' and therefore 0 expenditure
double Wbal = WPRIME;
double Wexp = 0;
int u = 0;
// lets run forward from 0s to end of ride
int min = WPRIME;
QVector<double> myvalues(last+1);
for (int t=0; t<=last; t++) {
int stop = last / 2;
// for each value in the input array apply the decay
// and integrate across the target output, but lets
// bound it;
// input is 0 then don't bother adding lots of zeroes
// only integrate WprimeDecayPeriod into the future, as per the spreadsheet
// stop integrating when it has decayed to less than 0.1 watts (exponential sum)
if (inputArray[t] <= 0) continue;
WPrimeIntegrator a(inputArray, 0, stop, tau);
WPrimeIntegrator b(inputArray, stop+1, last, tau);
for (int i=0; i<WprimeDecayPeriod && t+i <= last; i++) {
a.start();
b.start();
double value = inputArray[t] * pow(E, -(double(i)/tau));
// integrate
myvalues[t+i] += value;
}
}
a.wait();
b.wait();
// sum values
for (int t=0; t<=last; t++)
myvalues[t] = a.output[t] + b.output[t];
// now subtract WPRIME and work out minimum etc
for(int t=0; t <= last; t++) {
double value = WPRIME - myvalues[t];
if (value < min) min = value;
}
//qDebug()<<"compute time="<<time.elapsed();
qDebug()<<"min="<<min<<"CP="<<cp;
return min;
}
double
WPrime::maxMatch()
{
@@ -375,6 +363,32 @@ WPrime::maxMatch()
return max;
}
// decay and integrate -- split into threads for
// best performance
WPrimeIntegrator::WPrimeIntegrator(QVector<int> &source, int begin, int end, double TAU) :
source(source), begin(begin), end(end), TAU(TAU)
{
output.resize(source.size());
}
void
WPrimeIntegrator::run()
{
// run from start to stop adding decay to end
for (int t=begin; t<end; t++) {
if (source[t] <= 0) continue;
for (int i=0; i<WprimeDecayPeriod && t+i < source.size(); i++) {
double value = source[t] * pow(E, -(double(i)/TAU));
// integrate
output[t+i] += value;
}
}
}
//
// Associated Metrics
//

View File

@@ -25,6 +25,7 @@
#include "Zones.h"
#include "RideMetric.h"
#include <QVector>
#include <QThread>
#include <qwt_spline.h> // smoothing
#include <math.h>
@@ -76,4 +77,21 @@ class WPrime {
int last;
};
class WPrimeIntegrator : public QThread
{
public:
WPrimeIntegrator(QVector<int> &source, int begin, int end, double TAU);
// integrate from start to stop from source into output
// basically sums in the exponential decays, but we break it
// into threads to parallelise the work
void run();
QVector<int> &source;
int begin, end;
double TAU;
// resized to match source holds results
QVector<double> output;
};
#endif