STORMM Source Documentation
Loading...
Searching...
No Matches
hybrid.h
1// -*-c++-*-
2#ifndef STORMM_HYBRID_H
3#define STORMM_HYBRID_H
4
5#include <cstdio>
6#include <cstring>
7#include <stdexcept>
8#include <cassert>
9#include <typeinfo>
10#include <typeindex>
11#include <vector>
12#ifdef STORMM_USE_HPC
13# ifdef STORMM_USE_CUDA
14# include <cuda_runtime.h>
15# endif
16#endif
17#include "copyright.h"
18#include "Constants/behavior.h"
19#include "Constants/scaling.h"
20#include "DataTypes/common_types.h"
21#include "DataTypes/stormm_vector_types.h"
22#include "Math/rounding.h"
23#include "Parsing/polynumeric.h"
24#include "Reporting/error_format.h"
25#include "gpu_enumerators.h"
26#ifdef STORMM_USE_HPC
27# include "hpc_hybrid.h"
28#endif
29
30namespace stormm {
31namespace card {
32
33using constants::ExceptionResponse;
34using constants::mega;
35using errors::rtErr;
36using stmath::roundUp;
37using stmath::getPaddedMemorySize;
38using parse::PolyNumeric;
39
42constexpr char expedited_code = 'X';
43constexpr char decoupled_code = 'L';
44constexpr char unified_code = 'U';
45constexpr char host_only_code = 'L';
46constexpr char devc_only_code = 'D';
47constexpr char host_mounted_code = 'H';
49
51constexpr llint allocating = 1;
52constexpr llint deallocating = -1;
53constexpr ulint hybrid_byte_increment = 128;
54#ifdef STORMM_USE_HPC
55constexpr HybridFormat default_hpc_format = HybridFormat::EXPEDITED;
56#else
57constexpr HybridFormat default_hpc_format = HybridFormat::HOST_ONLY;
58#endif
59
61constexpr ulint tag_name_length = 23;
62
66
68 char name[tag_name_length];
69
71 char format;
72
76};
77
81 HybridKind kind;
82 HybridLabel label;
83 size_t length;
84 size_t element_size;
85 int allocations;
86 bool active;
87};
88
93class Ledger {
94public:
95
97 Ledger();
98
100 ~Ledger() = default;
101
103 int getActiveEntryCount() const;
104
108 int getSerialNumber();
109
111 llint getTotalExpedited() const;
112
114 llint getTotalDecoupled() const;
115
117 llint getTotalUnified() const;
118
120 llint getTotalHostOnly() const;
121
123 llint getTotalDevcOnly() const;
124
126 llint getTotalHostMounted() const;
127
132 void setEntry(int serno, HybridKind kind, const HybridLabel hlbl, size_t length,
133 size_t element_size, int allocations);
134
139 void unsetEntry(int serno);
140
147 LedgerEntry getEntry(int index) const;
148 std::vector<LedgerEntry> getEntry(const std::string &name) const;
150
152 void logMemory(size_t capacity, size_t element_size, HybridFormat fmt, const HybridLabel hlbl,
153 llint multiplier);
154
158 bool testActive(int serno);
159
162 int getAllocations(int serno);
163
172 void printMemoryProfile(int n_display = 8, llint display_threshold = mega);
173
174private:
175
178 llint total_expedited;
179 llint total_decoupled;
180 llint total_unified;
181 llint total_host_only;
182 llint total_devc_only;
183 llint total_host_mounted;
185
187 std::vector<LedgerEntry> entries;
188
190 std::vector<int> free_slots;
191};
192
202template <typename T> class Hybrid {
203public:
204
217 explicit Hybrid(size_t length_in = 0, const char* tag_in = nullptr,
218 const HybridFormat format_in = default_hpc_format,
219 const HybridKind kind_in = HybridKind::ARRAY);
220
221 explicit Hybrid(const std::vector<T> &S_in, const char* tag_in = nullptr,
222 const HybridFormat format_in = default_hpc_format);
223
224 explicit Hybrid(const HybridKind kind_in, const char* tag_in = nullptr,
225 const HybridFormat format_in = default_hpc_format, size_t length_in = 0);
227
230
234 Hybrid(const Hybrid &original);
235
239 Hybrid(Hybrid &&original);
240
245 Hybrid& operator=(const Hybrid &other);
246
252
254 HybridKind getKind() const;
255
257 HybridFormat getFormat() const;
258
260 size_t size() const;
261
263 size_t capacity() const;
264
267 size_t getPointerIndex() const;
268
270 size_t getElementSize() const;
271
274
276 int getSerialNumber() const;
277
279 int getAllocations() const;
280
284
287 bool verifyTarget() const;
288
297 const T* data(const HybridTargetLevel tier = HybridTargetLevel::HOST) const;
298 T* data(const HybridTargetLevel tier = HybridTargetLevel::HOST);
300
314 T readHost(size_t index) const;
315 std::vector<T> readHost(size_t offset, size_t count) const;
316 std::vector<T> readHost() const;
317 void readHost(T* v, size_t offset, size_t count) const;
319
340 void putHost(const T value, size_t index);
341 void putHost(const std::vector<T> &values, size_t offset, size_t count);
342 void putHost(const std::vector<T> &values);
343 size_t putHost(Hybrid<T> *target, const std::vector<T> &values, size_t offset = 0,
344 size_t padding = 0, size_t count = 0);
346#ifdef STORMM_USE_HPC
348 void upload(size_t start_pos = 0, size_t length_copy = 0);
349
351 void download(size_t start_pos = 0, size_t length_copy = 0);
352
369 T readDevice(size_t index) const;
370 std::vector<T> readDevice(size_t offset, size_t count) const;
371 std::vector<T> readDevice() const;
372 void readDevice(T* v, size_t offset, size_t count) const;
374
392 void putDevice(const T value, size_t index);
393 void putDevice(const T* values, size_t offset, size_t count);
394 void putDevice(const std::vector<T> &values, size_t offset, size_t count);
395 void putDevice(const std::vector<T> &values);
397#endif
400
416 void pushBack(const T element);
417 void pushBack(const T* elements, const size_t element_count);
418 void pushBack(const std::vector<T> &elements);
419 void pushBack(const Hybrid<T> &elements);
421
433 void resize(size_t new_length);
434 void resize(size_t new_length, T value);
436
449 void setPointer(Hybrid<T> *target, size_t position = 0, llint new_length = -1LL);
450
460 void swapTarget(Hybrid<T> *new_target, ExceptionResponse policy = ExceptionResponse::SILENT);
461
475 const Hybrid<T> getPointer(size_t position = 0, size_t new_length = 0,
476 const char* tag_in = nullptr) const;
477 Hybrid<T> getPointer(size_t position = 0, size_t new_length = 0, const char* tag_in = nullptr);
479#ifdef STORMM_USE_HPC
480# ifdef STORMM_USE_CUDA
490 const T* getDeviceValidHostPointer() const;
491 T* getDeviceValidHostPointer();
493# endif
494#endif
495private:
496
500 HybridKind kind;
501
509 HybridFormat format;
510
512 size_t length;
513
515 size_t element_size;
516
518 size_t growth_increment;
519
521 size_t max_capacity;
522
525 size_t pointer_index;
526
529 T* host_data;
530
532#ifdef STORMM_USE_HPC
533 T* devc_data;
534#endif
535
537 HybridLabel label;
538
540 int allocations;
541
544 int target_serial_number;
545
552 void enforceDataTypeLimits();
553
555 void allocate();
556
558 void deallocate();
559
561 void reallocate(size_t new_length, size_t new_capacity = 0);
562
567 HybridLabel assignLabel(const char* tag);
568#if 0
575 template <typename Treturn>
576 friend const Hybrid<Treturn> reinterpretCast(const Hybrid *target, size_t offset, size_t length,
577 const char* output_name);
578
579 template <typename Treturn>
580 friend Hybrid<Treturn> reinterpretCast(Hybrid *target, size_t offset, size_t length,
581 const char* output_name);
583#endif
584};
585
603template <typename T>
604const Hybrid<T> setPointer(const Hybrid<T> *target, size_t offset, size_t length,
605 const char* output_name = nullptr);
606
607template <typename T>
608Hybrid<T> setPointer(Hybrid<T> *target, size_t offset, size_t length,
609 const char* output_name = nullptr);
611
612} // namespace card
613} // namespace stormm
614
618extern stormm::card::Ledger gbl_mem_balance_sheet;
619
620#include "hybrid.tpp"
621
622#endif
An evolution of GpuBuffer in pmemd.cuda, the Composite array has elements that are accessible from ei...
Definition hybrid.h:202
void pushBack(const T element)
Mimic the C++ std::vector push_back functionality. A bounds check is followed by extension of the dat...
T readHost(size_t index) const
Get data from a given index of the host_data array. This substitutes for direct array access via the ...
size_t capacity() const
Return the number of elements in the Hybrid object's data array(s)
void setPointer(Hybrid< T > *target, size_t position=0, llint new_length=-1LL)
Set a Hybrid pointer struct to a segment of a Hybrid array struct.
void putHost(const T value, size_t index)
Put data into the host_data array. This substitutes for direct array access via the [ ] operator,...
int getTargetSerialNumber() const
Produce the serial number of the target (only valid for POINTER-kind objects). This function is neede...
int getAllocations() const
Return the number of times this object has been allocated.
HybridKind getKind() const
Get the object kind (pointer or array)
Hybrid(const Hybrid &original)
Copy constructor handles the reassignment of the underlying raw pointers.
size_t getElementSize() const
Return the size of an individual element in the data array(s)
bool verifyTarget() const
Verify that the target of a HybridKind::POINTER object remains in the state it was in when the pointe...
~Hybrid()
Destructor frees data with no re-allocation.
Hybrid & operator=(const Hybrid &other)
Copy assignment constructor handles the reassignment of the underlying raw pointers.
void shrinkToFit()
Trim a Hybrid array to the exact size of its data.
void resize(size_t new_length)
A std::vector-like resize() feature.
void swapTarget(Hybrid< T > *new_target, ExceptionResponse policy=ExceptionResponse::SILENT)
Swap the target of a POINTER-kind Hybrid object, transferring its starting index and current length t...
int getSerialNumber() const
Return the object's identifying serial number.
size_t getPointerIndex() const
Return the pointer start position, targeting another ARRAY-kind Hybrid object (relevant for POINTER-k...
size_t size() const
Return the number of elements in the Hybrid object's data array(s)
HybridFormat getFormat() const
Get the memory format.
const T * data(const HybridTargetLevel tier=HybridTargetLevel::HOST) const
Get a pointer directly to the GpuArray's data on either the host or the device.
HybridLabel getLabel() const
Return the object's identifying label.
Hybrid(Hybrid &&original)
The move constructor handles migration of a Hybrid object.
Hybrid(size_t length_in=0, const char *tag_in=nullptr, const HybridFormat format_in=default_hpc_format, const HybridKind kind_in=HybridKind::ARRAY)
Constructors vary based on whether CUDA is part of the compilation.
Hybrid & operator=(Hybrid &&other)
The move assignment operator must likewise handle transfer of the underlying data.
const Hybrid< T > getPointer(size_t position=0, size_t new_length=0, const char *tag_in=nullptr) const
Get a pointer to a Hybrid object at a specific location. This is the way to get const Hybrid POINTER-...
A struct for storing records of all active Hybrid memory arrays. This will also store tables of ident...
Definition hybrid.h:93
Ledger()
Constructor initializes the number of entries and allocations.
Definition hybrid.cpp:22
llint getTotalExpedited() const
Retrieve the total allocation of decoupled memory, in bytes.
Definition hybrid.cpp:53
llint getTotalUnified() const
Retrieve the total allocation of unified memory, in bytes.
Definition hybrid.cpp:63
int getActiveEntryCount() const
Retrieve the number of entries for Hybrid memory objects currently stored.
Definition hybrid.cpp:33
LedgerEntry getEntry(int index) const
Get information about a single entry of a ledger.
Definition hybrid.cpp:117
void unsetEntry(int serno)
Remove a Hybrid object from the catalog. This is to be called by the Hybrid object's destructor.
Definition hybrid.cpp:105
void logMemory(size_t capacity, size_t element_size, HybridFormat fmt, const HybridLabel hlbl, llint multiplier)
Log each tagged Hybrid array in the ledger.
Definition hybrid.cpp:134
~Ledger()=default
Default destructor.
void setEntry(int serno, HybridKind kind, const HybridLabel hlbl, size_t length, size_t element_size, int allocations)
Begin a catalog for the place of a Hybrid object among many others. This is to be called once for eac...
Definition hybrid.cpp:83
int getAllocations(int serno)
Query the number of times the Hybrid object catalogged in a particular entry has had its data arrays ...
Definition hybrid.cpp:195
llint getTotalDevcOnly() const
Retrieve the total allocation of device-only memory, in bytes.
Definition hybrid.cpp:73
bool testActive(int serno)
Query an index in the ledger to determine whether it catalogs an active Hybrid object.
Definition hybrid.cpp:187
llint getTotalHostOnly() const
Retrieve the total allocation of host-only memory, in bytes.
Definition hybrid.cpp:68
llint getTotalHostMounted() const
Retrieve the total allocation of host-mounted memory, in bytes.
Definition hybrid.cpp:78
llint getTotalDecoupled() const
Retrieve the total allocation of decoupled memory, in bytes.
Definition hybrid.cpp:58
void printMemoryProfile(int n_display=8, llint display_threshold=mega)
Print the current memory usage of all Hybrid objects. The function will print totals followed by spec...
Definition hybrid.cpp:209
int getSerialNumber()
Produce a number corresponding to some unused entry in the ledger. This will be either the lowest pos...
Definition hybrid.cpp:38
A Hybrid object's immutable identifying information, stored as a const member variable within the Hyb...
Definition hybrid.h:65
char format
Shorthand for the Hybrid object's format.
Definition hybrid.h:71
char name[tag_name_length]
A descriptive name for the Hybrid object.
Definition hybrid.h:68
int serial_number
Definition hybrid.h:75
Entries of the memory ledger recording not just a copy of the immutable type data but also allocation...
Definition hybrid.h:80