FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
checkpoint_control.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
9#include <kernel/util/dist.hpp>
10#include <kernel/util/dist_file_io.hpp>
11#include <kernel/util/string.hpp>
12#include <kernel/util/binary_stream.hpp>
13#include <kernel/util/pack.hpp>
14#include <kernel/lafem/container.hpp>
15
16#include <cstdio>
17#include <cstring>
18#include <map>
19#include <sys/stat.h>
20#include <memory>
21
22namespace FEAT
23{
24 namespace Control
25 {
33 {
34 public:
43 virtual std::uint64_t get_checkpoint_size(LAFEM::SerialConfig & config) = 0;
44
53 virtual void restore_from_checkpoint_data(std::vector<char> & data) = 0;
54
63 virtual std::uint64_t set_checkpoint_data(std::vector<char> & data, LAFEM::SerialConfig & config) = 0;
64
65 protected:
66 virtual ~Checkpointable() {}
67 }; // class Checkpointable
68
75 template <typename Object_>
77 {
78 private:
79 Object_ & _object;
80
81 public:
83 explicit CheckpointableWrapper(Object_ & obj) :
84 _object(obj) {}
85
94 virtual std::uint64_t get_checkpoint_size(LAFEM::SerialConfig & config) override
95 {
96 return _object.get_checkpoint_size(config);
97 }
98
107 virtual void restore_from_checkpoint_data(std::vector<char> & data) override
108 {
109 _object.restore_from_checkpoint_data(data);
110 }
111
120 virtual std::uint64_t set_checkpoint_data(std::vector<char> & data, LAFEM::SerialConfig & config) override
121 {
122 return _object.set_checkpoint_data(data, config);
123 }
124 }; // class CheckpointableWrapper
125
141 {
142 private:
144 std::map<String, std::shared_ptr<Checkpointable>> _checkpointable_by_identifier;
146 std::vector<char> _input_array;
148 std::map<String, std::uint64_t> _offset_by_identifier;
153
163 std::uint64_t _collect_checkpoint_data(std::vector<char> & buffer)
164 {
165 std::uint64_t checkpoint_size(0u);
166 std::uint64_t real_size(0u);
167 std::map<String, std::tuple<std::uint64_t, std::uint64_t>> sizes;
168
169 for (auto const & it : _checkpointable_by_identifier)
170 {
171 std::uint64_t identifierlength = (std::uint64_t)it.first.length();
172 std::uint64_t datalength = it.second->get_checkpoint_size(_config);
173
174 checkpoint_size += identifierlength + datalength + sizeof(std::uint64_t) + sizeof(std::uint64_t);
175 real_size += identifierlength + sizeof(std::uint64_t) + sizeof(std::uint64_t);
176 sizes[it.first] = std::make_tuple(identifierlength, datalength);
177 }
178
179 buffer.reserve(checkpoint_size);
180
181 for (auto const & it : _checkpointable_by_identifier)
182 {
183 char * cidentifierlength = reinterpret_cast<char *>(&std::get<0>(sizes[it.first]));
184 buffer.insert(std::end(buffer), cidentifierlength, cidentifierlength + sizeof(std::uint64_t));
185 buffer.insert(std::end(buffer), it.first.begin(), it.first.end());
186 std::uint64_t old_size = buffer.size();
187 buffer.insert(std::end(buffer), sizeof(std::uint64_t), 0); //set datalength to an arbitrary value
188 std::uint64_t ireal_size = it.second->set_checkpoint_data(buffer, _config);
189 char * csize = reinterpret_cast<char *>(&ireal_size);
190 for(std::uint64_t i(0) ; i < sizeof(std::uint64_t) ; ++i) //overwrite the the datalength
191 {
192 buffer[old_size + i] = csize[i];
193 }
194 real_size += ireal_size;
195 }
196
197 buffer.resize(real_size);
198 return real_size;
199 }
200
209 {
210 std::uint64_t stringsize;
211 std::uint64_t datasize(0);
212 std::size_t i = 0;
213 std::size_t size = _input_array.size();
214
215 // Loop over all objects stored in the checkpoint file
216 while (i < size)
217 {
218 // Get size of identifier string
219 ::memcpy(&stringsize, _input_array.data() + i, sizeof(std::uint64_t));
220 i += sizeof(std::uint64_t);
221
222 // Read the identifier string and put it as key for the calculated offset to the map
223 _offset_by_identifier[String(_input_array.data() + i, stringsize)] = i + stringsize;
224 i += stringsize;
225
226 // Get the size of the Data holding the array, to get the start point of the next checkpointable object in the array
227 ::memcpy(&datasize, _input_array.data() + i, sizeof(std::uint64_t));
228 i += sizeof(std::uint64_t) + datasize;
229 }
230 }
231
240 void _save(const String name)
241 {
242 std::vector<char> buffer;
244 std::vector<char> common(0);
245
246 DistFileIO::write_combined(common, buffer, name + ".cp", _comm);
247 }
248
260 void _load(const String name)
261 {
262
263 //std::vector<char> temp(0);
264 std::vector<char> common(0);
265 // read the checkpoint file
266 DistFileIO::read_combined(common, _input_array, name + ".cp", _comm);
267
269 }
270
271 public:
281 _comm(comm),
282 _config(config)
283 {
284 _input_array = std::vector<char>(0);
285 }
286
293 {
294 }
295
304 {
305 _config = conf;
306 }
314 {
315 _offset_by_identifier.clear();
316 _input_array.resize(0);
317 }
318
321 {
322 String identifiers;
323 for (auto item : _checkpointable_by_identifier)
324 {
325 if (identifiers.length() > 0)
326 {
327 identifiers += "\n";
328 }
329 identifiers += item.first;
330 }
331 return identifiers;
332 }
333
345 template <typename OT_>
346 void add_object(String identifier, OT_ & object)
347 {
348 XASSERTM(_checkpointable_by_identifier.count(identifier) == 0, "a object with the given identifier is already registered; choose a unique identifier");
349 auto checkpointable_object = std::make_shared<CheckpointableWrapper<OT_>>(object);
350 _checkpointable_by_identifier[identifier] = checkpointable_object;
351 }
352
361 void remove_object(String identifier)
362 {
363 XASSERTM(_checkpointable_by_identifier.count(identifier) == 1, "a object with the given identifier is not registered at this checkpoint instance");
364 _checkpointable_by_identifier.erase(identifier);
365 }
366
379 template <typename OT_>
380 void restore_object(String identifier, OT_ & object, bool add_to_checkpoint_control = true)
381 {
382 XASSERTM(_input_array.size() > 0u, "no input file has been loaded before");
383 XASSERTM(_offset_by_identifier.count(identifier) == 1, "input file doesn't contain data for the given identifier");
384
385 auto checkpointable_object = std::make_shared<CheckpointableWrapper<OT_>>(object);
386
387 std::uint64_t size(0);
388 char * in_data = _input_array.data() + _offset_by_identifier[identifier];
389 ::memcpy(&size, in_data, sizeof(std::uint64_t));
390 std::vector<char> buffer(in_data + sizeof(std::uint64_t), in_data + sizeof(std::uint64_t) + size);
391 checkpointable_object->restore_from_checkpoint_data(buffer);
392
393 if (add_to_checkpoint_control)
394 {
395 add_object(identifier, object);
396 }
397 }
398
407 void save(const String filename)
408 {
409 size_t pos = filename.rfind('.');
410 String extension = filename.substr(pos + 1);
411 String name = filename.substr(0, pos);
412
413 XASSERTM(name != "", "no complete filename consisting of name.extension given");
414
415 if (extension == "cp")
416 {
417 _save(name);
418 }
419 else
420 {
421 XASSERTM(extension != "zcp", "no zlib support, activate zlib or write uncompressed files with .cp extension instead");
422 XASSERTM(extension == "zcp", "no valid checkpoint filename choosen");
423 }
424 }
425
426 //Should we ignore the extension and just give in filename without .cp?
440 void load(const String filename)
441 {
442 XASSERTM(_input_array.size() == 0u, "another input file was read before");
443
444 size_t pos = filename.rfind('.');
445 String extension = filename.substr(pos + 1);
446 String name = filename.substr(0, pos);
447
448 XASSERTM(name != "", "no complete filename consisting of name.extension given");
449
450 if (extension == "cp")
451 {
452 _load(name);
453 }
454 else
455 {
456 XABORTM("no valid checkpoint file choosen");
457 }
458 }
459
468 {
469 std::vector<char> buffer;
470 std::uint64_t slen = _collect_checkpoint_data(buffer);
471
472 bs.write(reinterpret_cast<char *>(&slen), sizeof(slen));
473 bs.write(buffer.data(), static_cast<std::streamsize>(buffer.size()));
474 }
475
489 {
490 XASSERTM(_input_array.size() == 0, "another input file was read before");
491
492 char * buffer = bs.data();
493 std::uint64_t size = *(std::uint64_t *)(buffer);
494
495 _input_array.resize(size);
496 std::copy(buffer + sizeof(std::uint64_t), buffer + sizeof(std::uint64_t) + size - 1, _input_array.data());
497
499 }
500
501 }; // class Checkpoint
502
503 } // namespace Control
504} // namespace FEAT
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
FEAT Kernel base header.
Binary Stream class.
char * data()
Returns the data array of the stream.
Checkpoint/Restart infrastructure.
void set_config(FEAT::LAFEM::SerialConfig &conf)
Set a new serialize configuration.
void load(BinaryStream &bs)
Load checkpoint from stream.
void save(BinaryStream &bs)
Save checkpoint to a stream.
std::uint64_t _collect_checkpoint_data(std::vector< char > &buffer)
Build checkpoint buffer.
CheckpointControl(const Dist::Comm &comm, const LAFEM::SerialConfig &config=LAFEM::SerialConfig())
Constructor.
void _load(const String name)
Load checkpoint from disk.
std::vector< char > _input_array
Vector holding the array read from the input file during restore.
void add_object(String identifier, OT_ &object)
Register checkpointable object.
String get_identifier_list()
Retrieve a list of all items stored in the checkpoint.
void _restore_checkpoint_data()
Extract input buffer.
std::map< String, std::shared_ptr< Checkpointable > > _checkpointable_by_identifier
Mapping of identifier string to pointer to the checkpointable object.
void _save(const String name)
Write checkpoint files to disk.
void remove_object(String identifier)
Remove checkpointable object.
void load(const String filename)
Load checkpoint from disk.
const Dist::Comm & _comm
the mpi communicator identifying our mpi context
std::map< String, std::uint64_t > _offset_by_identifier
Mapping of identifier string to the offset in the input file.
void restore_object(String identifier, OT_ &object, bool add_to_checkpoint_control=true)
Restore checkpointable object.
FEAT::LAFEM::SerialConfig _config
The config class that controls the compression modes.
void save(const String filename)
Write checkpoint file to disk.
void clear_input()
Delete all read input.
Checkpoint interface class.
virtual void restore_from_checkpoint_data(std::vector< char > &data)=0
Extract object from checkpoint.
virtual std::uint64_t set_checkpoint_data(std::vector< char > &data, LAFEM::SerialConfig &config)=0
Collect checkpoint data from object.
virtual std::uint64_t get_checkpoint_size(LAFEM::SerialConfig &config)=0
Calculate size.
Wrapper class for checkpointable objects.
virtual void restore_from_checkpoint_data(std::vector< char > &data) override
Extract object from checkpoint.
CheckpointableWrapper(Object_ &obj)
Contructor.
virtual std::uint64_t get_checkpoint_size(LAFEM::SerialConfig &config) override
Calculate size.
virtual std::uint64_t set_checkpoint_data(std::vector< char > &data, LAFEM::SerialConfig &config) override
Collect checkpoint data from object.
Communicator class.
Definition: dist.hpp:1349
static void write_combined(const std::vector< char > &common, const std::vector< char > &buffer, const String &filename, const Dist::Comm &comm, int root_rank=0)
Writes a combined shared/ordered binary file.
static void read_combined(std::vector< char > &common, std::vector< char > &buffer, const String &filename, const Dist::Comm &comm, int root_rank=0, bool bcast_common=true)
Reads a combined shared/ordered binary file as written by the write_combined function.
Config class for serialize parameter.
Definition: container.hpp:47
String class implementation.
Definition: string.hpp:46
FEAT namespace.
Definition: adjactor.hpp:12