diff --git a/include/benchmark/benchmark_api.h b/include/benchmark/benchmark_api.h index 7762a42f..abfbad2c 100644 --- a/include/benchmark/benchmark_api.h +++ b/include/benchmark/benchmark_api.h @@ -595,7 +595,13 @@ public: // Foo in 4 threads // Foo in 8 threads // Foo in 16 threads - Benchmark* ThreadRange(int min_threads, int max_threads); + Benchmark *ThreadRange(int min_threads, int max_threads); + + // For each value n in the range, run this benchmark once using n threads. + // min_threads and max_threads are always included in the range. + // stride specifies the increment. E.g. DenseThreadRange(1, 8, 3) starts + // a benchmark with 1, 4, 7 and 8 threads. + Benchmark *DenseThreadRange(int min_threads, int max_threads, int stride = 1); // Equivalent to ThreadRange(NumCPUs(), NumCPUs()) Benchmark* ThreadPerCpu(); diff --git a/src/benchmark.cc b/src/benchmark.cc index f0f0a43d..a48f5ab3 100644 --- a/src/benchmark.cc +++ b/src/benchmark.cc @@ -293,6 +293,7 @@ public: void ComplexityLambda(BigOFunc* complexity); void Threads(int t); void ThreadRange(int min_threads, int max_threads); + void DenseThreadRange(int min_threads, int max_threads, int stride); void ThreadPerCpu(); void SetName(const char* name); @@ -548,6 +549,18 @@ void BenchmarkImp::ThreadRange(int min_threads, int max_threads) { AddRange(&thread_counts_, min_threads, max_threads, 2); } +void BenchmarkImp::DenseThreadRange(int min_threads, int max_threads, + int stride) { + CHECK_GT(min_threads, 0); + CHECK_GE(max_threads, min_threads); + CHECK_GE(stride, 1); + + for (auto i = min_threads; i < max_threads; i += stride) { + thread_counts_.push_back(i); + } + thread_counts_.push_back(max_threads); +} + void BenchmarkImp::ThreadPerCpu() { static int num_cpus = NumCPUs(); thread_counts_.push_back(num_cpus); @@ -580,6 +593,7 @@ void BenchmarkImp::AddRange(std::vector* dst, int lo, int hi, int mult) { } } + Benchmark::Benchmark(const char* name) : imp_(new BenchmarkImp(name)) { @@ -687,6 +701,12 @@ Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) { return this; } +Benchmark *Benchmark::DenseThreadRange(int min_threads, int max_threads, + int stride) { + imp_->DenseThreadRange(min_threads, max_threads, stride); + return this; +} + Benchmark* Benchmark::ThreadPerCpu() { imp_->ThreadPerCpu(); return this; diff --git a/test/benchmark_test.cc b/test/benchmark_test.cc index fe7d82c6..eeb6e854 100644 --- a/test/benchmark_test.cc +++ b/test/benchmark_test.cc @@ -220,5 +220,26 @@ BENCHMARK_CAPTURE(BM_non_template_args, basic_test, 0, 0); #endif // __cplusplus >= 201103L -BENCHMARK_MAIN() +static void BM_DenseThreadRanges(benchmark::State &st) { + switch (st.range(0)) { + case 1: + assert(st.threads == 1 || st.threads == 2 || st.threads == 3); + break; + case 2: + assert(st.threads == 1 || st.threads == 3 || st.threads == 4); + break; + case 3: + assert(st.threads == 5 || st.threads == 8 || st.threads == 11 || + st.threads == 14); + break; + default: + assert(false && "Invalid test case number"); + } + while (st.KeepRunning()) { + } +} +BENCHMARK(BM_DenseThreadRanges)->Arg(1)->DenseThreadRange(1, 3); +BENCHMARK(BM_DenseThreadRanges)->Arg(2)->DenseThreadRange(1, 4, 2); +BENCHMARK(BM_DenseThreadRanges)->Arg(3)->DenseThreadRange(5, 14, 3); +BENCHMARK_MAIN()