Browse Source

Merge #8115: Avoid integer division in the benchmark inner-most loop.

63ff57d Avoid integer division in the benchmark inner-most loop. (Gregory Maxwell)
0.13
Wladimir J. van der Laan 8 years ago
parent
commit
0026e0ef34
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 35
      src/bench/bench.cpp
  2. 7
      src/bench/bench.h

35
src/bench/bench.cpp

@ -5,6 +5,7 @@
#include "bench.h" #include "bench.h"
#include <iostream> #include <iostream>
#include <iomanip>
#include <sys/time.h> #include <sys/time.h>
using namespace benchmark; using namespace benchmark;
@ -25,7 +26,7 @@ BenchRunner::BenchRunner(std::string name, BenchFunction func)
void void
BenchRunner::RunAll(double elapsedTimeForOne) BenchRunner::RunAll(double elapsedTimeForOne)
{ {
std::cout << "Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n"; std::cout << "#Benchmark" << "," << "count" << "," << "min" << "," << "max" << "," << "average" << "\n";
for (std::map<std::string,BenchFunction>::iterator it = benchmarks.begin(); for (std::map<std::string,BenchFunction>::iterator it = benchmarks.begin();
it != benchmarks.end(); ++it) { it != benchmarks.end(); ++it) {
@ -38,22 +39,34 @@ BenchRunner::RunAll(double elapsedTimeForOne)
bool State::KeepRunning() bool State::KeepRunning()
{ {
if (count & countMask) {
++count;
return true;
}
double now; double now;
if (count == 0) { if (count == 0) {
beginTime = now = gettimedouble(); lastTime = beginTime = now = gettimedouble();
} }
else { else {
// timeCheckCount is used to avoid calling gettime most of the time,
// so benchmarks that run very quickly get consistent results.
if ((count+1)%timeCheckCount != 0) {
++count;
return true; // keep going
}
now = gettimedouble(); now = gettimedouble();
double elapsedOne = (now - lastTime)/timeCheckCount; double elapsed = now - lastTime;
double elapsedOne = elapsed * countMaskInv;
if (elapsedOne < minTime) minTime = elapsedOne; if (elapsedOne < minTime) minTime = elapsedOne;
if (elapsedOne > maxTime) maxTime = elapsedOne; if (elapsedOne > maxTime) maxTime = elapsedOne;
if (elapsedOne*timeCheckCount < maxElapsed/16) timeCheckCount *= 2; if (elapsed*128 < maxElapsed) {
// If the execution was much too fast (1/128th of maxElapsed), increase the count mask by 8x and restart timing.
// The restart avoids including the overhead of this code in the measurement.
countMask = ((countMask<<3)|7) & ((1LL<<60)-1);
countMaskInv = 1./(countMask+1);
count = 0;
minTime = std::numeric_limits<double>::max();
maxTime = std::numeric_limits<double>::min();
return true;
}
if (elapsed*16 < maxElapsed) {
countMask = ((countMask<<1)|1) & ((1LL<<60)-1);
countMaskInv = 1./(countMask+1);
}
} }
lastTime = now; lastTime = now;
++count; ++count;
@ -64,7 +77,7 @@ bool State::KeepRunning()
// Output results // Output results
double average = (now-beginTime)/count; double average = (now-beginTime)/count;
std::cout << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n"; std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << "\n";
return false; return false;
} }

7
src/bench/bench.h

@ -40,14 +40,15 @@ namespace benchmark {
std::string name; std::string name;
double maxElapsed; double maxElapsed;
double beginTime; double beginTime;
double lastTime, minTime, maxTime; double lastTime, minTime, maxTime, countMaskInv;
int64_t count; int64_t count;
int64_t timeCheckCount; int64_t countMask;
public: public:
State(std::string _name, double _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) { State(std::string _name, double _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) {
minTime = std::numeric_limits<double>::max(); minTime = std::numeric_limits<double>::max();
maxTime = std::numeric_limits<double>::min(); maxTime = std::numeric_limits<double>::min();
timeCheckCount = 1; countMask = 1;
countMaskInv = 1./(countMask + 1);
} }
bool KeepRunning(); bool KeepRunning();
}; };

Loading…
Cancel
Save