[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 ¶meters) {
- 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 ¶meters,
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 ¶meters,
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 ¶meters,
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 ¶meters) {
+ 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>(¶meters.maxIterations)->default_value(500),
"Maximum number of iterations to run the solver.")
+ ("maxRuntime",
+ po::value<int>(¶meters.maxIterations)->default_value(86400),
+ "Maximum amount of time to run the solver in seconds.")
("dualityGapThreshold",
po::value<Real>(¶meters.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