Remote communication
Sometimes during the course of local communication, it's necessary to send or receive messages outside of the local
neighborhood. For example in particle tracing, a local algorithm that exchanges particles as they cross neighboring
block boundaries, the block containing a particle's final destination may need to send summary statistics carried along
by the particle (such as total number of hops) back to the originating block where the particle began its journey. For
such cases, there is a remote version of diy::Master::exchange()
.
Synchronous remote rexchange
Everything follows the synchronous exchange
protocol of the Local communication page, except that a
remote
flag set to true
is passed to master.exchange
, and the master.foreach()
callback functions can access
blocks outside of their neighborhood.
When enqueuing data remotely, DIY doesn't know the assignment of block global ID (gid
) to MPI process rank; this
information is only kept for the local link. Hence, the full diy::BlockID
information (a tuple of block gid and MPI
process rank) must be provided by the user. For dequeuing, we iterate over a vector of incoming block gids
extracted from the communication proxy, and then dequeue each of those messages.
void foo(Block* b, // local block
const diy::Master::ProxyWithLink& cp) // communication proxy for neighbor blocks
{
diy::Link* l = cp.link(); // link to the neighbor blocks
// compute some local value
...
// for all neighbor blocks, enqueue data going to this neighbor block in the next exchange
for (int i = 0; i < l->size(); ++i)
cp.enqueue(l->target(i), value);
// enqueue something remote outside of the neighborhood
int dest_gid = ...; // block global ID of destination
int dest_proc = ...; // MPI process of destination block
diy::BlockID dest_block = {dest_gid, dest_proc};
cp.enqueue(dest_block, value);
}
void bar(Block* b, // local block
const diy::Master::ProxyWithLink& cp) // communication proxy for neighbor blocks
{
std::vector<int> incoming_gids;
cp.incoming(incoming_gids);
// for anything incoming, dequeue data received in the last exchange
for (int i = 0; i < incoming_gids.size(); i++)
{
int gid = incoming_gids[i];
if (cp.incoming(gid).size())
{
int v;
cp.dequeue(gid, v);
}
}
// compute some local value
...
}
int main(int argc, char**argv)
{
...
bool remote = true;
master.foreach(&foo);
master.exchange(remote);
master.foreach(&bar);
}