[sdpb] 72/233: Added checkpointing

Tobias Hansen thansen at moszumanska.debian.org
Thu Mar 9 04:06:20 UTC 2017


This is an automated email from the git hooks/post-receive script.

thansen pushed a commit to branch master
in repository sdpb.

commit 0006494688acfd054eafbb2416a83f14f359a0ba
Author: David Simmons-Duffin <dsd at neptune.sns.ias.edu>
Date:   Mon Aug 11 18:28:47 2014 -0400

    Added checkpointing
---
 src/SDPSolver.cpp | 123 ++++++++++++++++++++++++++++++++++++++++++++----------
 src/SDPSolver.h   |  41 +++---------------
 src/Timer.h       |  38 -----------------
 src/Timers.h      |  28 +++++++++++++
 src/main.cpp      |  16 +++++--
 src/serialize.h   |  76 +++++++++++++++++++++++++++++++++
 6 files changed, 224 insertions(+), 98 deletions(-)

diff --git a/src/SDPSolver.cpp b/src/SDPSolver.cpp
index 6a146ac..06824a2 100644
--- a/src/SDPSolver.cpp
+++ b/src/SDPSolver.cpp
@@ -1,9 +1,16 @@
 #include <iostream>
 #include <ostream>
 #include "omp.h"
+#include "boost/archive/text_oarchive.hpp"
+#include "boost/archive/text_iarchive.hpp"
+#include "boost/filesystem.hpp"
+#include "boost/filesystem/fstream.hpp"
 #include "SDPSolver.h"
-#include "Timer.h"
+#include "serialize.h"
+#include "Timers.h"
 
+using boost::filesystem::path;
+using boost::timer::nanosecond_type;
 using std::cout;
 
 SDPSolver::SDPSolver(const SDP &sdp):
@@ -92,7 +99,6 @@ SDPSolver::SDPSolver(const SDP &sdp):
     schurStabilizeVectors[b].resize(SchurBlocks.blocks[b].rows);
 }
 
-
 void printSolverHeader() {
   cout << "     mu       P-obj       D-obj     gap         P-err        D-err       P-step   D-step   beta\n";
   cout << "---------------------------------------------------------------------------------------------------\n";
@@ -440,14 +446,6 @@ void computeSchurRHS(const SDP &sdp,
   }
 }
 
-void SDPSolver::initialize(const SDPSolverParameters &parameters) {
-  fillVector(x, 0);
-  X.setZero();
-  X.addDiagonal(parameters.initialMatrixScale);
-  Y.setZero();
-  Y.addDiagonal(parameters.initialMatrixScale);
-}
-
 // PrimalResidues = sum_p F_p x_p - X - F_0
 //
 void computePrimalResidues(const SDP &sdp,
@@ -635,9 +633,27 @@ SDPSolverTerminateReason SDPSolver::run(const SDPSolverParameters &parameters,
                                         const path outFile,
                                         const path checkpointFile) {
   printSolverHeader();
-  timer.start("runSolver");
+  timers["Run solver"].start();
+  timers["Save checkpoint"].start();
+  nanosecond_type const checkpointNanoseconds = parameters.checkpointInterval * 1000000000LL;
+  nanosecond_type const maxRuntimeNanoseconds = parameters.maxRuntime * 1000000000LL;
+  SDPSolverTerminateReason finished = MaxIterationsExceeded;
+
+  for (int iteration = 1;; iteration++) {
+    
+    if (timers["Save checkpoint"].elapsed().wall >= checkpointNanoseconds) {
+      saveCheckpoint(checkpointFile);
+      timers["Save checkpoint"].start();
+    }
+    if (timers["Run solver"].elapsed().wall >= maxRuntimeNanoseconds) {
+      finished = MaxRuntimeExceeded;
+      break;
+    }
+    if (iteration > parameters.maxIterations) {
+      finished = MaxIterationsExceeded;
+      break;
+    }
 
-  for (int iteration = 1; iteration <= parameters.maxIterations; iteration++) {
     // Maintain the invariant x_B = g + E^T x_N
     basicCompletion(dualObjectiveReduced, FreeVarMatrixReduced, basicIndices, nonBasicIndices, x);
 
@@ -659,15 +675,18 @@ SDPSolverTerminateReason SDPSolver::run(const SDPSolverParameters &parameters,
     status.primalObjective = primalObjectiveValue(sdp, x);
     status.dualObjective   = dualObjectiveValue(sdp, dualObjectiveReduced, basicIndices, dualResidues);
 
-    const bool isPrimalFeasible = status.isPrimalFeasible(parameters);
-    const bool isDualFeasible   = status.isDualFeasible(parameters);
-    const bool isOptimal        = status.isOptimal(parameters);
+    const bool isPrimalFeasible = status.primalError  < parameters.primalErrorThreshold;
+    const bool isDualFeasible   = status.dualError    < parameters.dualErrorThreshold;
+    const bool isOptimal        = status.dualityGap() < parameters.dualityGapThreshold;
     const bool reductionSwitch  = true;
 
-    if (isPrimalFeasible && isDualFeasible && isOptimal)
-      return PrimalDualOptimal;
-    else if (isDualFeasible && status.dualObjective > parameters.maxDualObjective)
-      return DualFeasibleMaxObjectiveExceeded;
+    if (isPrimalFeasible && isDualFeasible && isOptimal) {
+      finished = PrimalDualOptimal;
+      break;
+    } else if (isDualFeasible && status.dualObjective > parameters.maxDualObjective) {
+      finished = DualFeasibleMaxObjectiveExceeded;
+      break;
+    }
 
     initializeSchurComplementSolver(BilinearPairingsXInv, BilinearPairingsY);
 
@@ -700,9 +719,28 @@ SDPSolverTerminateReason SDPSolver::run(const SDPSolverParameters &parameters,
     dY *= dualStepLength;
     Y += dY;
   }
+  
+  timers["Run solver"].stop();
+  saveCheckpoint(checkpointFile);
+  timers["Save checkpoint"].start();
+  return finished;
+}
 
-  timer.stop("runSolver");
-  return MaxIterationsExceeded;
+ostream& operator<<(ostream& os, const SDPSolverParameters& p) {
+  os << "maxIterations                = " << p.maxIterations                << endl;
+  os << "maxRuntime                   = " << p.maxRuntime                   << endl;
+  os << "checkpointInterval           = " << p.checkpointInterval           << endl;
+  os << "precision(actual)            = " << p.precision << "(" << mpf_get_default_prec() << ")" << endl;
+  os << "maxThreads                   = " << p.maxThreads                   << endl;
+  os << "dualityGapThreshold          = " << p.dualityGapThreshold          << endl;
+  os << "primalErrorThreshold         = " << p.primalErrorThreshold         << endl;
+  os << "dualErrorThreshold           = " << p.dualErrorThreshold           << endl;
+  os << "initialMatrixScale           = " << p.initialMatrixScale           << endl;
+  os << "feasibleCenteringParameter   = " << p.feasibleCenteringParameter   << endl;
+  os << "infeasibleCenteringParameter = " << p.infeasibleCenteringParameter << endl;
+  os << "stepLengthReduction          = " << p.stepLengthReduction          << endl;
+  os << "maxDualObjective             = " << p.maxDualObjective             << endl;
+  return os;
 }
 
 ostream &operator<<(ostream& os, const SDPSolverTerminateReason& r) {
@@ -713,9 +751,52 @@ ostream &operator<<(ostream& os, const SDPSolverTerminateReason& r) {
   case MaxIterationsExceeded:
     os << "maxIterations exceeded.";
     break;
+  case MaxRuntimeExceeded:
+    os << "maxRuntime exceeded.";
+    break;
   case DualFeasibleMaxObjectiveExceeded:
     os << "found dual feasible solution with dualObjective exceeding maxDualObjective.";
     break;
   }
   return os;
 }
+
+ostream& operator<<(ostream& os, const SDPSolverStatus& s) {
+  os << "primalObjective = " << s.primalObjective << endl;
+  os << "dualObjective   = " << s.dualObjective << endl;
+  os << "dualityGap      = " << s.dualityGap() << endl;
+  os << "primalError     = " << s.primalError << endl;
+  os << "dualError       = " << s.dualError << endl;
+  return os;
+}
+
+void backupCheckpointFile(path const& checkpointFile) {
+  path backupFile(checkpointFile);
+  backupFile.replace_extension(".ck.bk");
+  cout << "Saving checkpoint backup: " << backupFile << endl;
+  copy_file(checkpointFile, backupFile, boost::filesystem::copy_option::overwrite_if_exists);
+}
+
+void SDPSolver::saveCheckpoint(const path &checkpointFile) {
+  if (exists(checkpointFile))
+    backupCheckpointFile(checkpointFile);
+  boost::filesystem::ofstream ofs(checkpointFile);
+  boost::archive::text_oarchive ar(ofs);
+  cout << "Saving checkpoint       : " << checkpointFile << endl;
+  boost::serialization::serializeSDPSolverState(ar, x, X, Y);
+}
+
+void SDPSolver::loadCheckpoint(const path &checkpointFile) {
+  boost::filesystem::ifstream ifs(checkpointFile);
+  boost::archive::text_iarchive ar(ifs);
+  cout << "Loading checkpoint from : " << checkpointFile << endl;
+  boost::serialization::serializeSDPSolverState(ar, x, X, Y);
+}
+
+void SDPSolver::initialize(const SDPSolverParameters &parameters) {
+  fillVector(x, 0);
+  X.setZero();
+  X.addDiagonal(parameters.initialMatrixScale);
+  Y.setZero();
+  Y.addDiagonal(parameters.initialMatrixScale);
+}
diff --git a/src/SDPSolver.h b/src/SDPSolver.h
index 0b63ba4..184dd04 100644
--- a/src/SDPSolver.h
+++ b/src/SDPSolver.h
@@ -19,6 +19,7 @@ using boost::filesystem::path;
 class SDPSolverParameters {
 public:
   int maxIterations;
+  int maxRuntime;
   int checkpointInterval;
   int precision;
   int maxThreads;
@@ -42,26 +43,13 @@ public:
     maxDualObjective            .set_prec(precision);
   }
 
-  friend ostream& operator<<(ostream& os, const SDPSolverParameters& p) {
-    os << "maxIterations                = " << p.maxIterations                << endl;
-    os << "checkpointInterval           = " << p.checkpointInterval           << endl;
-    os << "precision(actual)            = " << p.precision << "(" << mpf_get_default_prec() << ")" << endl;
-    os << "maxThreads                   = " << p.maxThreads                   << endl;
-    os << "dualityGapThreshold          = " << p.dualityGapThreshold          << endl;
-    os << "primalErrorThreshold         = " << p.primalErrorThreshold         << endl;
-    os << "dualErrorThreshold           = " << p.dualErrorThreshold           << endl;
-    os << "initialMatrixScale           = " << p.initialMatrixScale           << endl;
-    os << "feasibleCenteringParameter   = " << p.feasibleCenteringParameter   << endl;
-    os << "infeasibleCenteringParameter = " << p.infeasibleCenteringParameter << endl;
-    os << "stepLengthReduction          = " << p.stepLengthReduction          << endl;
-    os << "maxDualObjective             = " << p.maxDualObjective             << endl;
-    return os;
-  }
+  friend ostream& operator<<(ostream& os, const SDPSolverParameters& p);
 };
 
 enum SDPSolverTerminateReason {
   PrimalDualOptimal,
   MaxIterationsExceeded,
+  MaxRuntimeExceeded,
   DualFeasibleMaxObjectiveExceeded,
 };
 
@@ -79,26 +67,7 @@ public:
       max(Real(abs(primalObjective) + abs(dualObjective)), Real(1));
   }
 
-  bool isPrimalFeasible(const SDPSolverParameters &p) {
-    return primalError < p.primalErrorThreshold;
-  }
-
-  bool isDualFeasible(const SDPSolverParameters &p) {
-    return dualError < p.dualErrorThreshold;
-  }
-
-  bool isOptimal(const SDPSolverParameters &p) {
-    return dualityGap() < p.dualityGapThreshold;
-  }
-
-  friend ostream& operator<<(ostream& os, const SDPSolverStatus& s) {
-    os << "primalObjective = " << s.primalObjective << endl;
-    os << "dualObjective   = " << s.dualObjective << endl;
-    os << "dualityGap      = " << s.dualityGap() << endl;
-    os << "primalError     = " << s.primalError << endl;
-    os << "dualError       = " << s.dualError << endl;
-    return os;
-  }
+  friend ostream& operator<<(ostream& os, const SDPSolverStatus& s);
 };
 
 class SDPSolver {
@@ -160,6 +129,8 @@ public:
                                        const BlockDiagonalMatrix &BilinearPairingsY);
   void solveSchurComplementEquation(Vector &dx);
   void computeSearchDirection(const Real &beta, const Real &mu, const bool correctorPhase);
+  void saveCheckpoint(const path &checkpointPath);
+  void loadCheckpoint(const path &checkpointPath);
 };
 
 #endif  // SDP_BOOTSTRAP_SDPSOLVER_H_
diff --git a/src/Timer.h b/src/Timer.h
deleted file mode 100644
index b7bd19b..0000000
--- a/src/Timer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef SDP_BOOTSTRAP_TIMER_H_
-#define SDP_BOOTSTRAP_TIMER_H_
-
-#include <iostream>
-#include <ostream>
-#include <map>
-#include "boost/timer/timer.hpp"
-
-using std::map;
-using std::string;
-using std::ostream;
-using boost::timer::cpu_timer;
-
-class Timer {
-public:
-  map<string,cpu_timer> timers;
-
-  void start(const string &t) {
-    timers[t].resume();
-  }
-
-  void stop(const string &t) {
-    timers[t].stop();
-  }
-
-  friend ostream& operator<<(ostream& os, const Timer& t) {
-    for (map<string,cpu_timer>::const_iterator it = t.timers.begin();
-         it != t.timers.end();
-         ++it) {
-      os << it->first << "\t:" << it->second.format();
-    }
-    return os;
-  }
-};
-
-extern Timer timer;
-
-#endif  // SDP_BOOTSTRAP_TIMER_H_
diff --git a/src/Timers.h b/src/Timers.h
new file mode 100644
index 0000000..e665f7a
--- /dev/null
+++ b/src/Timers.h
@@ -0,0 +1,28 @@
+#ifndef SDP_BOOTSTRAP_TIMERS_H_
+#define SDP_BOOTSTRAP_TIMERS_H_
+
+#include <iostream>
+#include <ostream>
+#include <map>
+#include "boost/timer/timer.hpp"
+
+using std::map;
+using std::string;
+using std::ostream;
+using boost::timer::cpu_timer;
+
+class Timers : public map<string,cpu_timer> {
+public:
+  friend ostream& operator<<(ostream& os, const Timers& t) {
+    for (map<string,cpu_timer>::const_iterator it = t.begin();
+         it != t.end();
+         ++it) {
+      os << it->first << "\t:" << it->second.format();
+    }
+    return os;
+  }
+};
+
+extern Timers timers;
+
+#endif  // SDP_BOOTSTRAP_TIMERS_H_
diff --git a/src/main.cpp b/src/main.cpp
index 21123c3..a1909e5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -6,7 +6,7 @@
 #include "boost/date_time/posix_time/posix_time.hpp"
 #include "boost/program_options.hpp"
 #include "types.h"
-#include "Timer.h"
+#include "Timers.h"
 #include "SDP.h"
 #include "parse.h"
 #include "SDPSolver.h"
@@ -20,7 +20,7 @@ using boost::posix_time::second_clock;
 
 namespace po = boost::program_options;
 
-Timer timer;
+Timers timers;
 
 int solveSDP(const path &sdpFile,
              const path &outFile,
@@ -44,13 +44,18 @@ int solveSDP(const path &sdpFile,
   const SDP sdp = readBootstrapSDP(sdpFile);
 
   SDPSolver solver(sdp);
-  solver.initialize(parameters);
+
+  if (exists(checkpointFile))
+    solver.loadCheckpoint(checkpointFile);
+  else
+    solver.initialize(parameters);
+
   SDPSolverTerminateReason reason = solver.run(parameters, outFile, checkpointFile);
 
   cout << "\nTerminated: " << reason << endl;
   cout << "\nStatus:\n";
   cout << solver.status << endl;
-  cout << timer << endl;
+  cout << timers << endl;
 
   return 0;
 }
@@ -100,6 +105,9 @@ int main(int argc, char** argv) {
     ("maxIterations",
      po::value<int>(&parameters.maxIterations)->default_value(500),
      "Maximum number of iterations to run the solver.")
+    ("maxRuntime",
+     po::value<int>(&parameters.maxIterations)->default_value(86400),
+     "Maximum amount of time to run the solver in seconds.")
     ("dualityGapThreshold",
      po::value<Real>(&parameters.dualityGapThreshold)->default_value(Real("1e-30")),
      "Threshold for duality gap (roughly the difference in primal and dual "
diff --git a/src/serialize.h b/src/serialize.h
new file mode 100644
index 0000000..037ba41
--- /dev/null
+++ b/src/serialize.h
@@ -0,0 +1,76 @@
+#ifndef SDP_BOOTSTRAP_SERIALIZE_H_
+#define SDP_BOOTSTRAP_SERIALIZE_H_
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <gmpxx.h>
+#include "boost/serialization/serialization.hpp"
+#include "boost/serialization/base_object.hpp"
+#include "boost/serialization/utility.hpp"
+#include "boost/serialization/vector.hpp"
+#include "boost/serialization/string.hpp"
+#include "boost/serialization/split_free.hpp"
+#include "boost/archive/text_iarchive.hpp"
+#include "boost/archive/text_oarchive.hpp"
+#include "boost/filesystem.hpp"
+#include "boost/filesystem/fstream.hpp"
+#include "types.h"
+#include "Vector.h"
+#include "Matrix.h"
+#include "BlockDiagonalMatrix.h"
+
+using boost::filesystem::path;
+using boost::archive::text_iarchive;
+using std::vector;
+
+namespace boost {
+  namespace serialization {
+
+    template<class Archive>
+    void load(Archive& ar, mpf_class& f, unsigned int version) {
+      std::string s;
+      ar & s;
+      f = mpf_class(s);
+    }
+
+    template<class Archive>
+    void save(Archive& ar, mpf_class const& f, unsigned int version) {
+      std::ostringstream os;
+      os.precision(f.get_prec());
+      os << f;
+      std::string s = os.str();
+      ar & s;
+    }
+
+    template<class Archive>
+    void serialize(Archive& ar, Matrix& m, const unsigned int version) {
+      ar & m.rows;
+      ar & m.cols;
+      ar & m.elements;
+    }
+
+    template<class Archive>
+    void serialize(Archive& ar, BlockDiagonalMatrix& m, const unsigned int version) {
+      ar & m.dim;
+      ar & m.blocks;
+      ar & m.blockStartIndices;
+    }
+
+    template<class Archive>
+    void serializeSDPSolverState(Archive& ar, Vector &x, BlockDiagonalMatrix &X, BlockDiagonalMatrix &Y) {
+      ar & x;
+      ar & X;
+      ar & Y;
+    }
+
+  } // namespace serialization
+} // namespace boost
+
+
+BOOST_SERIALIZATION_SPLIT_FREE(mpf_class)
+BOOST_CLASS_VERSION(mpf_class, 0)
+BOOST_CLASS_TRACKING(Matrix,              boost::serialization::track_never)
+BOOST_CLASS_TRACKING(BlockDiagonalMatrix, boost::serialization::track_never)
+
+#endif  // SDP_BOOTSTRAP_SERIALIZE_H_

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/sdpb.git



More information about the debian-science-commits mailing list