Skip to content

Commit 6889bc6

Browse files
committed
Add an implementation of ParticleCopyPlan::doHandShake that uses one-sided communication from MPI-3
1 parent 2922573 commit 6889bc6

File tree

2 files changed

+65
-4
lines changed

2 files changed

+65
-4
lines changed

Src/Particle/AMReX_ParticleCommunication.H

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <AMReX_Scan.H>
1111
#include <AMReX_TypeTraits.H>
1212
#include <AMReX_MakeParticle.H>
13+
#include <AMReX_ParmParse.H>
1314

1415
#include <map>
1516

@@ -137,6 +138,8 @@ struct ParticleCopyPlan
137138
BL_PROFILE("ParticleCopyPlan::build");
138139

139140
m_local = local;
141+
ParmParse pp("particles");
142+
pp.query("do_one_sided_comms", m_do_one_sided_comms);
140143

141144
const int ngrow = 1; // note - fix
142145

@@ -294,14 +297,21 @@ private:
294297
// In the global version, we don't know who we'll receive from, so we
295298
// need to do some collective communication first.
296299
//
297-
static void doHandShakeGlobal (const Vector<Long>& Snds, Vector<Long>& Rcvs);
300+
static void doHandShakeReduceScatter (const Vector<Long>& Snds, Vector<Long>& Rcvs);
301+
302+
//
303+
// Another version of the global handshake implemented with MPI-3
304+
// one-sided communication.
305+
//
306+
static void doHandShakeOneSided (const Vector<Long>& Snds, Vector<Long>& Rcvs);
298307

299308
//
300309
// Another version of the above that is implemented using MPI All-to-All
301310
//
302311
static void doHandShakeAllToAll (const Vector<Long>& Snds, Vector<Long>& Rcvs);
303312

304-
bool m_local;
313+
bool m_local = false;
314+
int m_do_one_sided_comms = 0;
305315
};
306316

307317
struct GetSendBufferOffset

Src/Particle/AMReX_ParticleCommunication.cpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,14 @@ void ParticleCopyPlan::doHandShake (const Vector<Long>& Snds, Vector<Long>& Rcvs
263263
{
264264
BL_PROFILE("ParticleCopyPlan::doHandShake");
265265
if (m_local) { doHandShakeLocal(Snds, Rcvs); }
266-
else { doHandShakeGlobal(Snds, Rcvs); }
266+
else if (m_do_one_sided_comms) {
267+
#if defined(BL_USE_MPI3)
268+
doHandShakeOneSided(Snds, Rcvs);
269+
#else
270+
amrex::Abort("ParticleCopyPlan::doHandShake: particles.do_one_sided_comms=1 requires MPI-3");
271+
#endif
272+
}
273+
else { doHandShakeReduceScatter(Snds, Rcvs); }
267274
}
268275

269276
void ParticleCopyPlan::doHandShakeLocal (const Vector<Long>& Snds, Vector<Long>& Rcvs) const // NOLINT(readability-convert-member-functions-to-static)
@@ -333,7 +340,7 @@ void ParticleCopyPlan::doHandShakeAllToAll (const Vector<Long>& Snds, Vector<Lon
333340
#endif
334341
}
335342

336-
void ParticleCopyPlan::doHandShakeGlobal (const Vector<Long>& Snds, Vector<Long>& Rcvs)
343+
void ParticleCopyPlan::doHandShakeReduceScatter (const Vector<Long>& Snds, Vector<Long>& Rcvs)
337344
{
338345
#ifdef AMREX_USE_MPI
339346
const int SeqNum = ParallelDescriptor::SeqNum();
@@ -381,6 +388,50 @@ void ParticleCopyPlan::doHandShakeGlobal (const Vector<Long>& Snds, Vector<Long>
381388
#endif
382389
}
383390

391+
void ParticleCopyPlan::doHandShakeOneSided (const Vector<Long>& Snds, Vector<Long>& Rcvs)
392+
{
393+
#if defined(AMREX_USE_MPI) && defined(BL_USE_MPI3)
394+
const int MyProc = ParallelContext::MyProcSub();
395+
const int NProcs = ParallelContext::NProcsSub();
396+
397+
AMREX_ALWAYS_ASSERT(static_cast<int>(Snds.size()) == NProcs);
398+
AMREX_ALWAYS_ASSERT(static_cast<int>(Rcvs.size()) == NProcs);
399+
400+
std::fill(Rcvs.begin(), Rcvs.end(), 0);
401+
402+
MPI_Win win;
403+
BL_MPI_REQUIRE(MPI_Win_create(Rcvs.dataPtr(),
404+
static_cast<MPI_Aint>(NProcs*sizeof(Long)),
405+
sizeof(Long),
406+
MPI_INFO_NULL,
407+
ParallelContext::CommunicatorSub(),
408+
&win));
409+
410+
BL_MPI_REQUIRE(MPI_Win_fence(0, win));
411+
412+
for (int i = 0; i < NProcs; ++i)
413+
{
414+
if (i == MyProc || Snds[i] == 0) { continue; }
415+
416+
BL_MPI_REQUIRE(MPI_Put(&Snds[i],
417+
1,
418+
ParallelDescriptor::Mpi_typemap<Long>::type(),
419+
i,
420+
MyProc,
421+
1,
422+
ParallelDescriptor::Mpi_typemap<Long>::type(),
423+
win));
424+
}
425+
426+
BL_MPI_REQUIRE(MPI_Win_fence(0, win));
427+
BL_MPI_REQUIRE(MPI_Win_free(&win));
428+
429+
AMREX_ASSERT(Rcvs[MyProc] == 0);
430+
#else
431+
amrex::ignore_unused(Snds,Rcvs);
432+
#endif
433+
}
434+
384435
void communicateParticlesFinish (const ParticleCopyPlan& plan)
385436
{
386437
BL_PROFILE("amrex::communicateParticlesFinish");

0 commit comments

Comments
 (0)