SIRIUS 7.5.0
Electronic structure library and applications
serializer.hpp
Go to the documentation of this file.
1// Copyright (c) 2013-2018 Anton Kozhevnikov, Thomas Schulthess
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without modification, are permitted provided that
5// the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
8// following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
10// and the following disclaimer in the documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
13// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
14// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
15// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
17// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
18// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
20/** \file serializer.hpp
21 *
22 * \brief Serializer for simple data structures.
23 */
24
25#ifndef __SERIALIZER_HPP__
26#define __SERIALIZER_HPP__
27
28#include <limits>
30#include "SDDK/memory.hpp"
31
32namespace sirius {
33
34/// Serialize and deserialize objects.
36{
37 private:
38 /// Position in the stream. This is used during unpacking.
39 size_t pos_{0};
40 /// Data stream is represendted as a sequence of characters.
41 std::vector<uint8_t> stream_;
42 public:
43
44 /// Copy n bytes into a serialization stream.
45 void copyin(uint8_t const* ptr__, size_t nbytes__)
46 {
47 /* resize the array */
48 stream_.resize(stream_.size() + nbytes__);
49 /* copy from pointer */
50 std::memcpy(&stream_[stream_.size() - nbytes__], ptr__, nbytes__);
51 }
52
53 /// Copy n bytes from the serialization stream.
54 /** When data is copied out, the position inside a stream is shifted to n bytes forward. */
55 void copyout(uint8_t* ptr__, size_t nbytes__)
56 {
57 std::memcpy(ptr__, &stream_[pos_], nbytes__);
58 pos_ += nbytes__;
59 }
60
61 void send_recv(mpi::Communicator const& comm__, int source__, int dest__)
62 {
63 if (source__ == dest__) {
64 return;
65 }
66
67 size_t sz;
68
69 mpi::Request r1, r2;
70
71 int tag = mpi::Communicator::get_tag(source__, dest__);
72
73 if (comm__.rank() == source__) {
74 sz = stream_.size();
75 RTE_ASSERT(sz < static_cast<size_t>(std::numeric_limits<int>::max()));
76 r1 = comm__.isend(&sz, 1, dest__, tag++);
77 r2 = comm__.isend(&stream_[0], (int)sz, dest__, tag++);
78 }
79
80 if (comm__.rank() == dest__) {
81 comm__.recv(&sz, 1, source__, tag++);
82 stream_.resize(sz);
83 comm__.recv(&stream_[0], (int)sz, source__, tag++);
84 }
85
86 if (comm__.rank() == source__) {
87 r1.wait();
88 r2.wait();
89 }
90 }
91
92 std::vector<uint8_t> const& stream() const
93 {
94 return stream_;
95 }
96};
97
98/// Serialize a single element.
99template <typename T>
100inline void serialize(serializer& s__, T var__)
101{
102 s__.copyin(reinterpret_cast<uint8_t const*>(&var__), sizeof(T));
103}
104
105/// Deserialize a single element.
106template <typename T>
107inline void deserialize(serializer& s__, T& var__)
108{
109 s__.copyout(reinterpret_cast<uint8_t*>(&var__), sizeof(T));
110}
111
112/// Serialize a vector.
113template <typename T>
114inline void serialize(serializer& s__, std::vector<T> const& vec__)
115{
116 serialize(s__, vec__.size());
117 s__.copyin(reinterpret_cast<uint8_t const*>(&vec__[0]), sizeof(T) * vec__.size());
118}
119
120/// Deserialize a vector.
121template <typename T>
122inline void deserialize(serializer& s__, std::vector<T>& vec__)
123{
124 size_t sz;
125 deserialize(s__, sz);
126 vec__.resize(sz);
127 s__.copyout(reinterpret_cast<uint8_t*>(&vec__[0]), sizeof(T) * vec__.size());
128}
129
130/// Serialize multidimentional array.
131template <typename T, int N>
132void serialize(serializer& s__, sddk::mdarray<T, N> const& array__)
133{
134 serialize(s__, array__.size());
135 if (array__.size() == 0) {
136 return;
137 }
138 for (int i = 0; i < N; i++) {
139 serialize(s__, array__.dim(i).begin());
140 serialize(s__, array__.dim(i).end());
141 }
142 s__.copyin(reinterpret_cast<uint8_t const*>(&array__[0]), sizeof(T) * array__.size());
143}
144
145/// Deserialize multidimentional array.
146template <typename T, int N>
148{
149 size_t sz;
150 deserialize(s__, sz);
151 if (sz == 0) {
152 array__ = sddk::mdarray<T, N>();
153 return;
154 }
155 std::array<sddk::mdarray_index_descriptor, N> dims;
156 for (int i = 0; i < N; i++) {
157 sddk::mdarray_index_descriptor::index_type begin, end;
158 deserialize(s__, begin);
159 deserialize(s__, end);
160 dims[i] = sddk::mdarray_index_descriptor(begin, end);
161 }
162 array__ = sddk::mdarray<T, N>(dims);
163 s__.copyout(reinterpret_cast<uint8_t*>(&array__[0]), sizeof(T) * array__.size());
164}
165
166/// Serialize block data descriptor.
167inline void serialize(serializer& s__, mpi::block_data_descriptor const& dd__)
168{
169 serialize(s__, dd__.num_ranks);
170 serialize(s__, dd__.counts);
171 serialize(s__, dd__.offsets);
172}
173
174/// Deserialize block data descriptor.
176{
177 deserialize(s__, dd__.num_ranks);
178 deserialize(s__, dd__.counts);
179 deserialize(s__, dd__.offsets);
180}
181
182}
183
184#endif
MPI communicator wrapper.
int rank() const
Rank of MPI process inside communicator.
Index descriptor of mdarray.
Definition: memory.hpp:554
index_type end() const
Return last index value.
Definition: memory.hpp:606
index_type begin() const
Return first index value.
Definition: memory.hpp:600
Multidimensional array with the column-major (Fortran) order.
Definition: memory.hpp:660
mdarray_index_descriptor dim(int i) const
Return a descriptor of a dimension.
Definition: memory.hpp:1226
size_t size() const
Return total size (number of elements) of the array.
Definition: memory.hpp:1207
Serialize and deserialize objects.
Definition: serializer.hpp:36
void copyout(uint8_t *ptr__, size_t nbytes__)
Copy n bytes from the serialization stream.
Definition: serializer.hpp:55
size_t pos_
Position in the stream. This is used during unpacking.
Definition: serializer.hpp:39
std::vector< uint8_t > stream_
Data stream is represendted as a sequence of characters.
Definition: serializer.hpp:41
void copyin(uint8_t const *ptr__, size_t nbytes__)
Copy n bytes into a serialization stream.
Definition: serializer.hpp:45
Contains declaration and implementation of mpi::Communicator class.
Memory management functions and classes.
Namespace of the SIRIUS library.
Definition: sirius.f90:5
void deserialize(serializer &s__, T &var__)
Deserialize a single element.
Definition: serializer.hpp:107