/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PerformanceCounters.h" #include #include #include #include using namespace filament::math; struct Scalar{}; struct Vector{}; template static void BM_trig(benchmark::State& state) noexcept { T f; state.SetLabel(T::label()); std::vector data(1024); std::vector res(1024); for (size_t i = 0; i < data.size(); i++) { data[i] = float((float(i) / data.size()) * F_2_PI - F_PI); } { PerformanceCounters pc(state); for (auto _ : state) { for (size_t i = 0, c = data.size(); i < c; i++) { res[i] = f(data[i]); } benchmark::ClobberMemory(); benchmark::DoNotOptimize(res); } pc.stop(); state.SetItemsProcessed(state.iterations() * data.size()); } } UTILS_NOINLINE static void init(std::vector& v) noexcept { for (size_t i = 0; i < v.size(); i++) { v[i] = (float(i + 1) / (v.size() + 1)) * 1024; } } template static void BM_func(benchmark::State& state) noexcept { T f; state.SetLabel(T::label()); std::vector res(1024); std::vector data(1024); init(data); { PerformanceCounters pc(state); for (auto _ : state) { for (size_t i = 0, c = data.size(); i < c; i++) { res[i] = f(data[i]); } benchmark::ClobberMemory(); benchmark::DoNotOptimize(res); } pc.stop(); state.SetItemsProcessed(state.iterations() * data.size()); } } struct StdCos { using result_type = float; float operator()(float v) { return std::cos(v); } static const char* label() { return "std::cos"; } }; struct FastCos { using result_type = float; float operator()(float v) { return fast::cos(v); } static const char* label() { return "fast::cos"; } }; struct StdLog2 { using result_type = float; float operator()(float v) { return std::log2(v); } static const char* label() { return "std::log2"; } }; struct FastLog2 { using result_type = float; float operator()(float v) { return fast::log2(v); } static const char* label() { return "fast::log2"; } }; struct Rcp { using result_type = float; float operator()(float v) { return 1.0f/v; } static const char* label() { return "1/x"; } }; struct StdISqrt { using result_type = float; float operator()(float v) { return 1.0f / std::sqrt(v); } static const char* label() { return "1/std::sqrt"; } }; struct FastISqrt { using result_type = float; float operator()(float v) { return fast::isqrt(v); } static const char* label() { return "fast::isqrt"; } }; struct StdPow2dot2 { using result_type = float; float operator()(float v) { return std::pow(v, 2.2f); } static const char* label() { return "std::pow(x, 2.2f)"; } }; struct StdExp2dot2Log { using result_type = float; float operator()(float v) { return std::exp(2.2f * std::log(v)); } static const char* label() { return "std::exp(2.2f * std::log(x))"; } }; struct Float16 { using result_type = half; half operator()(float v) { return half(v); } static const char* label() { return "half"; } }; BENCHMARK_TEMPLATE(BM_trig, Scalar, StdCos); BENCHMARK_TEMPLATE(BM_trig, Scalar, FastCos); BENCHMARK_TEMPLATE(BM_trig, Vector, FastCos); BENCHMARK_TEMPLATE(BM_func, Scalar, StdLog2); BENCHMARK_TEMPLATE(BM_func, Scalar, FastLog2); BENCHMARK_TEMPLATE(BM_func, Vector, FastLog2); BENCHMARK_TEMPLATE(BM_func, Scalar, Rcp); BENCHMARK_TEMPLATE(BM_func, Vector, Rcp); BENCHMARK_TEMPLATE(BM_func, Scalar, StdISqrt); BENCHMARK_TEMPLATE(BM_func, Vector, StdISqrt); BENCHMARK_TEMPLATE(BM_func, Scalar, FastISqrt); BENCHMARK_TEMPLATE(BM_func, Vector, FastISqrt); BENCHMARK_TEMPLATE(BM_func, Scalar, StdPow2dot2); BENCHMARK_TEMPLATE(BM_func, Scalar, StdExp2dot2Log); BENCHMARK_TEMPLATE(BM_func, Scalar, Float16);