aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2016-05-31 15:09:27 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2016-05-31 15:10:03 +0200
commit0026e0ef3472fc7d7d89a4f05548b1233302cba1 (patch)
tree74be02a937cc9a90a6acc3e7041e680e8c341801
parent950be19727a581970591d8f8138dfe4725750382 (diff)
parent63ff57db4beb2e92b3d8ed396da016f29f790195 (diff)
Merge #8115: Avoid integer division in the benchmark inner-most loop.
63ff57d Avoid integer division in the benchmark inner-most loop. (Gregory Maxwell)
-rw-r--r--src/bench/bench.cpp35
-rw-r--r--src/bench/bench.h7
2 files changed, 28 insertions, 14 deletions
diff --git a/src/bench/bench.cpp b/src/bench/bench.cpp
index 6ee3cdc27a..227546a7a7 100644
--- a/src/bench/bench.cpp
+++ b/src/bench/bench.cpp
@@ -5,6 +5,7 @@
#include "bench.h"
#include <iostream>
+#include <iomanip>
#include <sys/time.h>
using namespace benchmark;
@@ -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) {
@@ -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;
@@ -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;
}
diff --git a/src/bench/bench.h b/src/bench/bench.h
index 5ce13c642b..f13b145aaf 100644
--- a/src/bench/bench.h
+++ b/src/bench/bench.h
@@ -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();
};