https://mooseframework.inl.gov
Loading...
Searching...
No Matches
KokkosJaggedArray.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
14namespace Moose::Kokkos
15{
16
21template <unsigned int inner>
23{
27 unsigned int dim[inner] = {0};
31 unsigned int stride[inner + 1] = {0};
32
33#ifdef MOOSE_KOKKOS_SCOPE
39 KOKKOS_FUNCTION unsigned int operator[](unsigned int i) const { return dim[i]; }
40#endif
41};
42
43#ifdef MOOSE_KOKKOS_SCOPE
51template <typename T, unsigned int inner, LayoutType layout>
53{
54public:
61 : _data(data), _dim(dim)
62 {
63 }
64
69 KOKKOS_FUNCTION unsigned int size() const { return _dim.stride[inner]; }
75 KOKKOS_FUNCTION unsigned int n(unsigned int dim) const { return _dim[dim]; }
80 KOKKOS_FUNCTION T & operator[](unsigned int i) const
81 {
82 KOKKOS_ASSERT(i < _dim.stride[inner]);
83
84 return _data[i];
85 }
90 template <typename... indices>
91 KOKKOS_FUNCTION T & operator()(indices... i) const;
92
93protected:
97 T * _data;
102};
103
104template <typename T, unsigned int inner, LayoutType layout>
105template <typename... indices>
106KOKKOS_FUNCTION T &
108{
109 static_assert((std::is_convertible<indices, unsigned int>::value && ...),
110 "All arguments must be convertible to unsigned int");
111 static_assert(sizeof...(i) == inner, "Number of arguments should match array dimension");
112
113#ifndef NDEBUG
114 {
115 unsigned int idx[inner] = {static_cast<unsigned int>(i)...};
116
117 for (unsigned int d = 0; d < sizeof...(i); ++d)
118 KOKKOS_ASSERT(idx[d] < _dim[d]);
119 }
120#endif
121
122 unsigned int idx = 0;
123 unsigned int d = 0;
124
125 if constexpr (layout == LayoutType::LEFT)
126 (((idx +=
127 (d == 0 ? static_cast<unsigned int>(i) : static_cast<unsigned int>(i) * _dim.stride[d])),
128 ++d),
129 ...);
130 else
131 (((idx += (d == inner - 1 ? static_cast<unsigned int>(i)
132 : static_cast<unsigned int>(i) * _dim.stride[d])),
133 ++d),
134 ...);
135
136 return _data[idx];
137}
138#endif
139
159template <typename T,
160 unsigned int inner,
161 unsigned int outer,
162 typename index_type = MOOSE_KOKKOS_INDEX_TYPE,
165{
166public:
170 JaggedArray() = default;
171
172#ifdef MOOSE_KOKKOS_SCOPE
176 template <typename... size_type>
177 JaggedArray(size_type... n)
178 {
179 create(n...);
180 }
181
186 void create(const std::vector<index_type> & n);
191 template <typename... size_type>
192 void create(size_type... n);
198 void reserve(const std::array<uint64_t, outer> & index,
199 const std::array<uint64_t, inner> & dimension);
203 void finalize();
208 {
209 mooseAssert(_finalized, "KokkosJaggedArray not finalized.");
210
211 _data.copyToDevice();
212 }
217 {
218 mooseAssert(_finalized, "KokkosJaggedArray not finalized.");
219
220 _data.copyToHost();
221 }
226 {
227 mooseAssert(_finalized, "KokkosJaggedArray not finalized.");
228
229 _dims.moveToDevice();
230 _offsets.moveToDevice();
231 _data.moveToDevice();
232 }
237 {
238 mooseAssert(_finalized, "KokkosJaggedArray not finalized.");
239
240 _dims.moveToHost();
241 _offsets.moveToHost();
242 _data.moveToHost();
243 }
248 auto & array() { return _data; }
249
254 KOKKOS_FUNCTION bool isFinalized() const { return _finalized; }
259 KOKKOS_FUNCTION bool isHostAlloc() const { return _data.isHostAlloc(); }
264 KOKKOS_FUNCTION bool isDeviceAlloc() const { return _data.isDeviceAlloc(); }
269 KOKKOS_FUNCTION index_type size() const { return _data.size(); }
274 KOKKOS_FUNCTION index_type n() const { return _offsets.size(); }
280 KOKKOS_FUNCTION index_type n(unsigned int dim) const { return _offsets.n(dim); }
286 KOKKOS_FUNCTION auto operator[](index_type i) const;
292 template <typename... indices>
293 KOKKOS_FUNCTION auto operator()(indices... i) const;
294#endif
295
296protected:
312 bool _finalized = false;
313};
314
315#ifdef MOOSE_KOKKOS_SCOPE
316template <typename T,
317 unsigned int inner,
318 unsigned int outer,
319 typename index_type,
320 LayoutType layout>
321void
323{
324 _data.destroy();
325 _offsets.create(n);
326 _dims.create(n);
327
328 _finalized = false;
329}
330
331template <typename T,
332 unsigned int inner,
333 unsigned int outer,
334 typename index_type,
335 LayoutType layout>
336template <typename... size_type>
337void
339{
340 _data.destroy();
341 _offsets.create(n...);
342 _dims.create(n...);
343
344 _finalized = false;
345}
346
347template <typename T,
348 unsigned int inner,
349 unsigned int outer,
350 typename index_type,
351 LayoutType layout>
352void
354 const std::array<uint64_t, outer> & index, const std::array<uint64_t, inner> & dimension)
355{
356 mooseAssert(!_finalized, "KokkosJaggedArray already finalized.");
357
358 index_type idx = 0;
359 index_type stride = 1;
360
361 for (unsigned int o = 0; o < outer; ++o)
362 {
363 idx += index[o] * stride;
364 stride *= _offsets.n(o);
365 }
366
367 for (unsigned int i = 0; i < inner; ++i)
368 _dims[idx].dim[i] = dimension[i];
369
370 stride = 1;
371
372 if constexpr (layout == LayoutType::LEFT)
373 for (unsigned int i = 0; i < inner; ++i)
374 {
375 _dims[idx].stride[i] = stride;
376 stride *= dimension[i];
377 }
378 else
379 for (int i = inner - 1; i >= 0; --i)
380 {
381 _dims[idx].stride[i] = stride;
382 stride *= dimension[i];
383 }
384
385 _dims[idx].stride[inner] = stride;
386}
387
388template <typename T,
389 unsigned int inner,
390 unsigned int outer,
391 typename index_type,
392 LayoutType layout>
393void
395{
396 mooseAssert(!_finalized, "KokkosJaggedArray already finalized.");
397
398 index_type stride = 1;
399
400 for (index_type o = 0; o < _offsets.size(); ++o)
401 {
402 stride = 1;
403
404 for (unsigned int i = 0; i < inner; ++i)
405 stride *= _dims[o][i];
406
407 _offsets[o] = stride;
408 }
409
410 std::exclusive_scan(_offsets.begin(), _offsets.end(), _offsets.begin(), 0);
411
412 _dims.copyToDevice();
413 _offsets.copyToDevice();
414
415 // Pad an extra element at the end to avoid accessing the bound in the following operators when
416 // the last inner array has zero size
417 _data.create(_offsets.last() + stride + 1);
418
419 _finalized = true;
420}
421
422template <typename T,
423 unsigned int inner,
424 unsigned int outer,
425 typename index_type,
426 LayoutType layout>
427KOKKOS_FUNCTION auto
429{
430 auto data = &_data[_offsets[i]];
431 const auto & dim = _dims[i];
432
434}
435
436template <typename T,
437 unsigned int inner,
438 unsigned int outer,
439 typename index_type,
440 LayoutType layout>
441template <typename... indices>
442KOKKOS_FUNCTION auto
444{
445 auto data = &_data[_offsets(i...)];
446 const auto & dim = _dims(i...);
447
449}
450#endif
451
452} // namespace Moose::Kokkos
The Kokkos array class.
The inner array wrapper class.
JaggedArrayInnerDim< inner > _dim
Inner array dimension information.
KOKKOS_FUNCTION T & operator()(indices... i) const
Get an array entry.
T * _data
Pointer to the inner array data.
KOKKOS_FUNCTION T & operator[](unsigned int i) const
Get an array entry.
KOKKOS_FUNCTION unsigned int n(unsigned int dim) const
Get the size of a dimension of the inner array.
KOKKOS_FUNCTION JaggedArrayInnerData(T *data, JaggedArrayInnerDim< inner > dim)
Constructor.
KOKKOS_FUNCTION unsigned int size() const
Get the total inner array size.
The Kokkos jagged array class.
JaggedArray()=default
Default constructor.
KOKKOS_FUNCTION bool isHostAlloc() const
Get whether the array was allocated on host.
void moveToDevice()
Copy data from host to device and deallocate host.
JaggedArray(size_type... n)
Constructor.
bool _finalized
Whether the array was finalized.
KOKKOS_FUNCTION index_type size() const
Get the total data array size.
void moveToHost()
Copy data from device to host and deallocate device.
Array< index_type, outer, index_type > _offsets
Starting offset of each inner array into the sequential data array.
Array< JaggedArrayInnerDim< inner >, outer, index_type > _dims
Dimension information of each inner array.
KOKKOS_FUNCTION bool isFinalized() const
Get whether the array is finalized.
KOKKOS_FUNCTION auto operator()(indices... i) const
Get an inner array.
void copyToDevice()
Copy data from host to device.
void copyToHost()
Copy data from device to host.
void create(const std::vector< index_type > &n)
Allocate outer array.
KOKKOS_FUNCTION index_type n(unsigned int dim) const
Get the size of a dimension of the outer array.
KOKKOS_FUNCTION auto operator[](index_type i) const
Get an inner array.
Array1D< T, index_type > _data
Sequential data array.
KOKKOS_FUNCTION index_type n() const
Get the total outer array size.
void reserve(const std::array< uint64_t, outer > &index, const std::array< uint64_t, inner > &dimension)
Reserve inner array for an outer array entry.
KOKKOS_FUNCTION bool isDeviceAlloc() const
Get whether the array was allocated on device.
auto & array()
Get the underlying data array.
void finalize()
Setup array structure.
LayoutType
The enumerator that dictates the memory layout.
Definition KokkosArray.h:53
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:165
A simple object holding the dimension information of an inner array.
KOKKOS_FUNCTION unsigned int operator[](unsigned int i) const
Get the size of a dimension.
unsigned int stride[inner+1]
Stride of each dimension.
unsigned int dim[inner]
Size of each dimension.