static void run_benchmark(char *name, void (*benchmark)(void *), void (*setup)(void *), void (*teardown)(void *), void *data, int count, int iter) { int i; double min = HUGE_VAL; double sum = 0.0; double max = 0.0; for (i = 0; i < count; i++) { double begin, total; if (setup != NULL) { setup(data); } begin = gettimedouble(); benchmark(data); total = gettimedouble() - begin; if (teardown != NULL) { teardown(data); } if (total < min) { min = total; } if (total > max) { max = total; } sum += total; } printf("%s: min ", name); print_number(min * 1000000000.0 / iter); printf("ns / avg "); print_number((sum / count) * 1000000000.0 / iter); printf("ns / max "); print_number(max * 1000000000.0 / iter); printf("ns\n"); }
bool benchmark::State::KeepRunning() { if (count & countMask) { ++count; return true; } double now; uint64_t nowCycles; if (count == 0) { lastTime = beginTime = now = gettimedouble(); lastCycles = beginCycles = nowCycles = perf_cpucycles(); } else { now = gettimedouble(); double elapsed = now - lastTime; double elapsedOne = elapsed * countMaskInv; if (elapsedOne < minTime) minTime = elapsedOne; if (elapsedOne > maxTime) maxTime = elapsedOne; // We only use relative values, so don't have to handle 64-bit wrap-around specially nowCycles = perf_cpucycles(); uint64_t elapsedOneCycles = (nowCycles - lastCycles) * countMaskInv; if (elapsedOneCycles < minCycles) minCycles = elapsedOneCycles; if (elapsedOneCycles > maxCycles) maxCycles = elapsedOneCycles; 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(); minCycles = std::numeric_limits<uint64_t>::max(); maxCycles = std::numeric_limits<uint64_t>::min(); return true; } if (elapsed*16 < maxElapsed) { uint64_t newCountMask = ((countMask<<1)|1) & ((1LL<<60)-1); if ((count & newCountMask)==0) { countMask = newCountMask; countMaskInv = 1./(countMask+1); } } } lastTime = now; lastCycles = nowCycles; ++count; if (now - beginTime < maxElapsed) return true; // Keep going --count; assert(count != 0 && "count == 0 => (now == 0 && beginTime == 0) => return above"); // Output results double average = (now-beginTime)/count; int64_t averageCycles = (nowCycles-beginCycles)/count; std::cout << std::fixed << std::setprecision(15) << name << "," << count << "," << minTime << "," << maxTime << "," << average << "," << minCycles << "," << maxCycles << "," << averageCycles << "\n"; return false; }