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_