Adding high-precision timer using OpenMP (fixes issue #41) Change-Id: Ieffe5f789a591c1e766ae619b75f0d7f6cd890f4
diff --git a/internal/ceres/CMakeLists.txt b/internal/ceres/CMakeLists.txt index 16f25cf..cd4e6ac 100644 --- a/internal/ceres/CMakeLists.txt +++ b/internal/ceres/CMakeLists.txt
@@ -88,6 +88,7 @@ types.cc visibility_based_preconditioner.cc visibility.cc + wall_time.cc ) If (${PROTOBUF_FOUND})
diff --git a/internal/ceres/solver.cc b/internal/ceres/solver.cc index 66ca932..84c2756 100644 --- a/internal/ceres/solver.cc +++ b/internal/ceres/solver.cc
@@ -37,20 +37,21 @@ #include "ceres/program.h" #include "ceres/solver_impl.h" #include "ceres/stringprintf.h" +#include "ceres/wall_time.h" namespace ceres { Solver::~Solver() {} -// TODO(sameeragarwal): Use subsecond timers. void Solver::Solve(const Solver::Options& options, Problem* problem, Solver::Summary* summary) { - time_t start_time_seconds = time(NULL); + double start_time_seconds = internal::WallTimeInSeconds(); internal::ProblemImpl* problem_impl = CHECK_NOTNULL(problem)->problem_impl_.get(); internal::SolverImpl::Solve(options, problem_impl, summary); - summary->total_time_in_seconds = time(NULL) - start_time_seconds; + summary->total_time_in_seconds = + internal::WallTimeInSeconds() - start_time_seconds; } void Solve(const Solver::Options& options,
diff --git a/internal/ceres/solver_impl.cc b/internal/ceres/solver_impl.cc index 5d253dd..0ece8ee 100644 --- a/internal/ceres/solver_impl.cc +++ b/internal/ceres/solver_impl.cc
@@ -48,6 +48,7 @@ #include "ceres/schur_ordering.h" #include "ceres/stringprintf.h" #include "ceres/trust_region_minimizer.h" +#include "ceres/wall_time.h" namespace ceres { namespace internal { @@ -189,15 +190,16 @@ minimizer_options.trust_region_strategy = strategy.get(); TrustRegionMinimizer minimizer; - time_t minimizer_start_time = time(NULL); + double minimizer_start_time = WallTimeInSeconds(); minimizer.Minimize(minimizer_options, parameters, summary); - summary->minimizer_time_in_seconds = time(NULL) - minimizer_start_time; + summary->minimizer_time_in_seconds = + WallTimeInSeconds() - minimizer_start_time; } void SolverImpl::Solve(const Solver::Options& original_options, ProblemImpl* original_problem_impl, Solver::Summary* summary) { - time_t solver_start_time = time(NULL); + double solver_start_time = WallTimeInSeconds(); Solver::Options options(original_options); Program* original_program = original_problem_impl->mutable_program(); ProblemImpl* problem_impl = original_problem_impl; @@ -330,7 +332,7 @@ // Collect the discontiguous parameters into a contiguous state vector. reduced_program->ParameterBlocksToStateVector(parameters.data()); - time_t minimizer_start_time = time(NULL); + double minimizer_start_time = WallTimeInSeconds(); summary->preprocessor_time_in_seconds = minimizer_start_time - solver_start_time; @@ -350,7 +352,7 @@ return; } - time_t post_process_start_time = time(NULL); + double post_process_start_time = WallTimeInSeconds(); // Push the contiguous optimized parameters back to the user's parameters. reduced_program->StateVectorToParameterBlocks(parameters.data()); @@ -369,7 +371,8 @@ // Ensure the program state is set to the user parameters on the way out. original_program->SetParameterBlockStatePtrsToUserStatePtrs(); // Stick a fork in it, we're done. - summary->postprocessor_time_in_seconds = time(NULL) - post_process_start_time; + summary->postprocessor_time_in_seconds = + WallTimeInSeconds() - post_process_start_time; } // Strips varying parameters and residuals, maintaining order, and updating
diff --git a/internal/ceres/trust_region_minimizer.cc b/internal/ceres/trust_region_minimizer.cc index d848a17..5e9fc04 100644 --- a/internal/ceres/trust_region_minimizer.cc +++ b/internal/ceres/trust_region_minimizer.cc
@@ -47,6 +47,7 @@ #include "ceres/sparse_matrix.h" #include "ceres/trust_region_strategy.h" #include "ceres/types.h" +#include "ceres/wall_time.h" #include "glog/logging.h" namespace ceres { @@ -117,8 +118,8 @@ void TrustRegionMinimizer::Minimize(const Minimizer::Options& options, double* parameters, Solver::Summary* summary) { - time_t start_time = time(NULL); - time_t iteration_start_time = start_time; + double start_time = WallTimeInSeconds(); + double iteration_start_time = start_time; Init(options); summary->termination_type = NO_CONVERGENCE; @@ -204,9 +205,10 @@ } iteration_summary.iteration_time_in_seconds = - time(NULL) - iteration_start_time; - iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time + - summary->preprocessor_time_in_seconds; + WallTimeInSeconds() - iteration_start_time; + iteration_summary.cumulative_time_in_seconds = + WallTimeInSeconds() - start_time + + summary->preprocessor_time_in_seconds; summary->iterations.push_back(iteration_summary); // Call the various callbacks. @@ -227,7 +229,7 @@ int num_consecutive_invalid_steps = 0; while (true) { - iteration_start_time = time(NULL); + iteration_start_time = WallTimeInSeconds(); if (iteration_summary.iteration >= options_.max_num_iterations) { summary->termination_type = NO_CONVERGENCE; VLOG(1) << "Terminating: Maximum number of iterations reached."; @@ -248,7 +250,7 @@ iteration_summary.step_is_valid = false; iteration_summary.step_is_successful = false; - const time_t strategy_start_time = time(NULL); + const double strategy_start_time = WallTimeInSeconds(); TrustRegionStrategy::PerSolveOptions per_solve_options; per_solve_options.eta = options_.eta; TrustRegionStrategy::Summary strategy_summary = @@ -258,7 +260,7 @@ trust_region_step.data()); iteration_summary.step_solver_time_in_seconds = - time(NULL) - strategy_start_time; + WallTimeInSeconds() - strategy_start_time; iteration_summary.linear_solver_iterations = strategy_summary.num_iterations; @@ -505,9 +507,10 @@ } iteration_summary.iteration_time_in_seconds = - time(NULL) - iteration_start_time; - iteration_summary.cumulative_time_in_seconds = time(NULL) - start_time + - summary->preprocessor_time_in_seconds; + WallTimeInSeconds() - iteration_start_time; + iteration_summary.cumulative_time_in_seconds = + WallTimeInSeconds() - start_time + + summary->preprocessor_time_in_seconds; summary->iterations.push_back(iteration_summary); switch (RunCallbacks(iteration_summary)) {
diff --git a/internal/ceres/wall_time.cc b/internal/ceres/wall_time.cc new file mode 100644 index 0000000..0dce19f --- /dev/null +++ b/internal/ceres/wall_time.cc
@@ -0,0 +1,49 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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: strandmark@google.com (Petter Strandmark) + +#ifdef CERES_USE_OPENMP +#include <omp.h> +#else +#include <ctime> +#endif + +namespace ceres { +namespace internal { + +double WallTimeInSeconds() { +#ifdef CERES_USE_OPENMP + return omp_get_wtime(); +#else + return static_cast<double>(std::time(NULL)); +#endif +} + +} // namespace internal +} // namespace ceres
diff --git a/internal/ceres/wall_time.h b/internal/ceres/wall_time.h new file mode 100644 index 0000000..1a6e3bb --- /dev/null +++ b/internal/ceres/wall_time.h
@@ -0,0 +1,44 @@ +// Ceres Solver - A fast non-linear least squares minimizer +// Copyright 2012 Google Inc. All rights reserved. +// http://code.google.com/p/ceres-solver/ +// +// 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: strandmark@google.com (Petter Strandmark) + +#ifndef CERES_INTERNAL_WALL_TIME_H_ +#define CERES_INTERNAL_WALL_TIME_H_ + +namespace ceres { +namespace internal { + +// Returns time, in seconds, from some arbitrary starting point. Has very +// high precision if OpenMP is available, otherwise only second granularity. +double WallTimeInSeconds(); + +} // namespace internal +} // namespace ceres + +#endif // CERES_INTERNAL_WALL_TIME_H_