Exchangers¶
A set of classes responsible to:
- exchange ghost paticles between neighbouring ranks
- redistribite particles accross ranks
The implementation is split into two parts:
- exchanger classes, that are responsible to pack and unpack the data from
mirheo::ParticleVector
to buffers (see also Packers). - communication engines, that communicate the buffers created by the exchangers between ranks. The user must instantiate one engine per exchanger.
Exchanger classes¶
Different kind of exchange are implemented in Mirheo:
- Redistribution: the data is migrated from one rank to another
(see
mirheo::ParticleRedistributor
andmirheo::ObjectRedistributor
) - Ghost particles: the data is copied from one rank to possibly multiple ones
(see
mirheo::ParticleHaloExchanger
,mirheo::ObjectHaloExchanger
andmirheo::ObjectExtraExchanger
) - Reverse exchange: data is copied from possibly multiple ranks to another.
This can be used to gather e.g. the forces computed on ghost particles,
and therefore is related to the ghost particles exchangers.
(see
mirheo::ObjectReverseExchanger
)
In general, the process consists in:
- Create a map from particle/object to buffer(s) (this step might be unnecessary for e.g.
mirheo::ObjectExtraExchanger
andmirheo::ObjectReverseExchanger
) - Pack the data into the send buffers according to the map
- The communication engines communicate the data to the recv buffers (not the exchangers job)
- Unpack the data from recv buffers to a local container.
Interface¶
-
class
Exchanger
¶ Pack and unpack
ParticleVector
objects for exchange.The user should register one (or more) ExchangeEntity objects that represent the data to exchange. The functions interface functions can then be called in the correct order to pack and unpack the data.
Designed to be used with an ExchangeEngine.
Subclassed by mirheo::ObjectExtraExchanger, mirheo::ObjectHaloExchanger, mirheo::ObjectRedistributor, mirheo::ObjectReverseExchanger, mirheo::ParticleHaloExchanger, mirheo::ParticleRedistributor
Public Functions
-
void
addExchangeEntity
(std::unique_ptr<ExchangeEntity> &&e)¶ register an ExchangeEntity in this exchanger.
- Parameters
e
: The ExchangeEntity object to register. Will pass ownership.
-
ExchangeEntity *
getExchangeEntity
(size_t id)¶ - Return
- ExchangeEntity with the given id (0 <= id < getNumExchangeEntities()).
-
const ExchangeEntity *
getExchangeEntity
(size_t id) const¶
-
size_t
getNumExchangeEntities
() const¶ - Return
- The number of registered ExchangeEntity.
-
virtual void
prepareSizes
(size_t id, cudaStream_t stream) = 0¶ Compute the sizes of the data to be communicated in the given ExchangeEntity.
After this call, the
send.sizes
,send.sizeBytes
,send.offsets
andsend.offsetsBytes
of the ExchangeEntity are available on the CPU.- Parameters
id
: The index of the concerned ExchangeEntitystream
: Execution stream
-
virtual void
prepareData
(size_t id, cudaStream_t stream) = 0¶ Pack the data managed by the given ExchangeEntity.
- Note
- Must be executed after prepareSizes()
- Parameters
id
: The index of the concerned ExchangeEntitystream
: Execution stream
-
virtual void
combineAndUploadData
(size_t id, cudaStream_t stream) = 0¶ Unpack the received data.
After this call, the
recv.sizes
,recv.sizeBytes
,recv.offsets
andrecv.offsetsBytes
of the ExchangeEntity must be available on the CPU and GPU before this call. Furthermore, the recv buffers must already be on the device memory.- Parameters
id
: The index of the concerned ExchangeEntitystream
: Execution stream
- Note
- Must be executed after prepareData()
-
virtual bool
needExchange
(size_t id) = 0¶ Stats if the data of an ExchangeEntity needs to be exchanged.
If the
ParticleVector didn’t change since the last exchange, there is no need to run the exchange again. This function controls such behaviour.- Return
true
if exchange is required,false
otherwise- Parameters
id
: The index of the concerned ExchangeEntity
-
void
Derived classes¶
-
class
ParticleRedistributor
: public mirheo::Exchanger¶ Pack and unpack data for particle redistribution.
The redistribution consists in moving (not copying) the particles from one rank to the other. It affects all particles that have left the current subdomain. The redistribution is accelerated by making use of the cell-lists of the ParticleVector. This allows to check only the particles that are on the boundary cells; However, this assumes that only those particles leave the domain.
Public Functions
-
ParticleRedistributor
()¶ default constructor
-
void
attach
(ParticleVector *pv, CellList *cl)¶ Add a ParticleVector to the redistribution.
Multiple
ParticleVector objects can be attached to the same redistribution object.- Parameters
pv
: The ParticleVector to attachcl
: The associated cell-list ofpv
.
-
-
class
ObjectRedistributor
: public mirheo::Exchanger¶ Pack and unpack data for object redistribution.
As opposed to particles, objects must be redistributed as a whole for two reasons:
- the particles of one object must stay into a contiguous chunk in memory
- the objects might have associated data per object (or per bisegments for rods)
The redistribution consists in moving (not copying) the object data from one rank to the other. It affects all objects that have left the current subdomain (an object belongs to a subdomain if its center of mass is inside).
Public Functions
-
ObjectRedistributor
()¶ default constructor
-
void
attach
(ObjectVector *ov)¶ Add an ObjectVector to the redistribution.
Multiple
ObjectVector objects can be attached to the same redistribution object.- Parameters
ov
: The ObjectVector to attach
-
class
ParticleHaloExchanger
: public mirheo::Exchanger¶ Pack and unpack data for halo particles exchange.
The halo exchange consists in copying an image of all particles that are within one cut-off radius away to the neighbouring ranks. This leaves the original ParticleVector local data untouched. The result of this operation is stored in the halo LocalParticleVector.
The halo exchange is accelerated by making use of the associated CellList of the ParticleVector.
Public Functions
-
ParticleHaloExchanger
()¶ default constructor
-
void
attach
(ParticleVector *pv, CellList *cl, const std::vector<std::string> &extraChannelNames)¶ Add a ParticleVector for halo exchange.
Multiple
ParticleVector objects can be attached to the same halo exchanger.- Parameters
pv
: The ParticleVector to attachcl
: The associated cell-list ofpv
extraChannelNames
: The list of channels to exchange (additionally to the default positions and velocities)
-
-
class
ObjectHaloExchanger
: public mirheo::Exchanger¶ Pack and unpack data for halo object exchange.
The halo exchange consists in copying an image of all objects with bounding box that is within one cut-off radius away to the neighbouring ranks. This leaves the original ObjectVector local data untouched. The result of this operation is stored in the halo LocalObjectVector.
This is needed only when the full object is needed on the neighbour ranks (e.g.
Bouncer
or ObjectBelongingChecker).Public Functions
-
ObjectHaloExchanger
()¶ default constructor
-
void
attach
(ObjectVector *ov, real rc, const std::vector<std::string> &extraChannelNames)¶ Add a ObjectVector for halo exchange.
Multiple
ObjectVector objects can be attached to the same halo exchanger.- Parameters
ov
: The ObjectVector to attachrc
: The required cut-off radiusextraChannelNames
: The list of channels to exchange (additionally to the default positions and velocities)
-
PinnedBuffer<int> &
getSendOffsets
(size_t id)¶ - Return
- send offset within the send buffer (in number of elements) of the given ov
-
PinnedBuffer<int> &
getRecvOffsets
(size_t id)¶ - Return
- recv offset within the send buffer (in number of elements) of the given ov
-
DeviceBuffer<MapEntry> &
getMap
(size_t id)¶ - Return
- The map from LocalObjectVector to send buffer ids
-
-
class
ObjectExtraExchanger
: public mirheo::Exchanger¶ Pack and unpack extra data for halo object exchange.
This class only exchanges the additional data (not e.g. the default particle’s positions and velocities). It uses the packing map from an external
ObjectHaloExchanger. The attached ObjectVector objects must be the same as the ones in the external ObjectHaloExchanger (and in the same order).Public Functions
-
ObjectExtraExchanger
(ObjectHaloExchanger *entangledHaloExchanger)¶ Construct a ObjectExtraExchanger.
- Parameters
entangledHaloExchanger
: The object that will contain the packing maps.
-
void
attach
(ObjectVector *ov, const std::vector<std::string> &extraChannelNames)¶ Add a ObjectVector for halo exchange.
- Parameters
ov
: The ObjectVector to attachextraChannelNames
: The list of channels to exchange
-
-
class
ObjectReverseExchanger
: public mirheo::Exchanger¶ Pack and unpack data from ghost particles back to the original bulk data.
The ghost particles data must come from a ObjectHaloExchanger object. The attached ObjectVector objects must be the same as the ones in the external ObjectHaloExchanger (and in the same order).
Public Functions
-
ObjectReverseExchanger
(ObjectHaloExchanger *entangledHaloExchanger)¶ Construct a ObjectReverseExchanger.
- Parameters
entangledHaloExchanger
: The object that will create the ghost particles.
-
void
attach
(ObjectVector *ov, std::vector<std::string> channelNames)¶ Add an ObjectVector for reverse halo exchange.
- Parameters
ov
: The ObjectVector to attachchannelNames
: The list of channels to send back
-
Exchange Entity¶
Helper classes responsible to hold the buffers of the packed data to be communicated.
-
struct
BufferOffsetsSizesWrap
¶ A device-compatible structure that holds buffer information for packing / unpacking data.
In general, there is one buffer per source/destination rank. The current implementation uses a single array that contains all buffers in a contiguous way. The offsetsBytes values (one per buffer) state where each buffer start within the array.
Public Functions
-
char *
getBuffer
(int bufId)¶ - Return
- buffer with id
bufId
-
char *
-
struct
BufferInfos
¶ Structure held on the host only that contains pack/unpack buffers and their sizes/offsets (see BufferOffsetsSizesWrap).
Public Functions
-
void
clearAllSizes
(cudaStream_t stream)¶ set sizes and sizesBytes to zero on host and device
-
void
resizeInfos
(int nBuffers)¶ resize the size and offset buffers to support a given number of buffers
-
void
uploadInfosToDevice
(cudaStream_t stream)¶ upload all size and offset information from host to device
-
char *
getBufferDevPtr
(int bufId)¶ - Return
- The device pointer to the buffer with the given index
Public Members
-
PinnedBuffer<int>
sizes
¶ number of elements in each buffer
-
PinnedBuffer<int>
offsets
¶ prefix sum of the above
-
PinnedBuffer<size_t>
sizesBytes
¶ number of bytes per buffer
-
PinnedBuffer<size_t>
offsetsBytes
¶ start of each buffer (in bytes) within the array
-
PinnedBuffer<char>
buffer
¶ all buffers in contiguous memory.
-
std::vector<MPI_Request>
requests
¶ send or recv requests associated to each buffer; only relevant for MPIExchangeEngine
-
void
-
class
ExchangeEntity
¶ Manages communication data per ParticleVector.
Each ExchangeEntity holds send and recv BufferInfos object for a given ParticleVector.
Public Functions
-
ExchangeEntity
(std::string name, int uniqueId, ParticlePacker *packer)¶ Construct an ExchangeEntity object.
- Parameters
name
: The name of the Corresponding ParticleVectoruniqueId
: A positive integer. This must be unique when a collection of ExchangeEntity objects is registered in a singleExchanger
.packer
: The class used to pack/unpack the data into buffers
-
void
computeRecvOffsets
()¶ Compute the recv offsets and offsetsBytes on the host.
- Note
- the recv sizes must be available on the host.
-
void
computeSendOffsets
()¶ Compute the send offsets and offsetsBytes on the host.
- Note
- the send sizes must be available on the host.
-
void
computeSendOffsets_Dev2Dev
(cudaStream_t stream)¶ Compute the send offsets and offsetBytes on the device and download all sizes and offsets on the host.
- Note
- The send sizes must be available on the device
-
void
resizeSendBuf
()¶ resize the internal send buffers; requires send offsetsBytes to be available on the host
-
void
resizeRecvBuf
()¶ resize the internal recv buffers; requires recv offsetsBytes to be available on the host
-
int
getUniqueId
() const¶ - Return
- the unique id
-
BufferOffsetsSizesWrap
wrapSendData
()¶ - Return
- a BufferOffsetsSizesWrap from the send BufferInfos
-
BufferOffsetsSizesWrap
wrapRecvData
()¶ - Return
- a BufferOffsetsSizesWrap from the recv BufferInfos
-
const std::string &
getName
() const¶ - Return
- the name of the attached ParticleVector
-
const char *
getCName
() const¶ - Return
- the name of the attached ParticleVector in c-style string
Public Members
-
const int
nBuffers
= fragment_mapping::numFragments¶ equal to number of neighbours + 1 (for bulk)
-
const int
bulkId
= fragment_mapping::bulkId¶ The index of the bulk buffer.
-
BufferInfos
send
¶ buffers for the send data
-
BufferInfos
recv
¶ buffers for the recv data
-
std::vector<int>
recvRequestIdxs
¶ only relevant for MPIExchangeEngine
-
Communication engines¶
Interface¶
-
class
ExchangeEngine
¶ Base communication engine class.
Responsible to communicate the data managed by an
Exchanger
between different subdomains. The communication is split into two parts so that asynchronous communication can be used. Every init() call must have a single finalize() call that follows.Subclassed by mirheo::MPIExchangeEngine, mirheo::SingleNodeExchangeEngine
Public Functions
-
ExchangeEngine
(std::unique_ptr<Exchanger> &&exchanger)¶ Construct a communication engine.
- Parameters
exchanger
: TheExchanger
object that will prepare the data to communicate. The ownership of exchanger is transfered to the engine.
-
virtual void
init
(cudaStream_t stream) = 0¶ Initialize the communication.
The data packing from the exchanger happens in this step.
- Parameters
stream
: Execution stream used to prepare / download the data
-
Derived classes¶
-
class
MPIExchangeEngine
: public mirheo::ExchangeEngine¶ Engine implementing asynchronous MPI communication.
The pipeline is as follows:
- init() prepares the data into buffers, exchange the sizes, allocate recv buffers and post the asynchronous communication calls.
- finalize() waits for the communication to finish and unpacks the data.
Public Functions
-
MPIExchangeEngine
(std::unique_ptr<Exchanger> &&exchanger, MPI_Comm comm, bool gpuAwareMPI)¶ Construct a MPIExchangeEngine.
- Parameters
exchanger
: The class responsible to pack and unpack the data.comm
: The cartesian communicator that represents the simulation domain.gpuAwareMPI
:true
to enable RDMA implementation. Only works if the MPI library has this feature implemented.
-
void
init
(cudaStream_t stream)¶ Initialize the communication.
The data packing from the exchanger happens in this step.
- Parameters
stream
: Execution stream used to prepare / download the data
-
class
SingleNodeExchangeEngine
: public mirheo::ExchangeEngine¶ Special engine optimized for single node simulations.
Instead of communicating thedata through MPI, the send and recv buffers are simply swapped.
Public Functions
-
SingleNodeExchangeEngine
(std::unique_ptr<Exchanger> &&exchanger)¶ Construct a SingleNodeExchangeEngine.
- Parameters
exchanger
: The class responsible to pack and unpack the data.
-
void
init
(cudaStream_t stream)¶ Initialize the communication.
The data packing from the exchanger happens in this step.
- Parameters
stream
: Execution stream used to prepare / download the data
-