Add more autodiff benchmarks - Create new subdirectory internal/ceres/autodiff_benchmarks - Move the ba-autodiff benchmark to the new subdir. - Add new autodiff benchmarks for linear cost functions (1 and 10 params) Change-Id: Ic0e31cf2c05389935bb90c6a4fd9c0382a7e1ed0
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index a8813a6..9329162 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -511,9 +511,6 @@ endmacro() if (BUILD_BENCHMARKS) - add_executable(autodiff_cost_function_benchmark autodiff_cost_function_benchmark.cc) - add_dependencies_to_benchmark(autodiff_cost_function_benchmark) - add_executable(small_blas_gemv_benchmark small_blas_gemv_benchmark.cc) add_dependencies_to_benchmark(small_blas_gemv_benchmark) @@ -525,9 +522,10 @@ add_executable(schur_eliminator_benchmark schur_eliminator_benchmark.cc) add_dependencies_to_benchmark(schur_eliminator_benchmark) + + add_subdirectory(autodiff_benchmarks) endif (BUILD_BENCHMARKS) if(CODE_GENERATION) add_subdirectory(codegen) endif() -
diff --git a/internal/ceres/autodiff_benchmarks/CMakeLists.txt b/internal/ceres/autodiff_benchmarks/CMakeLists.txt new file mode 100644 index 0000000..e42e584 --- /dev/null +++ b/internal/ceres/autodiff_benchmarks/CMakeLists.txt
@@ -0,0 +1,55 @@ + +if(CODE_GENERATION) + macro (generate_benchmark_functor FUNCTOR_NAME FUNCTOR_FILE) + ceres_generate_cost_function_implementation_for_functor( + NAME ${FUNCTOR_NAME} + INPUT_FILE ${FUNCTOR_FILE} + OUTPUT_DIRECTORY benchmarks + NAMESPACE ceres + ) + endmacro() + include(CeresCodeGeneration) + + generate_benchmark_functor(SnavelyReprojectionError snavely_reprojection_error.h) + generate_benchmark_functor(Linear1CostFunction linear_cost_functions.h) + generate_benchmark_functor(Linear10CostFunction linear_cost_functions.h) + + list(APPEND CERES_BENCHMARK_FLAGS "-DWITH_CODE_GENERATION") +endif() + + +# TODO: Add support for other compilers +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + list(APPEND CERES_BENCHMARK_FLAGS "-mllvm" "-inline-threshold=1000000") + + # All other flags + fast-math + list(APPEND CERES_BENCHMARK_FAST_MATH_FLAGS ${CERES_BENCHMARK_FLAGS} "-ffast-math") +endif() + +add_executable(rat43_benchmark rat43_benchmark.cc) +add_dependencies_to_benchmark(rat43_benchmark) + + +add_executable(snavely_reprojection_error_benchmark snavely_reprojection_error_benchmark.cc) +add_dependencies_to_benchmark(snavely_reprojection_error_benchmark) +target_compile_options(snavely_reprojection_error_benchmark PRIVATE ${CERES_BENCHMARK_FLAGS}) + +add_executable(snavely_reprojection_error_benchmark_fast_math snavely_reprojection_error_benchmark.cc) +add_dependencies_to_benchmark(snavely_reprojection_error_benchmark_fast_math) +target_compile_options(snavely_reprojection_error_benchmark_fast_math PRIVATE ${CERES_BENCHMARK_FAST_MATH_FLAGS}) + +add_executable(linear_benchmark linear_benchmark.cc) +add_dependencies_to_benchmark(linear_benchmark) +target_compile_options(linear_benchmark PRIVATE ${CERES_BENCHMARK_FLAGS}) + +add_executable(linear_benchmark_fast_math linear_benchmark.cc) +add_dependencies_to_benchmark(linear_benchmark_fast_math) +target_compile_options(linear_benchmark_fast_math PRIVATE ${CERES_BENCHMARK_FAST_MATH_FLAGS}) + +if(CODE_GENERATION) + target_link_libraries(snavely_reprojection_error_benchmark PUBLIC SnavelyReprojectionError) + target_link_libraries(snavely_reprojection_error_benchmark_fast_math PUBLIC SnavelyReprojectionError) + target_link_libraries(linear_benchmark PUBLIC Linear1CostFunction Linear10CostFunction) + target_link_libraries(linear_benchmark_fast_math PUBLIC Linear1CostFunction Linear10CostFunction) +endif() +
diff --git a/internal/ceres/autodiff_benchmarks/linear_benchmark.cc b/internal/ceres/autodiff_benchmarks/linear_benchmark.cc new file mode 100644 index 0000000..25f6bd6 --- /dev/null +++ b/internal/ceres/autodiff_benchmarks/linear_benchmark.cc
@@ -0,0 +1,119 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2020 Google Inc. All rights reserved. +// http://ceres-solver.org/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: darius.rueckert@fau.de (Darius Rueckert) + +#include <memory> + +#include "benchmark/benchmark.h" +#include "ceres/ceres.h" +#include "codegen/test_utils.h" +#include "linear_cost_functions.h" + +namespace ceres { + +#ifdef WITH_CODE_GENERATION +static void BM_Linear1CodeGen(benchmark::State& state) { + double parameter_block1[] = {1.}; + double* parameters[] = {parameter_block1}; + + double jacobian1[1]; + double residuals[1]; + double* jacobians[] = {jacobian1}; + + std::unique_ptr<ceres::CostFunction> cost_function(new Linear1CostFunction()); + + while (state.KeepRunning()) { + cost_function->Evaluate(parameters, residuals, jacobians); + } +} +BENCHMARK(BM_Linear1CodeGen); +#endif + +static void BM_Linear1AutoDiff(benchmark::State& state) { + using FunctorType = + ceres::internal::CostFunctionToFunctor<Linear1CostFunction>; + + double parameter_block1[] = {1.}; + double* parameters[] = {parameter_block1}; + + double jacobian1[1]; + double residuals[1]; + double* jacobians[] = {jacobian1}; + + std::unique_ptr<ceres::CostFunction> cost_function( + new ceres::AutoDiffCostFunction<FunctorType, 1, 1>(new FunctorType())); + + while (state.KeepRunning()) { + cost_function->Evaluate(parameters, residuals, jacobians); + } +} +BENCHMARK(BM_Linear1AutoDiff); + +#ifdef WITH_CODE_GENERATION +static void BM_Linear10CodeGen(benchmark::State& state) { + double parameter_block1[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}; + double* parameters[] = {parameter_block1}; + + double jacobian1[10 * 10]; + double residuals[10]; + double* jacobians[] = {jacobian1}; + + std::unique_ptr<ceres::CostFunction> cost_function( + new Linear10CostFunction()); + + while (state.KeepRunning()) { + cost_function->Evaluate(parameters, residuals, jacobians); + } +} +BENCHMARK(BM_Linear10CodeGen); +#endif + +static void BM_Linear10AutoDiff(benchmark::State& state) { + using FunctorType = + ceres::internal::CostFunctionToFunctor<Linear10CostFunction>; + + double parameter_block1[] = {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.}; + double* parameters[] = {parameter_block1}; + + double jacobian1[10 * 10]; + double residuals[10]; + double* jacobians[] = {jacobian1}; + + std::unique_ptr<ceres::CostFunction> cost_function( + new ceres::AutoDiffCostFunction<FunctorType, 10, 10>(new FunctorType())); + + while (state.KeepRunning()) { + cost_function->Evaluate(parameters, residuals, jacobians); + } +} +BENCHMARK(BM_Linear10AutoDiff); + +} // namespace ceres + +BENCHMARK_MAIN();
diff --git a/internal/ceres/autodiff_benchmarks/linear_cost_functions.h b/internal/ceres/autodiff_benchmarks/linear_cost_functions.h new file mode 100644 index 0000000..2a9c06c --- /dev/null +++ b/internal/ceres/autodiff_benchmarks/linear_cost_functions.h
@@ -0,0 +1,75 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2020 Google Inc. All rights reserved. +// http://ceres-solver.org/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// * Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// * Neither the name of Google Inc. nor the names of its contributors may be +// used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// Author: darius.rueckert@fau.de (Darius Rueckert) +// +// +#ifndef CERES_INTERNAL_AUTODIFF_BENCHMARKS_LINEAR_COST_FUNCTIONS_H_ +#define CERES_INTERNAL_AUTODIFF_BENCHMARKS_LINEAR_COST_FUNCTIONS_H_ + +#include "ceres/codegen/codegen_cost_function.h" +#include "ceres/rotation.h" +namespace ceres { + +struct Linear1CostFunction : public ceres::CodegenCostFunction<1, 1> { + template <typename T> + bool operator()(const T* const x, T* residuals) const { + residuals[0] = x[0] + T(10); + return true; + } +#ifdef WITH_CODE_GENERATION +#include "benchmarks/linear1costfunction.h" +#else + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + return false; + } +#endif +}; + +struct Linear10CostFunction : public ceres::CodegenCostFunction<10, 10> { + template <typename T> + bool operator()(const T* const x, T* residuals) const { + for (int i = 0; i < 10; ++i) { + residuals[i] = x[i] + T(i); + } + return true; + } +#ifdef WITH_CODE_GENERATION +#include "benchmarks/linear10costfunction.h" +#else + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + return false; + } +#endif +}; +} +#endif // CERES_INTERNAL_AUTODIFF_BENCHMARKS_LINEAR_COST_FUNCTIONS_H_
diff --git a/internal/ceres/autodiff_cost_function_benchmark.cc b/internal/ceres/autodiff_benchmarks/rat43_benchmark.cc similarity index 100% rename from internal/ceres/autodiff_cost_function_benchmark.cc rename to internal/ceres/autodiff_benchmarks/rat43_benchmark.cc
diff --git a/internal/ceres/codegen/snavely_reprojection_error.h b/internal/ceres/autodiff_benchmarks/snavely_reprojection_error.h similarity index 81% rename from internal/ceres/codegen/snavely_reprojection_error.h rename to internal/ceres/autodiff_benchmarks/snavely_reprojection_error.h index d3c9da0..aa86fd7 100644 --- a/internal/ceres/codegen/snavely_reprojection_error.h +++ b/internal/ceres/autodiff_benchmarks/snavely_reprojection_error.h
@@ -29,20 +29,19 @@ // Author: darius.rueckert@fau.de (Darius Rueckert) // // -#ifndef CERES_INTERNAL_CODEGEN_SNAVELY_REPROJECTION_ERROR_H_ -#define CERES_INTERNAL_CODEGEN_SNAVELY_REPROJECTION_ERROR_H_ +#ifndef CERES_INTERNAL_AUTODIFF_BENCHMARK_SNAVELY_REPROJECTION_ERROR_H_ +#define CERES_INTERNAL_AUTODIFF_BENCHMARK_SNAVELY_REPROJECTION_ERROR_H_ #include "ceres/codegen/codegen_cost_function.h" #include "ceres/rotation.h" -namespace test { +namespace ceres { -struct SnavelyReprojectionErrorGen - : public ceres::CodegenCostFunction<2, 9, 3> { - SnavelyReprojectionErrorGen(double observed_x, double observed_y) +struct SnavelyReprojectionError : public ceres::CodegenCostFunction<2, 9, 3> { + SnavelyReprojectionError(double observed_x, double observed_y) : observed_x(observed_x), observed_y(observed_y) {} - SnavelyReprojectionErrorGen() = default; + SnavelyReprojectionError() = default; template <typename T> bool operator()(const T* const camera, const T* const point, @@ -82,11 +81,17 @@ return true; } - -#include "tests/snavelyreprojectionerrorgen.h" +#ifdef WITH_CODE_GENERATION +#include "benchmarks/snavelyreprojectionerror.h" +#else + virtual bool Evaluate(double const* const* parameters, + double* residuals, + double** jacobians) const { + return false; + } +#endif double observed_x; double observed_y; }; - -} // namespace test -#endif // CERES_INTERNAL_CODEGEN_SNAVELY_REPROJECTION_ERROR_H_ +} // namespace ceres +#endif // CERES_INTERNAL_AUTODIFF_BENCHMARK_SNAVELY_REPROJECTION_ERROR_H_
diff --git a/internal/ceres/codegen/codegen_ba_benchmark.cc b/internal/ceres/autodiff_benchmarks/snavely_reprojection_error_benchmark.cc similarity index 76% rename from internal/ceres/codegen/codegen_ba_benchmark.cc rename to internal/ceres/autodiff_benchmarks/snavely_reprojection_error_benchmark.cc index 8d37d75..4a58db2 100644 --- a/internal/ceres/codegen/codegen_ba_benchmark.cc +++ b/internal/ceres/autodiff_benchmarks/snavely_reprojection_error_benchmark.cc
@@ -1,5 +1,5 @@ // Ceres Solver - A fast non-linear least squares minimizer -// Copyright 2018 Google Inc. All rights reserved. +// Copyright 2020 Google Inc. All rights reserved. // http://ceres-solver.org/ // // Redistribution and use in source and binary forms, with or without @@ -26,20 +26,44 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // -// Authors: sameeragarwal@google.com (Sameer Agarwal) -//#define EIGEN_DONT_VECTORIZE +// Author: darius.rueckert@fau.de (Darius Rueckert) + #include <memory> #include "benchmark/benchmark.h" #include "ceres/ceres.h" +#include "codegen/test_utils.h" #include "snavely_reprojection_error.h" -#include "test_utils.h" namespace ceres { -static void BM_BAAutoDiff(benchmark::State& state) { +#ifdef WITH_CODE_GENERATION +static void BM_SnavelyReprojectionCodeGen(benchmark::State& state) { + double parameter_block1[] = {1., 2., 3., 4., 5., 6., 7., 8., 9.}; + double parameter_block2[] = {1., 2., 3.}; + double* parameters[] = {parameter_block1, parameter_block2}; + + double jacobian1[2 * 9]; + double jacobian2[2 * 3]; + double residuals[2]; + double* jacobians[] = {jacobian1, jacobian2}; + + const double x = 0.2; + const double y = 0.3; + + std::unique_ptr<ceres::CostFunction> cost_function( + new SnavelyReprojectionError(x, y)); + + while (state.KeepRunning()) { + cost_function->Evaluate(parameters, residuals, jacobians); + } +} +BENCHMARK(BM_SnavelyReprojectionCodeGen); +#endif + +static void BM_SnavelyReprojectionAutoDiff(benchmark::State& state) { using FunctorType = - ceres::internal::CostFunctionToFunctor<test::SnavelyReprojectionErrorGen>; + ceres::internal::CostFunctionToFunctor<SnavelyReprojectionError>; double parameter_block1[] = {1., 2., 3., 4., 5., 6., 7., 8., 9.}; double parameter_block2[] = {1., 2., 3.}; @@ -57,37 +81,11 @@ new FunctorType(x, y))); while (state.KeepRunning()) { - cost_function->Evaluate( - parameters, residuals, state.range(0) ? jacobians : nullptr); + cost_function->Evaluate(parameters, residuals, jacobians); } } -static void BM_BACodeGen(benchmark::State& state) { - double parameter_block1[] = {1., 2., 3., 4., 5., 6., 7., 8., 9.}; - double parameter_block2[] = {1., 2., 3.}; - double* parameters[] = {parameter_block1, parameter_block2}; - - double jacobian1[2 * 9]; - double jacobian2[2 * 3]; - double residuals[2]; - double* jacobians[] = {jacobian1, jacobian2}; - - const double x = 0.2; - const double y = 0.3; - - std::unique_ptr<ceres::CostFunction> cost_function( - new test::SnavelyReprojectionErrorGen(x, y)); - - while (state.KeepRunning()) { - cost_function->Evaluate( - parameters, residuals, state.range(0) ? jacobians : nullptr); - } -} - -BENCHMARK(BM_BAAutoDiff)->ArgName("Residual")->Arg(0); -BENCHMARK(BM_BAAutoDiff)->ArgName("Residual+Jacobian")->Arg(1); -BENCHMARK(BM_BACodeGen)->ArgName("Residual")->Arg(0); -BENCHMARK(BM_BACodeGen)->ArgName("Residual+Jacobian")->Arg(1); +BENCHMARK(BM_SnavelyReprojectionAutoDiff); } // namespace ceres
diff --git a/internal/ceres/codegen/CMakeLists.txt b/internal/ceres/codegen/CMakeLists.txt index 4dd75ed..4bea21f 100644 --- a/internal/ceres/codegen/CMakeLists.txt +++ b/internal/ceres/codegen/CMakeLists.txt
@@ -88,31 +88,3 @@ UnaryArithmetic BinaryComparison LogicalOperators ScalarFunctions LogicalFunctions Branches) endif() - -if (BUILD_BENCHMARKS) - generate_test_functor(SnavelyReprojectionErrorGen snavely_reprojection_error.h) - - # Benchmark with default compiler flags - add_executable(codegen_ba_benchmark codegen_ba_benchmark.cc) - add_dependencies_to_benchmark(codegen_ba_benchmark) - target_link_libraries(codegen_ba_benchmark PUBLIC SnavelyReprojectionErrorGen) - - # Benchmark with all optimizations (clang only) - if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - - # Always fine - list(APPEND CERES_BENCHMARK_FLAGS "-march=native") - list(APPEND CERES_BENCHMARK_FLAGS "-fno-math-errno" "-fno-trapping-math" "-fassociative-math" "-fno-signed-zeros" "-ffp-contract=fast") - - # This enables the 0*x=0 optimization - list(APPEND CERES_BENCHMARK_FLAGS "-fno-honor-infinities" "-fno-honor-nans") - - # Total overkill but we want to make sure everything inlineable is inlined. - list(APPEND CERES_BENCHMARK_FLAGS "-mllvm" "-inline-threshold=1000000") - - add_executable(codegen_ba_benchmark_fast_math codegen_ba_benchmark.cc) - add_dependencies_to_benchmark(codegen_ba_benchmark_fast_math) - target_link_libraries(codegen_ba_benchmark_fast_math PUBLIC SnavelyReprojectionErrorGen) - target_compile_options(codegen_ba_benchmark_fast_math PRIVATE ${CERES_BENCHMARK_FLAGS}) - endif() -endif()