https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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
17namespace Moose::Kokkos
18{
19
20#ifdef MOOSE_KOKKOS_SCOPE
21constexpr uint32_t FNV_PRIME = 0x01000193; // 16777619
22constexpr uint32_t FNV_OFFSET_BASIS = 0x811C9DC5; // 2166136261
23
24template <typename T>
25KOKKOS_FUNCTION uint32_t
26fnv1aHash(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
39template <typename T>
40KOKKOS_FUNCTION uint32_t
41fnv1aHash(const T & key)
42{
43 return fnv1aHash(key, FNV_OFFSET_BASIS);
44}
45
46template <typename T1, typename T2>
47struct Pair;
48
49template <typename T1, typename T2>
50KOKKOS_FUNCTION uint32_t
52{
53 return fnv1aHash(key.second, fnv1aHash(key.first));
54}
55#endif
56
57template <typename T1, typename T2, template <typename...> class MapType>
58class MapBase;
59
60template <typename T1, typename T2, template <typename...> class MapType>
61void dataStore(std::ostream & stream, MapBase<T1, T2, MapType> & map, void * context);
62template <typename T1, typename T2, template <typename...> class MapType>
63void dataLoad(std::istream & stream, MapBase<T1, T2, MapType> & map, void * context);
64
70template <typename T1, typename T2, template <typename...> class MapType>
72{
73public:
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
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 }
192 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
210 static const dof_id_type invalid_id = libMesh::DofObject::invalid_id;
211
212private:
213#ifdef MOOSE_KOKKOS_SCOPE
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
242template <typename T1, typename T2, template <typename...> class MapType>
243void
245{
246 get().clear();
247
248 _keys.destroy();
249 _values.destroy();
250 _offset.destroy();
251}
252
253#ifdef MOOSE_KOKKOS_SCOPE
254template <typename T1, typename T2, template <typename...> class MapType>
255void
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
286template <typename T1, typename T2, template <typename...> class MapType>
287void
289{
290 copy();
291
292 _keys.copyToDevice();
293 _values.copyToDevice();
294}
295
296template <typename T1, typename T2, template <typename...> class MapType>
297void
299{
300 copy();
301
302 _keys.copyToDeviceNested();
303 _values.copyToDeviceNested();
304}
305
306template <typename T1, typename T2, template <typename...> class MapType>
307void
309{
310 get().swap(map.get());
311 _keys.swap(map._keys);
312 _values.swap(map._values);
313 _offset.swap(map._offset);
314}
315
316template <typename T1, typename T2, template <typename...> class MapType>
317KOKKOS_FUNCTION dof_id_type
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
334template <typename T1, typename T2, template <typename...> class MapType>
335void
336dataStore(std::ostream & stream, MapBase<T1, T2, MapType> & map, void * context)
337{
338 using ::dataStore;
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
346template <typename T1, typename T2, template <typename...> class MapType>
347void
348dataLoad(std::istream & stream, MapBase<T1, T2, MapType> & map, void * context)
349{
350 using ::dataLoad;
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
359template <typename T1, typename T2>
361
362template <typename T1, typename T2>
364
365} // namespace Moose::Kokkos
KOKKOS_FUNCTION index_type size() const
Get the total array size.
The Kokkos array class.
The Kokkos wrapper class for standard map.
Definition KokkosMap.h:72
void copyToDeviceNested()
Copy host map to device, perform nested copy for Kokkos arrays.
Definition KokkosMap.h:298
KOKKOS_FUNCTION const T1 & key(dof_id_type idx) const
Get the key of an index.
Definition KokkosMap.h:169
auto end()
Get the end writeable iterator of the host map.
Definition KokkosMap.h:88
void clear()
Clear the underlying data.
Definition KokkosMap.h:244
Array< T2 > _values
Values on device.
Definition KokkosMap.h:232
Array< dof_id_type > _offset
Beginning offset into device arrays of each bucket.
Definition KokkosMap.h:236
auto begin()
Get the beginning writeable iterator of the host map.
Definition KokkosMap.h:78
auto & get()
Get the underlying writeable host map.
Definition KokkosMap.h:98
KOKKOS_FUNCTION bool exists(const T1 &key) const
Get whether a key exists.
Definition KokkosMap.h:163
KOKKOS_FUNCTION const T2 & operator()(const T1 &key) const
Definition KokkosMap.h:206
Array< T1 > _keys
Keys on device.
Definition KokkosMap.h:228
KOKKOS_FUNCTION dof_id_type size() const
Get the size of map.
Definition KokkosMap.h:146
static const dof_id_type invalid_id
Definition KokkosMap.h:210
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 const T2 & operator[](const T1 &key) const
Get the value corresponding to a key.
Definition KokkosMap.h:192
auto begin() const
Get the beginning const iterator of the host map.
Definition KokkosMap.h:83
const auto & get() const
Get the underlying const host map.
Definition KokkosMap.h:109
KOKKOS_FUNCTION const T2 & value(dof_id_type idx) const
Get the value of an index.
Definition KokkosMap.h:180
T2 & operator[](const T1 &key)
Call host map's operator[].
Definition KokkosMap.h:125
void copyToDevice()
Copy host map to device.
Definition KokkosMap.h:288
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
auto end() const
Get the end const iterator of the host map.
Definition KokkosMap.h:93
static constexpr dof_id_type invalid_id
void dataLoad(std::istream &stream, Array< T, dimension, index_type, layout > &array, void *context)
constexpr uint32_t FNV_OFFSET_BASIS
Definition KokkosMap.h:22
constexpr uint32_t FNV_PRIME
Definition KokkosMap.h:21
KOKKOS_FUNCTION uint32_t fnv1aHash(const T &key, uint32_t hash)
Definition KokkosMap.h:26
void dataStore(std::ostream &stream, Array< T, dimension, index_type, layout > &array, void *context)