It is worth noting that one can still be RAII when doing "late allocating" with, e.g., resize(n, value) (allocate(n, functor)) as in std::vector. As you see the only constructors being RAII are empty (default) or fill, range, copy, ... (move, =) but not "create size N and do not initialize with a value".
Constructor: currently a fill constructor, add an empty constructor (no allocation, size=0, capacity=0) and other RAII such as copy, move, assign =, etc.
for explicit "I want that GPU memory to be gone in constructor" workflow one could add a reserve constructor that only increases capacity but not size (does allocate but no uninitialized memory is exposed -> RAII ok; BUT general "accelerator" memory might only really be allocated on use as it is already seen on the host, so this constructor might still need a "memset" to an (unexposed) but random value per element to make sure the allocation happened while keeping size at zero (optimization: for current cuda architectures one might be able to skip the memset)
add resize(DataSpace, functor()) member to aquire and fill values
add convenciense signatures such as resize(DataSpace, val), assign, etc.
reset -> resize(0) should not set the fill level (size) to maximum (=capacity) but to 0
resize(0) is not the same as clear() since clear is allowed to deallocate resources, we do not want to deallocate in many cases; resize() does exactly that: for 0 input it does not change capacity but size (and we can disallow increasing capacity after first allocation if we want)
Wrappers that store and organize containers
Classes:GridBuffer (has two RAII container members for host/device + exchanges), ParticlesBuffer (has several GridBuffers) ...
delegate (mix) concepts between:
host and device scope of operation (e.g., setValue, reset (set meta & members), clear (drop members), etc.)
host / device synchronization
mapping to/from double buffers to allow algorithms to operate on up-to-date GUARD+BORDER+CORE as if they were one
updating of double buffers (host-device synchronization + transformations/preparations + MPI)
... more?
Simulation and Plugin Objects
[WIP] would be interesting if one can make these RAII without making life horrible...
Constructor
allocate ressources (such as GPUs, wrappers, containers with memory on device, ...) and but expose them with zero size to users
does need to parse or get as an input the planned simulation extend for static allocations of fields
register members in DataConnector
create valid state for user with "empty" simulation:
grids are of size (currentSize) zero but internally allocated (this memory is not exposed to user)
particle buffer have 0 frames but mallocMC heap is allocated and usable
initialize()/assign():
fill available containers with user data
add exchanges
might depend on a time step (which might lead to the decision to look for a checkpoint)
clear():
reset to state after allocateEmpty() so initialize() can be called again
cheaper version of deallocate() + allocateEmpty() since some ressources, e.g., a GPU or device memory are kept allocated (but removed from user control via containers) and are directly reused
resets all meta data
note: might trigger de-allocations and allocations in members, but might be able to reuse some or all memory
Destructor:
deallocate ressources (e.g., containers and their memory)
unsign from DataConnector (not implemented)
For functions that are currently not splitted or not useful to be splitted between allocate() and initialize() call them
Name (and introduce where missing) all allocation and initialization members correctly.
WIP: separate this scheme for containers (RAII) and control objects/wrappers (sim/plugin, GridBuffer).
Containers
Currently as RAII Containers which works best for stack allocated objects.
It is worth noting that one can still be RAII when doing "late allocating" with, e.g.,
resize(n, value)
(allocate(n, functor)
) as instd::vector
. As you see the only constructors being RAII are empty (default) or fill, range, copy, ... (move, =) but not "create size N and do not initialize with a value".Classes:
HostBufferIntern
,DeviceBufferIntern
get/setCurrentSize
)to do:
reserve
constructor that only increasescapacity
but notsize
(does allocate but no uninitialized memory is exposed -> RAII ok; BUT general "accelerator" memory might only really be allocated on use as it is already seen on the host, so this constructor might still need a "memset" to an (unexposed) but random value per element to make sure the allocation happened while keepingsize
at zero (optimization: for current cuda architectures one might be able to skip the memset)resize(DataSpace, functor())
member to aquire and fill valuesresize(DataSpace, val)
,assign
, etc.reset
->resize(0)
should not set the fill level (size) to maximum (=capacity) but to0
resize(0)
is not the same asclear()
sinceclear
is allowed to deallocate resources, we do not want to deallocate in many cases;resize()
does exactly that: for0
input it does not changecapacity
butsize
(and we can disallow increasing capacity after first allocation if we want)Wrappers that store and organize containers
Classes:
GridBuffer
(has two RAII container members for host/device + exchanges),ParticlesBuffer
(has severalGridBuffer
s) ...delegate (mix) concepts between:
Simulation and Plugin Objects
[WIP] would be interesting if one can make these RAII without making life horrible...
size
to usersDataConnector
size
(currentSize) zero but internally allocated (this memory is not exposed to user)initialize()
/assign()
:clear()
:allocateEmpty()
soinitialize()
can be called againdeallocate()
+allocateEmpty()
since some ressources, e.g., a GPU or device memory are kept allocated (but removed from user control via containers) and are directly reusedDataConnector
(not implemented)For functions that are currently not splitted or not useful to be splitted between
allocate()
andinitialize()
call themallocateAndInitialize()
Components that need work
PIConGPU
CallInit
SimulationHelper
/MySimulation
PMacc
Buffer
andBoxes
inlibPMacc/include/memory/