https://mooseframework.inl.gov
KokkosMap.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://www.mooseframework.org
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #pragma once
11 
12 #include "KokkosArray.h"
13 
14 #include <memory>
15 #include <map>
16 
17 namespace Moose::Kokkos
18 {
19 
20 #ifdef MOOSE_KOKKOS_SCOPE
21 constexpr uint32_t FNV_PRIME = 0x01000193; // 16777619
22 constexpr uint32_t FNV_OFFSET_BASIS = 0x811C9DC5; // 2166136261
23 
24 template <typename T>
25 KOKKOS_FUNCTION uint32_t
26 fnv1aHash(const T & key, uint32_t hash)
27 {
28  auto bytes = reinterpret_cast<const uint8_t *>(&key);
29 
30  for (size_t i = 0; i < sizeof(T); ++i)
31  {
32  hash ^= bytes[i];
33  hash *= FNV_PRIME;
34  }
35 
36  return hash;
37 }
38 
39 template <typename T>
40 KOKKOS_FUNCTION uint32_t
41 fnv1aHash(const T & key)
42 {
43  return fnv1aHash(key, FNV_OFFSET_BASIS);
44 }
45 
46 template <typename T1, typename T2>
47 struct Pair;
48 
49 template <typename T1, typename T2>
50 KOKKOS_FUNCTION uint32_t
51 fnv1aHash(const Pair<T1, T2> & key)
52 {
53  return fnv1aHash(key.second, fnv1aHash(key.first));
54 }
55 #endif
56 
57 template <typename T1, typename T2, template <typename...> class MapType>
58 class MapBase;
59 
60 template <typename T1, typename T2, template <typename...> class MapType>
61 void dataStore(std::ostream & stream, MapBase<T1, T2, MapType> & map, void * context);
62 template <typename T1, typename T2, template <typename...> class MapType>
63 void dataLoad(std::istream & stream, MapBase<T1, T2, MapType> & map, void * context);
64 
70 template <typename T1, typename T2, template <typename...> class MapType>
71 class MapBase
72 {
73 public:
78  auto begin() { return get().begin(); }
83  auto begin() const { return get().cbegin(); }
88  auto end() { return get().end(); }
93  auto end() const { return get().cend(); }
98  auto & get()
99  {
100  if (!_map_host)
101  _map_host = std::make_shared<MapType<T1, T2>>();
102 
103  return *_map_host;
104  }
109  const auto & get() const
110  {
111  if (!_map_host)
112  _map_host = std::make_shared<MapType<T1, T2>>();
113 
114  return *_map_host;
115  }
119  void clear();
125  T2 & operator[](const T1 & key) { return get()[key]; }
126 
127 #ifdef MOOSE_KOKKOS_SCOPE
128 
131  void copyToDevice();
135  void copyToDeviceNested();
140  void swap(MapBase<T1, T2, MapType> & map);
141 
146  KOKKOS_FUNCTION dof_id_type size() const
147  {
148  KOKKOS_IF_ON_HOST(return get().size();)
149 
150  return _keys.size();
151  }
157  KOKKOS_FUNCTION dof_id_type find(const T1 & key) const;
163  KOKKOS_FUNCTION bool exists(const T1 & key) const { return find(key) != invalid_id; }
169  KOKKOS_FUNCTION const T1 & key(dof_id_type idx) const
170  {
171  KOKKOS_ASSERT(idx != invalid_id);
172 
173  return _keys[idx];
174  }
180  KOKKOS_FUNCTION const T2 & value(dof_id_type idx) const
181  {
182  KOKKOS_ASSERT(idx != invalid_id);
183 
184  return _values[idx];
185  }
191  KOKKOS_FUNCTION const T2 & operator[](const T1 & key) const
193  {
194  KOKKOS_IF_ON_HOST(return get().at(key);)
195 
196  auto idx = find(key);
197 
198  KOKKOS_ASSERT(idx != invalid_id);
199 
200  return _values[idx];
201  }
202  // Due to a stupid NVCC compiler bug, one cannot do var[i][j] for a variable whose type is
203  // Array<Map<...>> (the second operator[] seems to be interpreted as if it is the operator of
204  // Array), while var[i](j) works. Until we figure out what is going on, one can use the following
205  // operator as a workaround.
206  KOKKOS_FUNCTION const T2 & operator()(const T1 & key) const { return operator[](key); }
208 #endif
209 
211 
212 private:
213 #ifdef MOOSE_KOKKOS_SCOPE
214 
217  void copy();
218 #endif
219 
224  mutable std::shared_ptr<MapType<T1, T2>> _map_host;
237 
238  friend void dataStore<T1, T2, MapType>(std::ostream &, MapBase<T1, T2, MapType> &, void *);
239  friend void dataLoad<T1, T2, MapType>(std::istream &, MapBase<T1, T2, MapType> &, void *);
240 };
241 
242 template <typename T1, typename T2, template <typename...> class MapType>
243 void
245 {
246  get().clear();
247 
248  _keys.destroy();
249  _values.destroy();
250  _offset.destroy();
251 }
252 
253 #ifdef MOOSE_KOKKOS_SCOPE
254 template <typename T1, typename T2, template <typename...> class MapType>
255 void
257 {
258  _keys.create(size());
259  _values.create(size());
260  _offset.create(size() + 1);
261  _offset = 0;
262 
263  for (const auto & [key, value] : get())
264  {
265  auto bucket = fnv1aHash(key) % size();
266 
267  _offset[bucket]++;
268  }
269 
270  std::exclusive_scan(_offset.begin(), _offset.end(), _offset.begin(), 0);
271 
272  _offset.copyToDevice();
273 
274  std::vector<dof_id_type> idx(size(), 0);
275 
276  for (const auto & [key, value] : get())
277  {
278  auto bucket = fnv1aHash(key) % size();
279 
280  _keys[_offset[bucket] + idx[bucket]] = key;
281  _values[_offset[bucket] + idx[bucket]] = value;
282  idx[bucket]++;
283  }
284 }
285 
286 template <typename T1, typename T2, template <typename...> class MapType>
287 void
289 {
290  copy();
291 
292  _keys.copyToDevice();
293  _values.copyToDevice();
294 }
295 
296 template <typename T1, typename T2, template <typename...> class MapType>
297 void
299 {
300  copy();
301 
302  _keys.copyToDeviceNested();
303  _values.copyToDeviceNested();
304 }
305 
306 template <typename T1, typename T2, template <typename...> class MapType>
307 void
309 {
310  get().swap(map.get());
311  _keys.swap(map._keys);
312  _values.swap(map._values);
313  _offset.swap(map._offset);
314 }
315 
316 template <typename T1, typename T2, template <typename...> class MapType>
317 KOKKOS_FUNCTION dof_id_type
318 MapBase<T1, T2, MapType>::find(const T1 & key) const
319 {
320  if (!size())
321  return invalid_id;
322 
323  auto bucket = fnv1aHash(key) % size();
324  auto begin = _offset[bucket];
325  auto end = _offset[bucket + 1];
326 
327  for (dof_id_type i = begin; i < end; ++i)
328  if (_keys[i] == key)
329  return i;
330 
331  return invalid_id;
332 }
333 
334 template <typename T1, typename T2, template <typename...> class MapType>
335 void
336 dataStore(std::ostream & stream, MapBase<T1, T2, MapType> & map, void * context)
337 {
339 
340  dataStore(stream, map.get(), context);
341  dataStore(stream, map._keys, context);
342  dataStore(stream, map._values, context);
343  dataStore(stream, map._offset, context);
344 }
345 
346 template <typename T1, typename T2, template <typename...> class MapType>
347 void
348 dataLoad(std::istream & stream, MapBase<T1, T2, MapType> & map, void * context)
349 {
351 
352  dataLoad(stream, map.get(), context);
353  dataLoad(stream, map._keys, context);
354  dataLoad(stream, map._values, context);
355  dataLoad(stream, map._offset, context);
356 }
357 #endif
358 
359 template <typename T1, typename T2>
361 
362 template <typename T1, typename T2>
364 
365 } // namespace Moose::Kokkos
auto end()
Get the end writeable iterator of the host map.
Definition: KokkosMap.h:88
constexpr uint32_t FNV_PRIME
Definition: KokkosMap.h:21
void copyToDevice()
Copy host map to device.
Definition: KokkosMap.h:288
void dataStore(std::ostream &stream, MapBase< T1, T2, MapType > &map, void *context)
Definition: KokkosMap.h:336
void dataLoad(std::istream &stream, MapBase< T1, T2, MapType > &map, void *context)
Definition: KokkosMap.h:348
void clear()
Clear the underlying data.
Definition: KokkosMap.h:244
KOKKOS_FUNCTION const T2 & value(dof_id_type idx) const
Get the value of an index.
Definition: KokkosMap.h:180
auto & get()
Get the underlying writeable host map.
Definition: KokkosMap.h:98
void dataLoad(std::istream &stream, Array< T, dimension, index_type, layout > &array, void *context)
Definition: KokkosArray.h:1269
void swap(std::vector< T > &data, const std::size_t idx0, const std::size_t idx1, const libMesh::Parallel::Communicator &comm)
Swap function for serial or distributed vector of data.
Definition: Shuffle.h:495
auto begin() const
Get the beginning const iterator of the host map.
Definition: KokkosMap.h:83
KOKKOS_FUNCTION uint32_t fnv1aHash(const T &key, uint32_t hash)
Definition: KokkosMap.h:26
constexpr uint32_t FNV_OFFSET_BASIS
Definition: KokkosMap.h:22
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
sideset clear()
static constexpr dof_id_type invalid_id
Array< dof_id_type > _offset
Beginning offset into device arrays of each bucket.
Definition: KokkosMap.h:236
KOKKOS_FUNCTION const T1 & key(dof_id_type idx) const
Get the key of an index.
Definition: KokkosMap.h:169
void copyToDeviceNested()
Copy host map to device, perform nested copy for Kokkos arrays.
Definition: KokkosMap.h:298
KOKKOS_FUNCTION index_type size() const
Get the total array size.
Definition: KokkosArray.h:205
void dataStore(std::ostream &stream, Array< T, dimension, index_type, layout > &array, void *context)
Definition: KokkosArray.h:1225
Array< T2 > _values
Values on device.
Definition: KokkosMap.h:232
static const dof_id_type invalid_id
Definition: KokkosMap.h:210
The Kokkos wrapper class for standard map.
Definition: KokkosMap.h:58
auto begin()
Get the beginning writeable iterator of the host map.
Definition: KokkosMap.h:78
T2 & operator[](const T1 &key)
Call host map&#39;s operator[].
Definition: KokkosMap.h:125
std::shared_ptr< MapType< T1, T2 > > _map_host
Standard map on host Stored as a shared pointer to avoid deep copy.
Definition: KokkosMap.h:224
KOKKOS_FUNCTION dof_id_type size() const
Get the size of map.
Definition: KokkosMap.h:146
KOKKOS_FUNCTION bool exists(const T1 &key) const
Get whether a key exists.
Definition: KokkosMap.h:163
void swap(MapBase< T1, T2, MapType > &map)
Swap with another Kokkos map.
Definition: KokkosMap.h:308
void copy()
Internal method to copy host map to device.
Definition: KokkosMap.h:256
KOKKOS_FUNCTION dof_id_type find(const T1 &key) const
Find the index of a key.
Definition: KokkosMap.h:318
Array< T1 > _keys
Keys on device.
Definition: KokkosMap.h:228
unsigned int idx(const ElemType type, const unsigned int nx, const unsigned int i, const unsigned int j)
KOKKOS_FUNCTION const T2 & operator()(const T1 &key) const
Definition: KokkosMap.h:206
uint8_t dof_id_type
auto end() const
Get the end const iterator of the host map.
Definition: KokkosMap.h:93