Skip to content

Commit 2aa23c2

Browse files
committed
User counters: normalize time by thread count
Fixes #2080
1 parent 021a05f commit 2aa23c2

File tree

5 files changed

+26
-17
lines changed

5 files changed

+26
-17
lines changed

src/benchmark_runner.cc

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,12 @@ BenchmarkReporter::Run CreateRunReport(
123123
: 0;
124124
}
125125

126-
internal::Finish(&report.counters, results.iterations, seconds,
126+
// The CPU time is the total time taken by all thread. If we used that as
127+
// the denominator, we'd be calculating the rate per thread here. This is
128+
// why we have to divide the total cpu_time by the number of threads for
129+
// global counters to get a global rate.
130+
const double thread_seconds = seconds / b.threads();
131+
internal::Finish(&report.counters, results.iterations, thread_seconds,
127132
b.threads());
128133
}
129134
return report;

src/counter.cc

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@ double Finish(Counter const& c, IterationCount iterations, double cpu_time,
2323
double num_threads) {
2424
double v = c.value;
2525
if ((c.flags & Counter::kIsRate) != 0) {
26-
// The CPU time is the total time taken by all threads (https://github.com/google/benchmark/pull/1836)
27-
// If we used that as the denominator, we'd be calculating the rate per thread here. This is why
28-
// we have to divide the total cpu_time by the number of threads for global counters to get a global rate.
29-
//
30-
// See https://github.com/google/benchmark/issues/2080
31-
v /= (cpu_time / num_threads);
26+
v /= cpu_time;
3227
}
3328
if ((c.flags & Counter::kAvgThreads) != 0) {
3429
v /= num_threads;

test/user_counters_tabular_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_CounterRates_Tabular/threads:%int\",%csv_report,"
418418
// VS2013 does not allow this function to be passed as a lambda argument
419419
// to CHECK_BENCHMARK_RESULTS()
420420
void CheckTabularRate(Results const& e) {
421-
double t = e.DurationCPUTime();
421+
double t = e.DurationCPUTime() / e.NumThreads();
422422
CHECK_FLOAT_COUNTER_VALUE(e, "Foo", EQ, 1. / t, 0.001);
423423
CHECK_FLOAT_COUNTER_VALUE(e, "Bar", EQ, 2. / t, 0.001);
424424
CHECK_FLOAT_COUNTER_VALUE(e, "Baz", EQ, 4. / t, 0.001);

test/user_counters_test.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,10 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_AvgThreadsRate/"
381381
// VS2013 does not allow this function to be passed as a lambda argument
382382
// to CHECK_BENCHMARK_RESULTS()
383383
void CheckAvgThreadsRate(Results const& e) {
384-
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / e.DurationCPUTime(), 0.001);
385-
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / e.DurationCPUTime(), 0.001);
384+
// this (and not real time) is the time used
385+
double t = e.DurationCPUTime() / e.NumThreads();
386+
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / t, 0.001);
387+
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / t, 0.001);
386388
}
387389
CHECK_BENCHMARK_RESULTS("BM_Counters_AvgThreadsRate/threads:%int",
388390
&CheckAvgThreadsRate);

test/user_counters_threads_test.cc

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_WithBytesAndItemsPSec/threads:%int\","
107107
// VS2013 does not allow this function to be passed as a lambda argument
108108
// to CHECK_BENCHMARK_RESULTS()
109109
void CheckBytesAndItemsPSec(Results const& e) {
110-
double t = e.DurationCPUTime(); // this (and not real time) is the time used
110+
// this (and not real time) is the time used
111+
double t = e.DurationCPUTime() / e.NumThreads();
111112
CHECK_COUNTER_VALUE(e, int, "foo", EQ, 1 * e.NumThreads());
112113
// check that the values are within 0.1% of the expected values
113114
CHECK_FLOAT_RESULT_VALUE(e, "bytes_per_second", EQ,
@@ -158,7 +159,8 @@ ADD_CASES(TC_CSVOut,
158159
// VS2013 does not allow this function to be passed as a lambda argument
159160
// to CHECK_BENCHMARK_RESULTS()
160161
void CheckRate(Results const& e) {
161-
double t = e.DurationCPUTime(); // this (and not real time) is the time used
162+
// this (and not real time) is the time used
163+
double t = e.DurationCPUTime() / e.NumThreads();
162164
// check that the values are within 0.1% of the expected values
163165
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, (1. * e.NumThreads()) / t, 0.001);
164166
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, (2. * e.NumThreads()) / t, 0.001);
@@ -258,7 +260,8 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_InvertedRate/"
258260
// VS2013 does not allow this function to be passed as a lambda argument
259261
// to CHECK_BENCHMARK_RESULTS()
260262
void CheckInvertedRate(Results const& e) {
261-
double t = e.DurationCPUTime(); // this (and not real time) is the time used
263+
// this (and not real time) is the time used
264+
double t = e.DurationCPUTime() / e.NumThreads();
262265
// check that the values are within 0.1% of the expected values
263266
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, t / (e.NumThreads()), 0.001);
264267
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, t / (8192.0 * e.NumThreads()), 0.001);
@@ -394,8 +397,10 @@ ADD_CASES(TC_CSVOut, {{"^\"BM_Counters_AvgThreadsRate/"
394397
// VS2013 does not allow this function to be passed as a lambda argument
395398
// to CHECK_BENCHMARK_RESULTS()
396399
void CheckAvgThreadsRate(Results const& e) {
397-
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / e.DurationCPUTime(), 0.001);
398-
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / e.DurationCPUTime(), 0.001);
400+
// this (and not real time) is the time used
401+
double t = e.DurationCPUTime() / e.NumThreads();
402+
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. / t, 0.001);
403+
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. / t, 0.001);
399404
}
400405
CHECK_BENCHMARK_RESULTS("BM_Counters_AvgThreadsRate/threads:%int",
401406
&CheckAvgThreadsRate);
@@ -496,7 +501,8 @@ ADD_CASES(
496501
// to CHECK_BENCHMARK_RESULTS()
497502
void CheckIsIterationInvariantRate(Results const& e) {
498503
double its = e.NumIterations();
499-
double t = e.DurationCPUTime(); // this (and not real time) is the time used
504+
// this (and not real time) is the time used
505+
double t = e.DurationCPUTime() / e.NumThreads();
500506
// check that the values are within 0.1% of the expected values
501507
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, its * 1. * e.NumThreads() / t, 0.001);
502508
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, its * 2. * e.NumThreads() / t, 0.001);
@@ -596,7 +602,8 @@ ADD_CASES(TC_CSVOut,
596602
// to CHECK_BENCHMARK_RESULTS()
597603
void CheckAvgIterationsRate(Results const& e) {
598604
double its = e.NumIterations();
599-
double t = e.DurationCPUTime(); // this (and not real time) is the time used
605+
// this (and not real time) is the time used
606+
double t = e.DurationCPUTime() / e.NumThreads();
600607
// check that the values are within 0.1% of the expected values
601608
CHECK_FLOAT_COUNTER_VALUE(e, "foo", EQ, 1. * e.NumThreads() / its / t, 0.001);
602609
CHECK_FLOAT_COUNTER_VALUE(e, "bar", EQ, 2. * e.NumThreads() / its / t, 0.001);

0 commit comments

Comments
 (0)