-
Notifications
You must be signed in to change notification settings - Fork 1.7k
#2080: Fix rate and thread rate counter aggregates #2081
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
| v /= (cpu_time / num_threads); | ||
| } | ||
| if ((c.flags & Counter::kAvgThreads) != 0) { | ||
| v /= num_threads; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i should know this but i've lost track: can flags be both IsRate and AvgThreads? if so, are we then dividing twice incorrectly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i should know this but i've lost track: can flags be both IsRate and AvgThreads
IIUC, yes, that's what kAvgThreadsRate will do:
benchmark/include/benchmark/benchmark.h
Line 655 in 2279f2a
| kAvgThreadsRate = kIsRate | kAvgThreads, |
if so, are we then dividing twice incorrectly?
I think it is correct. For IsRate we are multiplying by the number of threads (note the brackets, a / (b / c) = a / b * c). Then for kAvgThreads we are dividing by the number of threads again a / b * c / c = a / b, so we get what we'd expect for the per-thread average?
But this should just be tested in some unit tests. I need to check where the existing tests are.
LebedevRI
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lossless way to do this would be to introduce kIsThreadInvariant.
Let's continue the high level discussion in #2080 (comment), since you left a longer response over there. I don't think introducing a new flag is the way to go here. |
|
merged 2089 |
|
Well, this does what it claims to. |
Is that a question for me? I haven't used |
|
agreed, this does what the issue suggested. we still need some documentation in the docs somewhere, and yes please check the ProcessCPUTime also makes sense. |
|
Thank you so much for adding all the tests @LebedevRI and @dmah42 and sorry I didn't get to it earlier. I updated the PR description and will look into the docs and check ProcessCPUTime before marking it as ready for review. |
|
If I understand the docs correctly, static void BM_ExampleTiming(benchmark::State& state) {
for (auto _ : state) {
benchmark::DoNotOptimize(1 + 2);
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
state.SetIterationTime(1);
}
state.counters["counter"] = benchmark::Counter(1);
state.counters["counter_rate"] = benchmark::Counter(1, benchmark::Counter::kIsRate);
state.counters["counter_thread_rate"] = benchmark::Counter(1, benchmark::Counter::kAvgThreadsRate);
}
BENCHMARK(BM_ExampleTiming)
->Threads(1)
->Threads(10);
BENCHMARK(BM_ExampleTiming)
->Threads(1)
->Threads(10)
->UseManualTime();
BENCHMARK(BM_ExampleTiming)
->Threads(1)
->Threads(10)
->UseRealTime();
BENCHMARK(BM_ExampleTiming)
->Threads(1)
->Threads(10)
->MeasureProcessCPUTime();
BENCHMARK(BM_ExampleTiming)
->Threads(1)
->Threads(10)
->UseManualTime()
->MeasureProcessCPUTime();
BENCHMARK(BM_ExampleTiming)
->Threads(1)
->Threads(10)
->UseRealTime()
->MeasureProcessCPUTime();The rates are consistent as long as you don't use CPU time for the rate calculation (which makes sense given my sleep / manual timing). So I think we're good on this front? |
|
I updated the docs in 894fa39. Let me know if you'd like me to add an example or if that's enough :) |
As the name suggests, it measures the Process CPU Time, |
at this point i'm not sure either. the docs say "// Measure the total CPU consumption, use it to decide for how long to the difference is (on Linux) between i'm afraid i'll need to let you decide how this should correspond to Threads and timing outputs. |
Changes
When using counters that represent a global rate (
benchmark::Counter::kIsRate), before this PR, the rate was effectively computed per thread because we pass the sum of all seconds (wall or CPU time) passed across all threads. This breaks the definition of the global rate and subsequently, when usingkAvgThreadsRate, the rate is divided by the number of threads (again), yielding non-sense results.This is a regression introduced by #1836. This PR fixes it by dividing the total seconds count by the number of threads before passing it to the counter finalization, which then computes the rates etc.
We're also fixing the test expectations.
References