@@ -326,24 +326,33 @@ IterationCount BenchmarkRunner::PredictNumItersNeeded(
326326 // expansion should be 14x.
327327 const bool is_significant = (i.seconds / GetMinTimeToApply ()) > 0.1 ;
328328 multiplier = is_significant ? multiplier : 10.0 ;
329+
329330 if (!IsZero (GetMinRelAccuracy ())) {
330- multiplier = std::max (multiplier, std::sqrt (i. seconds2 / i. iters - std::pow (i. seconds / i. iters , 2 .)) / (i. seconds / i. iters ) / sqrt (i. iters ) * 1.4 / GetMinRelAccuracy ());
331+ multiplier = std::max (multiplier, GetRelAccuracy (i ) * 1.4 / GetMinRelAccuracy ());
331332 }
332333
334+ // So what seems to be the sufficiently-large iteration count? Round up.
335+ const IterationCount max_next_iters = static_cast <IterationCount>(
336+ std::lround (std::max (multiplier * static_cast <double >(i.iters ),
337+ static_cast <double >(i.iters ) + 1.0 )));
338+ // But we do have *some* limits though..
339+ const IterationCount next_iters = std::min (max_next_iters, kMaxIterations );
340+
341+ BM_VLOG (3 ) << " Next iters: " << next_iters << " , " << multiplier << " \n " ;
342+ return next_iters; // round up before conversion to integer.
343+ }
344+
333345bool BenchmarkRunner::ShouldReportIterationResults (
334346 const IterationResults& i) const {
335347 // Determine if this run should be reported;
336348 // Either it has run for a sufficient amount of time
337349 // or because an error was reported.
338350 return i.results .skipped_ ||
339- i.iters >= kMaxIterations || // Too many iterations already.
340- (((i.seconds >= GetMinTimeToApply ()) &&
341- (b.use_manual_time () && !IsZero (GetMinRelAccuracy ()) && (std::sqrt (i.seconds2 / i.iters - std::pow (i.seconds / i.iters , 2 .)) / (i.seconds / i.iters ) / sqrt (i.iters ) <= GetMinRelAccuracy ()))) || // The relative accuracy is enough.
342- // CPU time is specified but the elapsed real time greatly exceeds
343- // the minimum time.
344- // Note that user provided timers are except from this test.
345- ((i.results .real_time_used >= 5 * GetMinTimeToApply ()) &&
346- !b.use_manual_time ()));
351+ // Too many iterations already.
352+ i.iters >= kMaxIterations ||
353+ // We have applied for enough time and the relative accuracy is good enough.
354+ // Relative accuracy is checked only for user provided timers.
355+ (HasSufficientTimeToApply (i) && (!b.use_manual_time () || HasSufficientRelAccuracy (i)));
347356}
348357
349358double BenchmarkRunner::GetMinTimeToApply () const {
@@ -355,6 +364,22 @@ double BenchmarkRunner::GetMinTimeToApply() const {
355364 return warmup_done ? min_time : min_warmup_time;
356365}
357366
367+ double GetRelAccuracy (const IterationResults& i) const {
368+ return std::sqrt (i.seconds2 / i.iters - std::pow (i.seconds / i.iters , 2 .)) / (i.seconds / i.iters ) / sqrt (i.iters );
369+ }
370+
371+ bool BenchmarkRunner::HasSufficientTimeToApply (const IterationResults& i) const {
372+ return i.seconds >= GetMinTimeToApply () ||
373+ // CPU time is specified but the elapsed real time greatly exceeds
374+ // the minimum time.
375+ // Note that user provided timers are except from this test.
376+ (!b.use_manual_time () && i.results .real_time_used >= 5 * GetMinTimeToApply ());
377+ }
378+
379+ bool BenchmarkRunner::HasSufficientRelAccuracy (const IterationResults& i) const {
380+ return (!IsZero (GetMinRelAccuracy ()) && (GetRelAccuracy (i) <= GetMinRelAccuracy ()));
381+ }
382+
358383void BenchmarkRunner::FinishWarmUp (const IterationCount& i) {
359384 warmup_done = true ;
360385 iters = i;
0 commit comments