DNDSR 0.1.0.dev1+gcd065ad
Distributed Numeric Data Structure for CFV
Loading...
Searching...
No Matches
DeviceTransferable.hpp
Go to the documentation of this file.
1#pragma once
2/// @file DeviceTransferable.hpp
3/// @brief CRTP mixin that provides uniform to_device/to_host/device/getDeviceArrayBytes
4/// for classes that enumerate their device-managed arrays via
5/// for_each_device_member(F&&).
6
8#include "DNDS/Errors.hpp"
10
11#include <fmt/format.h>
12
13namespace DNDS
14{
15 /**
16 * @brief CRTP mixin giving a class uniform `to_device` / `to_host` / `device` /
17 * `getDeviceArrayBytes` methods.
18 *
19 * @details The derived class only has to expose its device-managed members
20 * via a `for_each_device_member(F&&)` method template that invokes `F(m)`
21 * once per `MemberRef<ArrayPairType>`:
22 *
23 * ```cpp
24 * template <typename F>
25 * void for_each_device_member(F&& f)
26 * {
27 * for_each_member_list(device_array_list(), std::forward<F>(f));
28 * }
29 * ```
30 *
31 * Once that is in place, all four member functions below iterate every
32 * registered pair and forward the device operation.
33 */
34 template <typename Derived>
36 {
37 public:
38 /// @brief Mirror every registered @ref DNDS::ArrayPair "ArrayPair" to the given device backend.
40 {
41 auto op = [B](auto &v)
42 {
43 v.ref.to_device(B);
44 };
45 self().for_each_device_member(op);
46 }
47
48 /// @brief Pull every registered pair back to host memory.
49 void to_host()
50 {
51 auto op = [](auto &v)
52 {
53 v.ref.to_host();
54 };
55 self().for_each_device_member(op);
56 }
57
58 /// @brief Consistent device backend across all registered pairs.
59 /// @details Asserts that every pair's father and son live on the same
60 /// backend; throws a descriptive message if not.
62 {
64 auto getB = [&B](auto &v)
65 {
66 if (v.ref.father)
67 B = v.ref.father->device();
68 };
69 self().for_each_device_member(getB);
70
71 auto check = [&B](auto &v)
72 {
73 if (v.ref.father)
75 B == v.ref.father->device(),
76 fmt::format("member [{}.father] expected to be on device {} but on {}",
77 v.name,
79 device_backend_name(v.ref.father->device())));
80 if (v.ref.son)
82 B == v.ref.son->device(),
83 fmt::format("member [{}.son] expected to be on device {} but on {}",
84 v.name,
86 device_backend_name(v.ref.son->device())));
87 };
88 self().for_each_device_member(check);
89
90 return B;
91 }
92
93 /// @brief Total footprint of every registered father+son pair in bytes.
95 {
96 index bytes = 0;
97 auto accumulate = [&bytes](auto &v)
98 {
99 if (v.ref.father)
100 bytes += v.ref.father->FullSizeBytes();
101 if (v.ref.son)
102 bytes += v.ref.son->FullSizeBytes();
103 };
104 self().for_each_device_member(accumulate);
105 return bytes;
106 }
107
108 private:
109 Derived &self() { return static_cast<Derived &>(*this); }
110 };
111}
Device memory abstraction layer with backend-specific storage and factory creation.
Assertion / error-handling macros and supporting helper functions.
#define DNDS_assert_info(expr, info)
Debug-only assertion with an extra std::string info message.
Definition Errors.hpp:113
Tiny reflection-style helpers (MemberRef, MemberPtr) and for_each_member_* visitors used by config / ...
CRTP mixin giving a class uniform to_device / to_host / device / getDeviceArrayBytes methods.
DeviceBackend device()
Consistent device backend across all registered pairs.
index getDeviceArrayBytes()
Total footprint of every registered father+son pair in bytes.
void to_host()
Pull every registered pair back to host memory.
void to_device(DeviceBackend B)
Mirror every registered ArrayPair to the given device backend.
the host side operators are provided as implemented
DeviceBackend
Enumerates the backends a DeviceStorage / Array can live on.
@ Unknown
Unset / sentinel.
const char * device_backend_name(DeviceBackend B)
Canonical string name for a DeviceBackend (used in log messages).
int64_t index
Global row / DOF index type (signed 64-bit; handles multi-billion-cell meshes).
Definition Defines.hpp:107
Eigen::Matrix< real, 5, 1 > v