tvm
serializer.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
33 #ifndef TVM_SUPPORT_SERIALIZER_H_
34 #define TVM_SUPPORT_SERIALIZER_H_
35 
36 #include <dlpack/dlpack.h>
37 #include <tvm/ffi/container/array.h>
38 #include <tvm/ffi/container/map.h>
39 #include <tvm/ffi/endian.h>
40 #include <tvm/ffi/string.h>
41 #include <tvm/support/io.h>
42 
43 #include <cstdint>
44 #include <cstring>
45 #include <string>
46 #include <type_traits>
47 #include <unordered_map>
48 #include <utility>
49 #include <vector>
50 
51 namespace tvm {
52 namespace support {
53 
54 // ---- Arithmetic types ----
55 template <typename T>
56 struct Serializer<T, std::enable_if_t<std::is_arithmetic_v<T>>> {
57  static constexpr bool enabled = true;
58 
59  static void Write(Stream* strm, const T& data) {
60  if constexpr (TVM_FFI_IO_NO_ENDIAN_SWAP) {
61  strm->Write(&data, sizeof(T));
62  } else {
63  T copy = data;
64  ffi::ByteSwap(&copy, sizeof(T), 1);
65  strm->Write(&copy, sizeof(T));
66  }
67  }
68 
69  static bool Read(Stream* strm, T* data) {
70  bool ok = strm->Read(data, sizeof(T)) == sizeof(T);
71  if constexpr (!TVM_FFI_IO_NO_ENDIAN_SWAP) {
72  ffi::ByteSwap(data, sizeof(T), 1);
73  }
74  return ok;
75  }
76 };
77 
78 // ---- Enum types (delegate to underlying arithmetic type) ----
79 template <typename T>
80 struct Serializer<T, std::enable_if_t<std::is_enum_v<T>>> {
81  static constexpr bool enabled = true;
82  using U = std::underlying_type_t<T>;
83 
84  static void Write(Stream* strm, const T& data) {
85  Serializer<U>::Write(strm, static_cast<U>(data));
86  }
87 
88  static bool Read(Stream* strm, T* data) {
89  U val;
90  if (!Serializer<U>::Read(strm, &val)) return false;
91  *data = static_cast<T>(val);
92  return true;
93  }
94 };
95 
96 // ---- std::string ----
97 template <>
98 struct Serializer<std::string> {
99  static constexpr bool enabled = true;
100 
101  static void Write(Stream* strm, const std::string& data) {
102  uint64_t sz = static_cast<uint64_t>(data.size());
103  Serializer<uint64_t>::Write(strm, sz);
104  if (sz != 0) {
105  strm->Write(data.data(), data.size());
106  }
107  }
108 
109  static bool Read(Stream* strm, std::string* data) {
110  uint64_t sz;
111  if (!Serializer<uint64_t>::Read(strm, &sz)) return false;
112  data->resize(static_cast<size_t>(sz));
113  if (sz != 0) {
114  size_t nbytes = static_cast<size_t>(sz);
115  return strm->Read(&(*data)[0], nbytes) == nbytes;
116  }
117  return true;
118  }
119 };
120 
121 // ---- std::vector<T> ----
122 template <typename T>
123 struct Serializer<std::vector<T>> {
124  static constexpr bool enabled = true;
125 
126  static void Write(Stream* strm, const std::vector<T>& vec) {
127  uint64_t sz = static_cast<uint64_t>(vec.size());
128  Serializer<uint64_t>::Write(strm, sz);
129  if constexpr (std::is_arithmetic_v<T> && TVM_FFI_IO_NO_ENDIAN_SWAP) {
130  if (sz != 0) {
131  strm->Write(vec.data(), sizeof(T) * vec.size());
132  }
133  } else {
134  for (const auto& v : vec) {
135  Serializer<T>::Write(strm, v);
136  }
137  }
138  }
139 
140  static bool Read(Stream* strm, std::vector<T>* vec) {
141  uint64_t sz;
142  if (!Serializer<uint64_t>::Read(strm, &sz)) return false;
143  vec->resize(static_cast<size_t>(sz));
144  if constexpr (std::is_arithmetic_v<T> && TVM_FFI_IO_NO_ENDIAN_SWAP) {
145  if (sz != 0) {
146  size_t nbytes = sizeof(T) * static_cast<size_t>(sz);
147  return strm->Read(vec->data(), nbytes) == nbytes;
148  }
149  return true;
150  } else {
151  for (size_t i = 0; i < static_cast<size_t>(sz); ++i) {
152  if (!Serializer<T>::Read(strm, &(*vec)[i])) return false;
153  }
154  return true;
155  }
156  }
157 };
158 
159 // ---- std::pair<A, B> ----
160 template <typename A, typename B>
161 struct Serializer<std::pair<A, B>> {
162  static constexpr bool enabled = true;
163 
164  static void Write(Stream* strm, const std::pair<A, B>& data) {
165  Serializer<A>::Write(strm, data.first);
166  Serializer<B>::Write(strm, data.second);
167  }
168 
169  static bool Read(Stream* strm, std::pair<A, B>* data) {
170  return Serializer<A>::Read(strm, &data->first) && Serializer<B>::Read(strm, &data->second);
171  }
172 };
173 
174 // ---- std::unordered_map<K, V> ----
175 template <typename K, typename V>
176 struct Serializer<std::unordered_map<K, V>> {
177  static constexpr bool enabled = true;
178 
179  static void Write(Stream* strm, const std::unordered_map<K, V>& data) {
180  std::vector<std::pair<K, V>> vec(data.begin(), data.end());
181  Serializer<std::vector<std::pair<K, V>>>::Write(strm, vec);
182  }
183 
184  static bool Read(Stream* strm, std::unordered_map<K, V>* data) {
185  std::vector<std::pair<K, V>> vec;
186  if (!Serializer<std::vector<std::pair<K, V>>>::Read(strm, &vec)) return false;
187  data->clear();
188  data->insert(vec.begin(), vec.end());
189  return true;
190  }
191 };
192 
193 // ---- ffi::String ----
194 template <>
195 struct Serializer<ffi::String> {
196  static constexpr bool enabled = true;
197 
198  static void Write(Stream* strm, const ffi::String& data) {
199  uint64_t sz = static_cast<uint64_t>(data.size());
200  Serializer<uint64_t>::Write(strm, sz);
201  if (sz != 0) {
202  strm->Write(data.data(), data.size());
203  }
204  }
205 
206  static bool Read(Stream* strm, ffi::String* data) {
207  std::string s;
208  if (!Serializer<std::string>::Read(strm, &s)) return false;
209  *data = ffi::String(std::move(s));
210  return true;
211  }
212 };
213 
214 // ---- ffi::Array<T> (binary-compatible with std::vector<T>) ----
215 template <typename T>
216 struct Serializer<ffi::Array<T>> {
217  static constexpr bool enabled = true;
218 
219  static void Write(Stream* strm, const ffi::Array<T>& arr) {
220  uint64_t sz = static_cast<uint64_t>(arr.size());
221  Serializer<uint64_t>::Write(strm, sz);
222  for (size_t i = 0; i < arr.size(); ++i) {
223  Serializer<T>::Write(strm, arr[i]);
224  }
225  }
226 
227  static bool Read(Stream* strm, ffi::Array<T>* arr) {
228  uint64_t sz;
229  if (!Serializer<uint64_t>::Read(strm, &sz)) return false;
230  *arr = ffi::Array<T>();
231  for (uint64_t i = 0; i < sz; ++i) {
232  T val;
233  if (!Serializer<T>::Read(strm, &val)) return false;
234  arr->push_back(std::move(val));
235  }
236  return true;
237  }
238 };
239 
240 // ---- ffi::Map<K, V> (binary format: uint64_t count, then key/value pairs) ----
241 template <typename K, typename V>
242 struct Serializer<ffi::Map<K, V>> {
243  static constexpr bool enabled = true;
244 
245  static void Write(Stream* strm, const ffi::Map<K, V>& data) {
246  uint64_t sz = static_cast<uint64_t>(data.size());
247  Serializer<uint64_t>::Write(strm, sz);
248  for (const auto& kv : data) {
249  Serializer<K>::Write(strm, kv.first);
250  Serializer<V>::Write(strm, kv.second);
251  }
252  }
253 
254  static bool Read(Stream* strm, ffi::Map<K, V>* data) {
255  uint64_t sz;
256  if (!Serializer<uint64_t>::Read(strm, &sz)) return false;
257  *data = ffi::Map<K, V>();
258  for (uint64_t i = 0; i < sz; ++i) {
259  K key;
260  V val;
261  if (!Serializer<K>::Read(strm, &key)) return false;
262  if (!Serializer<V>::Read(strm, &val)) return false;
263  data->Set(std::move(key), std::move(val));
264  }
265  return true;
266  }
267 };
268 
269 // ---- DLDataType ----
270 template <>
271 struct Serializer<DLDataType> {
272  static constexpr bool enabled = true;
273 
274  static void Write(Stream* strm, const DLDataType& dtype) {
275  Serializer<uint8_t>::Write(strm, dtype.code);
276  Serializer<uint8_t>::Write(strm, dtype.bits);
277  Serializer<uint16_t>::Write(strm, dtype.lanes);
278  }
279 
280  static bool Read(Stream* strm, DLDataType* dtype) {
281  if (!Serializer<uint8_t>::Read(strm, &dtype->code)) return false;
282  if (!Serializer<uint8_t>::Read(strm, &dtype->bits)) return false;
283  if (!Serializer<uint16_t>::Read(strm, &dtype->lanes)) return false;
284  return true;
285  }
286 };
287 
288 // ---- DLDevice ----
289 template <>
290 struct Serializer<DLDevice> {
291  static constexpr bool enabled = true;
292 
293  static void Write(Stream* strm, const DLDevice& dev) {
294  int32_t device_type = static_cast<int32_t>(dev.device_type);
296  Serializer<int32_t>::Write(strm, dev.device_id);
297  }
298 
299  static bool Read(Stream* strm, DLDevice* dev) {
300  int32_t device_type = 0;
301  if (!Serializer<int32_t>::Read(strm, &device_type)) return false;
302  dev->device_type = static_cast<DLDeviceType>(device_type);
303  if (!Serializer<int32_t>::Read(strm, &dev->device_id)) return false;
304  return true;
305  }
306 };
307 
308 } // namespace support
309 } // namespace tvm
310 
311 #endif // TVM_SUPPORT_SERIALIZER_H_
Abstract binary stream for serialization.
Definition: io.h:57
virtual size_t Write(const void *ptr, size_t size)=0
Write raw bytes to the stream.
Binary stream I/O interface.
constexpr const char * device_type
The device type.
Definition: stmt.h:913
An object that builds and maintains block scope and StmtSref mapping for Dependence analysis.
Definition: analyzer.h:37
static bool Read(Stream *strm, DLDataType *dtype)
Definition: serializer.h:280
static void Write(Stream *strm, const DLDataType &dtype)
Definition: serializer.h:274
static void Write(Stream *strm, const DLDevice &dev)
Definition: serializer.h:293
static bool Read(Stream *strm, DLDevice *dev)
Definition: serializer.h:299
static void Write(Stream *strm, const ffi::Array< T > &arr)
Definition: serializer.h:219
static bool Read(Stream *strm, ffi::Array< T > *arr)
Definition: serializer.h:227
static bool Read(Stream *strm, ffi::Map< K, V > *data)
Definition: serializer.h:254
static void Write(Stream *strm, const ffi::Map< K, V > &data)
Definition: serializer.h:245
static bool Read(Stream *strm, ffi::String *data)
Definition: serializer.h:206
static void Write(Stream *strm, const ffi::String &data)
Definition: serializer.h:198
Primary Serializer template. Specialize for each serializable type.
Definition: io.h:42
static constexpr bool enabled
Definition: io.h:43