DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
ArrayEigenMatrixBatch_DeviceView.hpp
Go to the documentation of this file.
1#pragma once
2/// @file ArrayEigenMatrixBatch_DeviceView.hpp
3/// @brief Device-callable views and on-buffer matrix-batch helpers for
4/// @ref DNDS::ArrayEigenMatrixBatch "ArrayEigenMatrixBatch" (variable-sized matrix batches per row).
5///
6/// Also defines a `MatrixBatch<real_T>` utility class that packs multiple
7/// variable-shaped matrices into a single flat buffer using 32-bit size-pair
8/// headers so each row can self-describe its matrix shapes.
9
10#include "../DeviceView.hpp"
11#include "DNDS/Defines.hpp"
13#include "Eigen/src/Core/Matrix.h"
14#include "Eigen/src/Core/util/Constants.h"
15#include <cstddef>
16#include <type_traits>
17
18namespace DNDS
19{
20 /**
21 * @brief Packed variable-shape matrix-batch layout inside a flat buffer.
22 *
23 * @details Each row of @ref DNDS::ArrayEigenMatrixBatch "ArrayEigenMatrixBatch" stores several matrices whose
24 * shapes may differ. @ref DNDS::MatrixBatch "MatrixBatch" provides:
25 * - nested @ref DNDS::UInt32PairIn64 "UInt32PairIn64" / @ref DNDS::UInt16QuadIn64 "UInt16QuadIn64" helpers to pack two 32-bit
26 * (or four 16-bit) integers into a single 64-bit word (matrix shape headers);
27 * - size computation (`getBufSize`) and compression (@ref CompressIn) for
28 * an input vector of Eigen matrices;
29 * - `operator()(j)` that returns an `Eigen::Map` onto the `j`-th matrix
30 * inside the already-compressed row buffer.
31 *
32 * The templated `real_T` allows both mutable and const variants.
33 */
34 template <class real_T = real>
36 {
37 public:
39 {
40 uint64_t data;
41 DNDS_DEVICE_CALLABLE [[nodiscard]] uint32_t getM() const { return uint32_t(data & 0x00000000FFFFFFFFULL); }
42 DNDS_DEVICE_CALLABLE [[nodiscard]] uint32_t getN() const { return uint32_t(data >> 32); }
43 DNDS_DEVICE_CALLABLE void setM(uint32_t v) { data = (data & 0xFFFFFFFF00000000ULL) | uint64_t(v); }
44 DNDS_DEVICE_CALLABLE void setN(uint32_t v) { data = (data & 0x00000000FFFFFFFFULL) | (uint64_t(v) << 32); }
45 };
46 static_assert(sizeof(UInt32PairIn64) == 8);
47
49 {
50 uint64_t data;
51 DNDS_DEVICE_CALLABLE [[nodiscard]] uint16_t getA() const { return uint16_t((data & 0x000000000000FFFFULL) >> 0); }
52 DNDS_DEVICE_CALLABLE [[nodiscard]] uint16_t getB() const { return uint16_t((data & 0x00000000FFFF0000ULL) >> 16); }
53 DNDS_DEVICE_CALLABLE [[nodiscard]] uint16_t getC() const { return uint16_t((data & 0x0000FFFF00000000ULL) >> 32); }
54 DNDS_DEVICE_CALLABLE [[nodiscard]] uint16_t getD() const { return uint16_t((data & 0xFFFF000000000000ULL) >> 48); }
55
56 DNDS_DEVICE_CALLABLE void setA(uint16_t v) { data = (data & (~0x000000000000FFFFULL)) | (uint64_t(v) << 0); }
57 DNDS_DEVICE_CALLABLE void setB(uint16_t v) { data = (data & (~0x00000000FFFF0000ULL)) | (uint64_t(v) << 16); }
58 DNDS_DEVICE_CALLABLE void setC(uint16_t v) { data = (data & (~0x0000FFFF00000000ULL)) | (uint64_t(v) << 32); }
59 DNDS_DEVICE_CALLABLE void setD(uint16_t v) { data = (data & (~0xFFFF000000000000ULL)) | (uint64_t(v) << 48); }
60 };
61 static_assert(sizeof(UInt32PairIn64) == 8 && sizeof(UInt16QuadIn64) == 8);
62
63 using t_matrix = Eigen::Matrix<std::remove_cv_t<real_T>, Eigen::Dynamic, Eigen::Dynamic>;
64 using t_map_const = Eigen::Map<const t_matrix, Eigen::Unaligned>;
65 using t_map =
66 std::conditional_t<std::is_const_v<real_T>,
68 Eigen::Map<t_matrix, Eigen::Unaligned>>;
69
70 template <class t_matrices_elem>
71 static rowsize getBufSize(const std::vector<t_matrices_elem> &matrices)
72 {
73 DNDS_assert(matrices.size() < DNDS_ROWSIZE_MAX);
74 rowsize bufSiz = matrices.size() + 1;
75 for (const auto &i : matrices)
76 {
77 Eigen::Index mSiz = i.rows() * i.cols();
78 static_assert(std::numeric_limits<Eigen::Index>::digits > std::numeric_limits<uint32_t>::digits);
79 DNDS_assert((mSiz + bufSiz) < DNDS_ROWSIZE_MAX && i.rows() <= UINT16_MAX && i.cols() <= UINT16_MAX);
80 bufSiz += mSiz;
81 }
82 return bufSiz;
83 }
84
85 private:
86 real_T *_buf;
87 rowsize _buf_size;
88 static_assert(sizeof(real_T) == 8 || sizeof(real_T) == 4);
89 static const ptrdiff_t n_real_in_64 = 8 / sizeof(real);
90
91 DNDS_DEVICE_CALLABLE real_T *get_kth_64_meta_block(rowsize k) { return _buf + (k + 1) * n_real_in_64; }
92 DNDS_DEVICE_CALLABLE [[nodiscard]] const real_T *get_kth_64_meta_block(rowsize k) const
93 {
94 return (const_cast<MatrixBatch *>(this))->get_kth_64_meta_block(k);
95 }
96
97 public:
98 DNDS_DEVICE_CALLABLE MatrixBatch(real_T *n_buf, rowsize new_size) : _buf(n_buf), _buf_size(new_size)
99 {
100 }
101
102 DNDS_DEVICE_CALLABLE [[nodiscard]] uint64_t &Size() const
103 {
104 DNDS_assert(_buf_size > 0);
105 return *(uint64_t *)(_buf);
106 }
107
108 DNDS_DEVICE_CALLABLE [[nodiscard]] uint16_t getNRow(rowsize k) const
109 {
110 DNDS_assert(k < _buf_size - 1);
111 return ((UInt16QuadIn64 *)get_kth_64_meta_block(k))->getA();
112 }
113
114 DNDS_DEVICE_CALLABLE [[nodiscard]] uint16_t getNCol(rowsize k) const
115 {
116 DNDS_assert(k < _buf_size - 1);
117 return ((UInt16QuadIn64 *)get_kth_64_meta_block(k))->getB();
118 }
119
120 DNDS_DEVICE_CALLABLE [[nodiscard]] uint32_t getOffset(rowsize k) const
121 {
122 DNDS_assert(k < _buf_size - 1);
123 return ((UInt32PairIn64 *)get_kth_64_meta_block(k))->getN();
124 }
125
127 {
128 DNDS_assert(k < _buf_size - 1);
129 ((UInt16QuadIn64 *)get_kth_64_meta_block(k))->setA(v);
130 }
131
133 {
134 DNDS_assert(k < _buf_size - 1);
135 ((UInt16QuadIn64 *)get_kth_64_meta_block(k))->setB(v);
136 }
137
139 {
140 DNDS_assert(k < _buf_size - 1);
141 ((UInt32PairIn64 *)get_kth_64_meta_block(k))->setN(v);
142 }
143
144 template <class t_matrices_elem>
145 void CompressIn(const std::vector<t_matrices_elem> &matrices)
146 {
147 DNDS_assert(getBufSize(matrices) <= _buf_size);
148 this->Size() = uint64_t(matrices.size()); // assuming could fit
149 // std::cout << "Size: " << this->Size() << std::endl;
150 uint32_t curOffset = uint32_t(this->Size()) + 1;
151 for (size_t i = 0; i < matrices.size(); i++)
152 {
153 DNDS_assert(matrices[i].rows() <= Eigen::Index(UINT16_MAX));
154 DNDS_assert(matrices[i].cols() <= Eigen::Index(UINT16_MAX));
155 this->setNRow(rowsize(i), uint16_t(matrices[i].rows()));
156 this->setNCol(rowsize(i), uint16_t(matrices[i].cols()));
157 this->setOffset(rowsize(i), curOffset);
158 this->operator[](i) = matrices[i];
159 // std::cout << "SET: " << this->operator[](i) << std::endl;
160 static_assert(std::numeric_limits<Eigen::Index>::digits > std::numeric_limits<uint32_t>::digits);
161 DNDS_assert(matrices[i].size() <= Eigen::Index(UINT32_MAX - curOffset)); // overflow check
162 curOffset += matrices[i].size();
163 }
164 }
167 {
168 DNDS_assert(k < this->Size());
169 auto n_row = getNRow(k);
170 auto n_col = getNCol(k);
171 auto offset = getOffset(k);
172 return {_buf + offset, n_row, n_col};
173 }
174
177 {
178 DNDS_assert(k < this->Size());
179 auto n_row = getNRow(k);
180 auto n_col = getNCol(k);
181 auto offset = getOffset(k);
182 return {_buf + offset, n_row, n_col};
183 }
184 };
185
186 template <DeviceBackend B, class real_T>
187 class ArrayEigenMatrixBatchDeviceView : public ArrayDeviceView<B, real_T, NonUniformSize>
188 {
189 public:
191 using t_base::t_base;
192
196
198
200
202
207
209 {
210 return {this->t_base::operator[](i), this->RowSize(i)};
211 }
212
214 {
215 return this->operator[](i).Size();
216 }
217
219 {
220 return this->operator[](i)[j];
221 }
222
224 {
225 return this->operator[](i)[j];
226 }
227 };
228
229}
Core type aliases, constants, and metaprogramming utilities for the DNDS framework.
#define DNDS_DEVICE_TRIVIAL_COPY_DEFINE(T, T_Self)
Definition Defines.hpp:83
#define DNDS_DEVICE_CALLABLE
Definition Defines.hpp:76
#define DNDS_ROWSIZE_MAX
Definition Defines.hpp:118
Device memory abstraction layer with backend-specific storage and factory creation.
#define DNDS_assert(expr)
Debug-only assertion (compiled out when DNDS_NDEBUG is defined). Prints the expression + file/line + ...
Definition Errors.hpp:108
Non-owning device-callable view of an Array, specialised per DeviceBackend.
DNDS_DEVICE_CALLABLE MatrixBatch< real_T > operator[](index i)
typename MatrixBatch< real_T >::t_matrix t_matrix
DNDS_DEVICE_CALLABLE MatrixBatch< const real_T > operator[](index i) const
typename MatrixBatch< real_T >::t_map_const t_map_const
DNDS_DEVICE_CALLABLE t_map_const operator()(index i, rowsize j) const
DNDS_DEVICE_CALLABLE t_map operator()(index i, rowsize j)
T * operator[](index iRow)
Raw row pointer. iRow == Size() is allowed for past-the-end queries (useful for computing buffer end ...
DNDS_DEVICE_CALLABLE rowsize RowSize() const
Uniform row width for fixed layouts (asserts otherwise).
Packed variable-shape matrix-batch layout inside a flat buffer.
void CompressIn(const std::vector< t_matrices_elem > &matrices)
DNDS_DEVICE_CALLABLE uint32_t getOffset(rowsize k) const
DNDS_DEVICE_CALLABLE uint16_t getNCol(rowsize k) const
Eigen::Matrix< std::remove_cv_t< real_T >, Eigen::Dynamic, Eigen::Dynamic > t_matrix
static rowsize getBufSize(const std::vector< t_matrices_elem > &matrices)
DNDS_DEVICE_CALLABLE uint64_t & Size() const
Eigen::Map< const t_matrix, Eigen::Unaligned > t_map_const
DNDS_DEVICE_CALLABLE void setOffset(rowsize k, uint32_t v)
DNDS_DEVICE_CALLABLE MatrixBatch(real_T *n_buf, rowsize new_size)
DNDS_DEVICE_CALLABLE uint16_t getNRow(rowsize k) const
DNDS_DEVICE_CALLABLE t_map_const operator[](rowsize k) const
std::conditional_t< std::is_const_v< real_T >, t_map_const, Eigen::Map< t_matrix, Eigen::Unaligned > > t_map
DNDS_DEVICE_CALLABLE void setNCol(rowsize k, uint16_t v)
DNDS_DEVICE_CALLABLE void setNRow(rowsize k, uint16_t v)
DNDS_DEVICE_CALLABLE t_map operator[](rowsize k)
the host side operators are provided as implemented
int32_t rowsize
Row-width / per-row element-count type (signed 32-bit).
Definition Defines.hpp:109
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
double real
Canonical floating-point scalar used throughout DNDSR (double precision).
Definition Defines.hpp:105
DNDS_DEVICE_CALLABLE void setA(uint16_t v)
DNDS_DEVICE_CALLABLE void setD(uint16_t v)
DNDS_DEVICE_CALLABLE void setC(uint16_t v)
DNDS_DEVICE_CALLABLE uint16_t getC() const
DNDS_DEVICE_CALLABLE uint16_t getB() const
DNDS_DEVICE_CALLABLE uint16_t getA() const
DNDS_DEVICE_CALLABLE void setB(uint16_t v)
DNDS_DEVICE_CALLABLE uint16_t getD() const
DNDS_DEVICE_CALLABLE uint32_t getM() const
DNDS_DEVICE_CALLABLE void setN(uint32_t v)
DNDS_DEVICE_CALLABLE uint32_t getN() const
DNDS_DEVICE_CALLABLE void setM(uint32_t v)
Eigen::Matrix< real, 5, 1 > v