Add checkpoint readers and writers and tests
This commit is contained in:
parent
78d67070c0
commit
be39eeb776
@ -1,7 +1,7 @@
|
|||||||
include $(top_srcdir)/etc/make/emacs.mk
|
include $(top_srcdir)/etc/make/emacs.mk
|
||||||
include $(top_srcdir)/atrip.mk
|
include $(top_srcdir)/atrip.mk
|
||||||
|
|
||||||
SUBDIRS = src bench
|
SUBDIRS = src bench test
|
||||||
|
|
||||||
|
|
||||||
_ATRIPSRCS = Sources.mk
|
_ATRIPSRCS = Sources.mk
|
||||||
|
|||||||
200
atrip.org
200
atrip.org
@ -6,6 +6,45 @@
|
|||||||
The algorithm uses two main data types, the =Slice= and the
|
The algorithm uses two main data types, the =Slice= and the
|
||||||
=SliceUnion= as a container and resource manager of the =Slice=.
|
=SliceUnion= as a container and resource manager of the =Slice=.
|
||||||
|
|
||||||
|
* Tests :noexport:test:
|
||||||
|
|
||||||
|
We will try to test some programatic functionality in atrip too, and
|
||||||
|
mostly we will append all tests in a single file, however this might
|
||||||
|
change for special purpose test functionality.
|
||||||
|
|
||||||
|
#+begin_src c++ :tangle (atrip-test-main) :noweb yes
|
||||||
|
#include <atrip.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
<<testcase-headers>>
|
||||||
|
|
||||||
|
<<testcase-prologs>>
|
||||||
|
|
||||||
|
#define TESTCASE(_name, ...) { \
|
||||||
|
std::cout << "\x1b[35m-> \x1b[0m" \
|
||||||
|
<< _name \
|
||||||
|
<< std::endl; \
|
||||||
|
__VA_ARGS__ \
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
<<testcase>>
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
Therefore, small tests can be written like
|
||||||
|
|
||||||
|
#+begin_src example
|
||||||
|
,#+begin_src c++ :noweb-ref testcase
|
||||||
|
// your c++ snippet of code
|
||||||
|
,#+end_src
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
* The slice
|
* The slice
|
||||||
|
|
||||||
The following section introduces the idea of a slice.
|
The following section introduces the idea of a slice.
|
||||||
@ -2988,6 +3027,7 @@ namespace atrip {
|
|||||||
#include <atrip/Equations.hpp>
|
#include <atrip/Equations.hpp>
|
||||||
#include <atrip/SliceUnion.hpp>
|
#include <atrip/SliceUnion.hpp>
|
||||||
#include <atrip/Unions.hpp>
|
#include <atrip/Unions.hpp>
|
||||||
|
#include <atrip/Checkpoint.hpp>
|
||||||
|
|
||||||
using namespace atrip;
|
using namespace atrip;
|
||||||
|
|
||||||
@ -3671,6 +3711,166 @@ namespace atrip {
|
|||||||
}
|
}
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
* Checkpoints and restarts
|
||||||
|
|
||||||
|
** Prolog :noexport:
|
||||||
|
|
||||||
|
#+begin_src c++ :tangle (atrip-checkpoint-h)
|
||||||
|
#pragma once
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include <atrip/Atrip.hpp>
|
||||||
|
|
||||||
|
namespace atrip {
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
** Introduction
|
||||||
|
|
||||||
|
For very heavy workloads and possible bugs in the packages it is often
|
||||||
|
useful to restart from a given state of the calculation.
|
||||||
|
|
||||||
|
An advantage of the =atrip= algorithm is that the state is essentially given
|
||||||
|
by the
|
||||||
|
|
||||||
|
#+begin_src yaml
|
||||||
|
No: number of occupied orbitals
|
||||||
|
Nv: number of virtual orbitals
|
||||||
|
Nranks: number of ranks
|
||||||
|
Nnodes: number of nodes
|
||||||
|
Energy: the current total energy of the iterations
|
||||||
|
Iteration: the iteration number
|
||||||
|
Distribution: the type of distribution
|
||||||
|
RankRoundRobin: wether the round robin is done through the ranks or
|
||||||
|
nodes
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
This information we can encode in a simple struct
|
||||||
|
|
||||||
|
#+name: checkpoint-definition
|
||||||
|
#+begin_src c++ :tangle (atrip-checkpoint-h)
|
||||||
|
// template <typename F>
|
||||||
|
struct Checkpoint {
|
||||||
|
size_t no, nv;
|
||||||
|
size_t nranks;
|
||||||
|
size_t nnodes;
|
||||||
|
double energy;
|
||||||
|
size_t iteration;
|
||||||
|
// TODO
|
||||||
|
// Input<F>::TuplesDistribution distribution(GROUP_AND_SORT);
|
||||||
|
bool rankRoundRobin;
|
||||||
|
};
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
** Input and output
|
||||||
|
|
||||||
|
In order to read and write the [[checkpoint-definition][checkpoint information]], we need
|
||||||
|
to define a format. We choose a simple yaml format without any kind
|
||||||
|
of depth, so that we can write quite easily a parser.
|
||||||
|
|
||||||
|
#+begin_src c++ :tangle (atrip-checkpoint-h)
|
||||||
|
void write_checkpoint(Checkpoint const& c, std::string const& filepath) {
|
||||||
|
std::ofstream out(filepath);
|
||||||
|
out << "No: " << c.no
|
||||||
|
<< "\n"
|
||||||
|
<< "Nv: " << c.nv
|
||||||
|
<< "\n"
|
||||||
|
<< "Nranks: " << c.nranks
|
||||||
|
<< "\n"
|
||||||
|
<< "Nnodes: " << c.nnodes
|
||||||
|
<< "\n"
|
||||||
|
<< "Energy: " << std::setprecision(19) << c.energy
|
||||||
|
<< "\n"
|
||||||
|
<< "Iteration: " << c.iteration
|
||||||
|
<< "\n"
|
||||||
|
<< "RankRoundRobin: " << (c.rankRoundRobin ? "true" : "false")
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
Checkpoint read_checkpoint(std::string const& filepath) {
|
||||||
|
std::ifstream in(filepath);
|
||||||
|
Checkpoint c;
|
||||||
|
// trim chars from the string, to be more sure and not use regexes
|
||||||
|
auto trim = [](std::string& s, std::string const& chars) {
|
||||||
|
s.erase(0, s.find_first_not_of(chars));
|
||||||
|
s.erase(s.find_last_not_of(chars) + 1);
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
for (std::string header, value; std::getline(in, header, ':');) {
|
||||||
|
std::getline(in, value, '\n');
|
||||||
|
trim(value, " \t"); // trim all whitespaces
|
||||||
|
trim(header, " \t");
|
||||||
|
|
||||||
|
/**/ if (header == "No") c.no = std::atoi(value.c_str());
|
||||||
|
else if (header == "Nv") c.nv = std::atoi(value.c_str());
|
||||||
|
else if (header == "Nranks") c.nranks = std::atoi(value.c_str());
|
||||||
|
else if (header == "Nnodes") c.nnodes = std::atoi(value.c_str());
|
||||||
|
else if (header == "Energy") c.energy = std::atof(value.c_str());
|
||||||
|
else if (header == "Iteration") c.iteration = std::atoi(value.c_str());
|
||||||
|
else if (header == "RankRoundRobin") c.rankRoundRobin = (value[0] == 't');
|
||||||
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
*** Test :noexport:test:
|
||||||
|
|
||||||
|
#+begin_src c++ :noweb-ref testcase-headers
|
||||||
|
#include <atrip/Checkpoint.hpp>
|
||||||
|
using namespace atrip;
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
#+begin_src c++ :noweb-ref testcase
|
||||||
|
#define _CMP_CHECK(what) \
|
||||||
|
std::cout << "\t Checking " << #what << std::endl; \
|
||||||
|
assert(in.what == what); \
|
||||||
|
assert(out.what == what);
|
||||||
|
|
||||||
|
TESTCASE("Testing checkpoint reader and writers",
|
||||||
|
const std::string out_checkpoint = "/tmp/checkpoint.yaml";
|
||||||
|
const double energy = -1.493926352289995443;
|
||||||
|
const size_t no = 154, nv = 1500, nranks = 48*10, nnodes = 10;
|
||||||
|
const size_t iteration = 546;
|
||||||
|
std::cout << "\twriting to " << out_checkpoint << std::endl;
|
||||||
|
|
||||||
|
for (bool rankRoundRobin: {true, false}) {
|
||||||
|
atrip::Checkpoint out = {no,
|
||||||
|
nv,
|
||||||
|
nranks,
|
||||||
|
nnodes,
|
||||||
|
energy,
|
||||||
|
iteration,
|
||||||
|
rankRoundRobin}, in;
|
||||||
|
|
||||||
|
|
||||||
|
write_checkpoint(out, out_checkpoint);
|
||||||
|
in = read_checkpoint(out_checkpoint);
|
||||||
|
|
||||||
|
_CMP_CHECK(no);
|
||||||
|
_CMP_CHECK(nv);
|
||||||
|
_CMP_CHECK(nranks);
|
||||||
|
_CMP_CHECK(nnodes);
|
||||||
|
_CMP_CHECK(iteration);
|
||||||
|
_CMP_CHECK(rankRoundRobin);
|
||||||
|
_CMP_CHECK(energy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
)
|
||||||
|
#undef _CMP_CHECK
|
||||||
|
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
** Epilog :noexport:
|
||||||
|
#+begin_src c++ :tangle (atrip-checkpoint-h)
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
|
||||||
* Include header
|
* Include header
|
||||||
|
|
||||||
#+begin_src c++ :tangle (atrip-main-h)
|
#+begin_src c++ :tangle (atrip-main-h)
|
||||||
|
|||||||
@ -142,6 +142,7 @@ dnl -----------------------------------------------------------------------
|
|||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
bench/Makefile
|
bench/Makefile
|
||||||
|
test/Makefile
|
||||||
docs/Makefile
|
docs/Makefile
|
||||||
docs/conf.py:docs/conf.py
|
docs/conf.py:docs/conf.py
|
||||||
docs/Doxyfile:docs/Doxyfile
|
docs/Doxyfile:docs/Doxyfile
|
||||||
|
|||||||
17
test/Makefile.am
Normal file
17
test/Makefile.am
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
include $(top_srcdir)/atrip.mk
|
||||||
|
|
||||||
|
AM_CPPFLAGS = -I$(top_srcdir)/include/ $(CTF_CPPFLAGS)
|
||||||
|
AM_LDFLAGS = @LAPACK_LIBS@ @BLAS_LIBS@
|
||||||
|
|
||||||
|
bin_PROGRAMS = main
|
||||||
|
main_SOURCES = main.cxx
|
||||||
|
|
||||||
|
|
||||||
|
test_main_LDADD = \
|
||||||
|
$(top_builddir)/src/libatrip.a
|
||||||
|
|
||||||
|
if WITH_BUILD_CTF
|
||||||
|
test_main_LDADD += $(CTF_BUILD_PATH)/lib/libctf.a
|
||||||
|
else
|
||||||
|
test_main_LDADD += @LIBCTF_LD_LIBRARY_PATH@/libctf.a
|
||||||
|
endif
|
||||||
Loading…
Reference in New Issue
Block a user