Skip to content

Commit

Permalink
Merge #8115: Avoid integer division in the benchmark inner-most loop.
Browse files Browse the repository at this point in the history
63ff57d Avoid integer division in the benchmark inner-most loop. (Gregory Maxwell)
  • Loading branch information
laanwj committed May 31, 2016
2 parents 950be19 + 63ff57d commit 0026e0e
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 14 deletions.
35 changes: 24 additions & 11 deletions src/bench/bench.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "bench.h"

#include <iostream>
#include <iomanip>
#include <sys/time.h>

using namespace benchmark;
Expand All @@ -25,7 +26,7 @@ BenchRunner::BenchRunner(std::string name, BenchFunction func)
void
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();
it != benchmarks.end(); ++it) {
Expand All @@ -38,22 +39,34 @@ BenchRunner::RunAll(double elapsedTimeForOne)

bool State::KeepRunning()
{
if (count & countMask) {
++count;
return true;
}
double now;
if (count == 0) {
beginTime = now = gettimedouble();
lastTime = beginTime = now = gettimedouble();
}
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();
double elapsedOne = (now - lastTime)/timeCheckCount;
double elapsed = now - lastTime;
double elapsedOne = elapsed * countMaskInv;
if (elapsedOne < minTime) minTime = 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;
++count;
Expand All @@ -64,7 +77,7 @@ bool State::KeepRunning()

// Output results
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;
}
7 changes: 4 additions & 3 deletions src/bench/bench.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ namespace benchmark {
std::string name;
double maxElapsed;
double beginTime;
double lastTime, minTime, maxTime;
double lastTime, minTime, maxTime, countMaskInv;
int64_t count;
int64_t timeCheckCount;
int64_t countMask;
public:
State(std::string _name, double _maxElapsed) : name(_name), maxElapsed(_maxElapsed), count(0) {
minTime = std::numeric_limits<double>::max();
maxTime = std::numeric_limits<double>::min();
timeCheckCount = 1;
countMask = 1;
countMaskInv = 1./(countMask + 1);
}
bool KeepRunning();
};
Expand Down

0 comments on commit 0026e0e

Please sign in to comment.