nanobenchmark_test.cc (2701B)
1 // Copyright 2019 Google LLC 2 // SPDX-License-Identifier: Apache-2.0 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #include "hwy/nanobenchmark.h" 17 18 #include <stddef.h> 19 #include <stdio.h> 20 21 #include "hwy/tests/hwy_gtest.h" 22 #include "hwy/tests/test_util-inl.h" 23 24 namespace hwy { 25 namespace { 26 27 // Governs duration of test; avoid timeout in debug builds. 28 #if HWY_IS_DEBUG_BUILD 29 constexpr size_t kMaxEvals = 3; 30 #else 31 constexpr size_t kMaxEvals = 4; 32 #endif 33 34 FuncOutput Div(const void*, FuncInput in) { 35 // Here we're measuring the throughput because benchmark invocations are 36 // independent. Any dividend will do; the divisor is nonzero. 37 return 0xFFFFF / in; 38 } 39 40 template <size_t N> 41 void MeasureDiv(const FuncInput (&inputs)[N]) { 42 printf("Measuring integer division (output on final two lines)\n"); 43 Result results[N]; 44 Params params; 45 params.max_evals = kMaxEvals; 46 const size_t num_results = Measure(&Div, nullptr, inputs, N, results, params); 47 for (size_t i = 0; i < num_results; ++i) { 48 printf("%5d: %6.2f ticks; MAD=%4.2f%%\n", 49 static_cast<int>(results[i].input), results[i].ticks, 50 results[i].variability * 100.0); 51 } 52 } 53 54 RandomState rng; 55 56 // A function whose runtime depends on rng. 57 FuncOutput Random(const void* /*arg*/, FuncInput in) { 58 const size_t r = rng() & 0xF; 59 FuncOutput ret = static_cast<FuncOutput>(in); 60 for (size_t i = 0; i < r; ++i) { 61 ret /= ((rng() & 1) + 2); 62 } 63 return ret; 64 } 65 66 // Ensure the measured variability is high. 67 template <size_t N> 68 void MeasureRandom(const FuncInput (&inputs)[N]) { 69 Result results[N]; 70 Params p; 71 p.max_evals = kMaxEvals; 72 p.verbose = false; 73 const size_t num_results = Measure(&Random, nullptr, inputs, N, results, p); 74 for (size_t i = 0; i < num_results; ++i) { 75 HWY_ASSERT(results[i].variability > 1E-3); 76 } 77 } 78 79 TEST(NanobenchmarkTest, RunTest) { 80 const int unpredictable = Unpredictable1(); // == 1, unknown to compiler. 81 static const FuncInput inputs[] = {static_cast<FuncInput>(unpredictable) + 2, 82 static_cast<FuncInput>(unpredictable + 9)}; 83 84 MeasureDiv(inputs); 85 MeasureRandom(inputs); 86 } 87 88 } // namespace 89 } // namespace hwy 90 91 HWY_TEST_MAIN();