Peano 4
Loading...
Searching...
No Matches
peano4::stacks::STDVectorStackOverSmartPointers< T > Class Template Reference

This stack hosts data of constant size which are stored on the heap and subject to smart pointers. More...

#include <STDVectorStackOverSmartPointers.h>

Collaboration diagram for peano4::stacks::STDVectorStackOverSmartPointers< T >:

Data Structures

class  PopBlockStackView
 This class represents a whole block of the tree. More...
 
class  PushBlockStackView
 

Public Member Functions

 STDVectorStackOverSmartPointers ()
 
 STDVectorStackOverSmartPointers (const STDVectorStackOverSmartPointers< T > &)
 
STDVectorStackOverSmartPointers< T > & operator= (const STDVectorStackOverSmartPointers< T > &stack)
 One is allowed to copy a stack but it has to be empty.
 
void clone (const STDVectorStackOverSmartPointers< T > &data)
 Clone data into the current object on which clone() is called.
 
pop ()
 Pops element from a stack.
 
T & top (int shift=0)
 Get top element or shiftth top element.
 
const T & top (int shift=0) const
 Get top element or shiftth top element.
 
void push (const T &element)
 Pushes element to a stack.
 
PopBlockStackView popBlock (int numberOfElements)
 This operation grabs numberOfElements from the input stack en block and returns a view to it.
 
PushBlockStackView pushBlock (int numberOfElements)
 Push a block on the output stack.
 
int size () const
 
bool empty () const
 
void clear ()
 
void startSend (peano4::grid::TraversalObserver::SendReceiveContext context, int rank, int tag, MPI_Comm comm)
 Start the actual send process.
 
void startReceive (peano4::grid::TraversalObserver::SendReceiveContext context, int rank, int tag, MPI_Comm comm, int numberOfElements)
 Counterpart of startSend()
 
bool tryToFinishSendOrReceive ()
 Semantics are alost an exact 1:1 copy of the superclass implementation.
 
int sendingOrReceiving () const
 I need this one to find out whether I'm waiting for data.
 
void reverse ()
 Reversing a stream is something I need extremely rarely.
 
std::string toString () const
 

Private Member Functions

void gather ()
 Allocate buffer and gather.
 
void prepareGatheredDataBuffer ()
 Mere alloc.
 
void scatter ()
 Scatter received gathered data.
 
void gatherMetaData ()
 Allocate buffer and gather.
 
void prepareMetaDataBuffers ()
 Mere alloc.
 
void scatterDebugMetaData ()
 

Private Attributes

std::vector< T > _data
 This is the attribute holding all the temporary stacks.
 
T::DoFType * _gatheredData
 See MPI routines below.
 
int_gatheredMetaData
 Meta data with size of memory chunks.
 
double * _gatheredDebugMetaData
 Debug data.
 
IOMode _ioMode
 
int _ioRank
 
int _ioTag
 
MPI_Request * _ioMPIRequest
 
MPI_Request * _ioMetaDataMPIRequest
 
MPI_Request * _ioDebugMetaDataMPIRequest
 

Static Private Attributes

static tarch::logging::Log _log
 Logging device.
 

Detailed Description

template<class T>
class peano4::stacks::STDVectorStackOverSmartPointers< T >

This stack hosts data of constant size which are stored on the heap and subject to smart pointers.

We assume that that the object stored on the stack

  • all point to a memory region of the same size
  • offer a field T::Cardinality which tells us what this size is
  • defines a native pointer value which points to actual data

Once we work with smart pointers, we can work with shallow copies as data travel over the individual stacks. This implies that we "only" have to make the clones for the data exchange between threads and ranks actual deep copies.

Special care is however required if we work with solver localisation, i.e. solvers which do not store data in each and every grid entity. If a solver decides not to store a certain piece of data, the underlying value pointer will exist but will point to nullptr. So we may not attempt to deep copy it, but instead need to ensure that the cloned vector will hold nullptr, too.

MPI

One tricky aspect in the context of smart pointers is actually the MPI data exchange which has to take into account that data are scattered over the heap. See the documentation of the send/receive operations. They discuss how the business with the required deep copies actually works. Anyway, to make it work, we need the used datatype T to have two fields:

  • A type expression DoFType;
  • A constexpr int Cardinality.

The other tricky thing is that some mesh entities might hold nullptrs. We now have two options:

  1. We actually only flatten the non-nullptr data.
  2. We send out a huge array with "all" flattened data and take into account that some data within this array hold garbage, as the actual data actually dd point to nullptr.

We go down the latter route. It would be no problem to squeeze out areas in the flattened/gathered area which correspond to nullptr. Yet, if we do so we do not know a priori how big the outgoing data will be. This implies that we have to send out the data in two chunks: First the meta data and then we can trigger the corresponding receive call with a matching size. This is too complicated for me. I just send out everything - including rubbish.

Comparison to normal STD stack

The normal stack works with the STL stack yet never shrinks it. This is to avoid too many memory relocations. Instead, it holds an integer counter which always clarifies how many elements in the STL container hole valid data.

The present container works with the "native" STL container.

Parameters
THosts usually pointer which is backed up by a smart pointer, i.e. deleted as soon as noone needs it anymore. T has to provide a clone() operation.

Definition at line 92 of file STDVectorStackOverSmartPointers.h.

Constructor & Destructor Documentation

◆ STDVectorStackOverSmartPointers() [1/2]

template<class T >
peano4::stacks::STDVectorStackOverSmartPointers< T >::STDVectorStackOverSmartPointers ( )

Definition at line 8 of file STDVectorStackOverSmartPointers.cpph.

◆ STDVectorStackOverSmartPointers() [2/2]

Member Function Documentation

◆ clear()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::clear ( )

Definition at line 337 of file STDVectorStackOverSmartPointers.cpph.

Referenced by peano4.output.Makefile.Makefile::__init__().

Here is the caller graph for this function:

◆ clone()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::clone ( const STDVectorStackOverSmartPointers< T > & data)

Clone data into the current object on which clone() is called.

This operation overwrites the baseclass version. If we called the plain base class version, we would end up with a shallow copy. However, we want a semi-shallow copy: We replicate the meta data, and then we call the clone() of the actual vector over pointers. It is up to this routine if we craete a shallow copy or not.

Read the class documentation why I think that the clone() on the subvectors should create a deep copy. It is the section on intra-node parallelisation.

This operation has to use the default constructor of T to resize, as we want the destination data structure to be able to host the target data. So it has to issue all the news if required.

Definition at line 54 of file STDVectorStackOverSmartPointers.cpph.

References assertion1, logDebug, and toString().

Here is the call graph for this function:

◆ empty()

template<class T >
bool peano4::stacks::STDVectorStackOverSmartPointers< T >::empty ( ) const

Definition at line 332 of file STDVectorStackOverSmartPointers.cpph.

◆ gather()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::gather ( )
private

Allocate buffer and gather.

Definition at line 157 of file STDVectorStackOverSmartPointers.cpph.

References assertion, logDebug, and toString().

Here is the call graph for this function:

◆ gatherMetaData()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::gatherMetaData ( )
private

Allocate buffer and gather.

Definition at line 68 of file STDVectorStackOverSmartPointers.cpph.

References assertion, and logDebug.

◆ operator=()

One is allowed to copy a stack but it has to be empty.

Definition at line 189 of file STDVectorStackOverSmartPointers.h.

References peano4::stacks::STDVectorStackOverSmartPointers< T >::_data, and assertion.

◆ pop()

template<class T >
T peano4::stacks::STDVectorStackOverSmartPointers< T >::pop ( )

Pops element from a stack.

I have to be careful how and why I use std::move here, as we employ smart pointers. I found that a move after the return confuses the reference counting, and eventually leads to memory leaks.

Definition at line 359 of file STDVectorStackOverSmartPointers.cpph.

References assertion.

◆ popBlock()

template<class T >
peano4::stacks::STDVectorStackOverSmartPointers< T >::PopBlockStackView peano4::stacks::STDVectorStackOverSmartPointers< T >::popBlock ( int numberOfElements)

This operation grabs numberOfElements from the input stack en block and returns a view to it.

Subsequent pops do not affect this block anymore, i.e. the stack is reduced immediately.

Parameters
numberOfElementsSize of the view

Definition at line 385 of file STDVectorStackOverSmartPointers.cpph.

◆ prepareGatheredDataBuffer()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::prepareGatheredDataBuffer ( )
private

Mere alloc.

We use the tarch's allocation. Therefore, we can have aligned data here. Without the tarch, the code call would be

    _gatheredData     = new typename T::DoFType[ size() * T::Cardinality ];

Definition at line 172 of file STDVectorStackOverSmartPointers.cpph.

References tarch::Heap, and logDebug.

◆ prepareMetaDataBuffers()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::prepareMetaDataBuffers ( )
private

Mere alloc.

We use the tarch's allocation. Therefore, we can have aligned data here. Without tarch, the call would be

    _gatheredDebugMetaData = new double[ Dimensions*2*size() ];

Definition at line 97 of file STDVectorStackOverSmartPointers.cpph.

References tarch::allocateMemory(), tarch::Heap, and logDebug.

Here is the call graph for this function:

◆ push()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::push ( const T & element)

Pushes element to a stack.

Definition at line 379 of file STDVectorStackOverSmartPointers.cpph.

◆ pushBlock()

template<class T >
peano4::stacks::STDVectorStackOverSmartPointers< T >::PushBlockStackView peano4::stacks::STDVectorStackOverSmartPointers< T >::pushBlock ( int numberOfElements)

Push a block on the output stack.

Parameters
numberOfElementsSize of the view

Definition at line 391 of file STDVectorStackOverSmartPointers.cpph.

◆ reverse()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::reverse ( )

Reversing a stream is something I need extremely rarely.

The biggest application is the realisation of joins through peano4::parallel::SpacetreeSet::streamLocalVertexInformationToMasterThroughVerticalStacks(). Here, I need a streamed version of the tree to get the up-to-date data of the mesh in. However, I don't have streams. I have only stacks. So I map the stream idea to a stack.

Definition at line 347 of file STDVectorStackOverSmartPointers.cpph.

◆ scatter()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::scatter ( )
private

Scatter received gathered data.

We run over the size keeping in mind that the target has been created over objects with the constructor argument T::ObjectConstruction::NoData. That is, each entry hosts a pointer, but this pointer will currently point to nullptr, as the object is not yet prepared to host any data. We run over the meta data to find out if this is ok, or if we actually want this stack entry to host data. If so, we use the "real" constructor and then copy the raw content over from the gathered data set.

Definition at line 135 of file STDVectorStackOverSmartPointers.cpph.

References assertion, and logDebug.

◆ scatterDebugMetaData()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::scatterDebugMetaData ( )
private

Definition at line 106 of file STDVectorStackOverSmartPointers.cpph.

References logDebug.

◆ sendingOrReceiving()

template<class T >
int peano4::stacks::STDVectorStackOverSmartPointers< T >::sendingOrReceiving ( ) const

I need this one to find out whether I'm waiting for data.

Returns
A negative value if we don't send or receive anymore. Otherwise, we return the rank of the communication partner.

Definition at line 342 of file STDVectorStackOverSmartPointers.cpph.

References peano4::stacks::None.

◆ size()

◆ startReceive()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::startReceive ( peano4::grid::TraversalObserver::SendReceiveContext context,
int rank,
int tag,
MPI_Comm comm,
int numberOfElements )

Counterpart of startSend()

We have to prepare the en bloc, raw data buffers for both the data and the meta data (if required). After that, we can trigger the two non-blocking receives.

See clone() for a description why we have to use resize() with the standard constructor here.

See also
startSend()

Definition at line 228 of file STDVectorStackOverSmartPointers.cpph.

References assertion, assertion3, logDebug, logError, peano4::stacks::MPIReceive, tarch::mpi::MPIReturnValueToString(), peano4::stacks::None, and toString().

Here is the call graph for this function:

◆ startSend()

template<class T >
void peano4::stacks::STDVectorStackOverSmartPointers< T >::startSend ( peano4::grid::TraversalObserver::SendReceiveContext context,
int rank,
int tag,
MPI_Comm comm )

Start the actual send process.

Always pairs up with a finish... call.

Gathering the data

As we have to assume that the data of interest are scattered over the main memory, we first allocate one big buffer for the data. This is a buffer over T::DoFType. We then copy the chunks over and send this block rather than the "original" stack data.

The meta data has to be treated (almost) in the same way: In this case, we create manually a buffer over 2 * Dimensions * no of elements doubles and then copy the meta data over one by one. That means: we do not expect T's datatype to encapsulate the meta data - which also doesn't make any sense as T's data itself is scattered over the memory since it works with pointers.

Cleaning up

All clean ups are realised within tryToFinishSendOrReceive() where I have to delete the gathered buffer. To save memory overall, I can delete the pointers to the data scattered over the memory straightaway once all is copied over. As these pointers are shared smart pointers, this immediate delete might free memory as the shared pointer counter reduces to zero.

Definition at line 182 of file STDVectorStackOverSmartPointers.cpph.

References assertion, logDebug, logError, tarch::mpi::MPIReturnValueToString(), peano4::stacks::MPISend, and peano4::stacks::None.

Here is the call graph for this function:

◆ top() [1/2]

template<class T >
T & peano4::stacks::STDVectorStackOverSmartPointers< T >::top ( int shift = 0)

Get top element or shiftth top element.

We start to count with 0, i.e. a shift of 0 (default) really returns the top element. A shift of 3 returns the fourth element from the stack

Definition at line 367 of file STDVectorStackOverSmartPointers.cpph.

References assertion.

◆ top() [2/2]

template<class T >
const T & peano4::stacks::STDVectorStackOverSmartPointers< T >::top ( int shift = 0) const

Get top element or shiftth top element.

We start to count with 0, i.e. a shift of 0 (default) really returns the top element. A shift of 3 returns the fourth element from the stack

Definition at line 373 of file STDVectorStackOverSmartPointers.cpph.

References assertion.

◆ toString()

template<class T >
std::string peano4::stacks::STDVectorStackOverSmartPointers< T >::toString ( ) const

Definition at line 352 of file STDVectorStackOverSmartPointers.cpph.

References toString().

Here is the call graph for this function:

◆ tryToFinishSendOrReceive()

template<class T >
bool peano4::stacks::STDVectorStackOverSmartPointers< T >::tryToFinishSendOrReceive ( )

Semantics are alost an exact 1:1 copy of the superclass implementation.

Clean up

If a send or receive had been pending and just completed, we start the actual clean up process.

As we know that MPI sends in order, we do not have to test for the meta data. Once the real data has dropped in, we know that the meta data are in place, too.

Rationale

I originally wanted to call the superclass and just free the buffer if its result is true. However, at the time when the result comes back, I do not know if it has just switched from false to true or had been true all along. To avoid complicated logic, I decided to replicate the parent data and to inject the free into the replicated code.

Definition at line 277 of file STDVectorStackOverSmartPointers.cpph.

References assertion, tarch::freeMemory(), tarch::Heap, logDebug, logTraceInWith4Arguments, logTraceOutWith1Argument, peano4::stacks::MPIReceive, peano4::stacks::MPISend, peano4::stacks::None, and toString().

Here is the call graph for this function:

Field Documentation

◆ _data

◆ _gatheredData

template<class T >
T::DoFType* peano4::stacks::STDVectorStackOverSmartPointers< T >::_gatheredData
private

See MPI routines below.

This routine holds the actual data in a continuous way.

Definition at line 109 of file STDVectorStackOverSmartPointers.h.

◆ _gatheredDebugMetaData

template<class T >
double* peano4::stacks::STDVectorStackOverSmartPointers< T >::_gatheredDebugMetaData
private

Debug data.

Is only used in debug mode to store the x and h values tied to each entry on the stack.

Definition at line 126 of file STDVectorStackOverSmartPointers.h.

◆ _gatheredMetaData

template<class T >
int* peano4::stacks::STDVectorStackOverSmartPointers< T >::_gatheredMetaData
private

Meta data with size of memory chunks.

The entries here hold either T::Cardinality or zero. In the latter case, any copy should reconstruct an entry with a nullptr. The entries effectively cluster _gatheredData into chunks.

Definition at line 118 of file STDVectorStackOverSmartPointers.h.

◆ _ioDebugMetaDataMPIRequest

template<class T >
MPI_Request* peano4::stacks::STDVectorStackOverSmartPointers< T >::_ioDebugMetaDataMPIRequest
private

◆ _ioMetaDataMPIRequest

template<class T >
MPI_Request* peano4::stacks::STDVectorStackOverSmartPointers< T >::_ioMetaDataMPIRequest
private

◆ _ioMode

template<class T >
IOMode peano4::stacks::STDVectorStackOverSmartPointers< T >::_ioMode
private

Definition at line 128 of file STDVectorStackOverSmartPointers.h.

◆ _ioMPIRequest

◆ _ioRank

template<class T >
int peano4::stacks::STDVectorStackOverSmartPointers< T >::_ioRank
private

Definition at line 129 of file STDVectorStackOverSmartPointers.h.

◆ _ioTag

template<class T >
int peano4::stacks::STDVectorStackOverSmartPointers< T >::_ioTag
private

Definition at line 130 of file STDVectorStackOverSmartPointers.h.

◆ _log

template<class T >
tarch::logging::Log peano4::stacks::STDVectorStackOverSmartPointers< T >::_log
staticprivate

Logging device.

Definition at line 97 of file STDVectorStackOverSmartPointers.h.


The documentation for this class was generated from the following files: