Skip to content

Commit 4fd42af

Browse files
committed
Restart from multiple patches
1 parent a5ec903 commit 4fd42af

File tree

1 file changed

+66
-65
lines changed

1 file changed

+66
-65
lines changed

include/picongpu/plugins/openPMD/restart/LoadSpecies.hpp

Lines changed: 66 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -103,33 +103,30 @@ namespace picongpu
103103

104104
auto numRanks = gc.getGlobalSize();
105105

106-
size_t patchIdx = getPatchIdx(params, particleSpecies);
106+
auto [fullMatches, partialMatches] = getPatchIdx(params, particleSpecies);
107107

108-
std::shared_ptr<uint64_t> fullParticlesInfoShared
109-
= particleSpecies.particlePatches["numParticles"][::openPMD::RecordComponent::SCALAR]
110-
.load<uint64_t>();
111-
particles.seriesFlush();
112-
uint64_t* fullParticlesInfo = fullParticlesInfoShared.get();
113-
114-
/* Run a prefix sum over the numParticles[0] element in
115-
* particlesInfo to retreive the offset of particles
116-
*/
117-
uint64_t particleOffset = 0u;
118-
/* count total number of particles on the device */
119-
uint64_t totalNumParticles = 0u;
120-
121-
assert(patchIdx < numRanks);
122-
123-
for(size_t i = 0u; i <= patchIdx; ++i)
108+
if(!partialMatches.empty())
124109
{
125-
if(i < patchIdx)
126-
particleOffset += fullParticlesInfo[i];
127-
if(i == patchIdx)
128-
totalNumParticles = fullParticlesInfo[i];
110+
std::cerr << "WARNING: Found " << partialMatches.size()
111+
<< " particle patches that only partially intersect with the local domain. Will ignore "
112+
"this patch and lose those particles."
113+
<< std::endl;
129114
}
130115

131-
log<picLog::INPUT_OUTPUT>("openPMD: Loading %1% particles from offset %2%")
132-
% (long long unsigned) totalNumParticles % (long long unsigned) particleOffset;
116+
std::shared_ptr<uint64_t> numParticlesShared
117+
= particleSpecies.particlePatches["numParticles"].load<uint64_t>();
118+
std::shared_ptr<uint64_t> numParticlesOffsetShared
119+
= particleSpecies.particlePatches["numParticlesOffset"].load<uint64_t>();
120+
particles.seriesFlush();
121+
uint64_t* patchNumParticles = numParticlesShared.get();
122+
uint64_t* patchNumParticlesOffset = numParticlesOffsetShared.get();
123+
124+
uint64_t totalNumParticles = std::transform_reduce(
125+
fullMatches.begin(),
126+
fullMatches.end(),
127+
0,
128+
/* reduce = */ [](uint64_t left, uint64_t right) { return left + right; },
129+
/* transform = */ [patchNumParticles](size_t patchIdx) { return patchNumParticles[patchIdx]; });
133130

134131
log<picLog::INPUT_OUTPUT>("openPMD: malloc mapped memory: %1%") % speciesName;
135132

@@ -146,43 +143,53 @@ namespace picongpu
146143
mallocMem;
147144
mallocMem(buffers, mappedFrame, maxChunkSize);
148145

149-
uint32_t const numLoadIterations
150-
= maxChunkSize == 0u ? 0u : alpaka::core::divCeil(totalNumParticles, maxChunkSize);
151-
152-
for(uint64_t loadRound = 0u; loadRound < numLoadIterations; ++loadRound)
146+
for(size_t const patchIdx : fullMatches)
153147
{
154-
auto particleLoadOffset = particleOffset + loadRound * maxChunkSize;
155-
auto numLeftParticles = totalNumParticles - loadRound * maxChunkSize;
148+
uint64_t particleOffset = patchNumParticlesOffset[patchIdx];
149+
uint64_t numParticles = patchNumParticles[patchIdx];
150+
151+
log<picLog::INPUT_OUTPUT>("openPMD: Loading %1% particles from offset %2%")
152+
% (long long unsigned) totalNumParticles % (long long unsigned) particleOffset;
153+
156154

157-
auto numParticlesCurrentBatch = std::min(numLeftParticles, maxChunkSize);
155+
uint32_t const numLoadIterations
156+
= maxChunkSize == 0u ? 0u : alpaka::core::divCeil(numParticles, maxChunkSize);
158157

159-
log<picLog::INPUT_OUTPUT>("openPMD: (begin) load species %1% round: %2%/%3%") % speciesName
160-
% (loadRound + 1) % numLoadIterations;
161-
if(numParticlesCurrentBatch != 0)
158+
for(uint64_t loadRound = 0u; loadRound < numLoadIterations; ++loadRound)
162159
{
163-
meta::ForEach<
164-
typename NewParticleDescription::ValueTypeSeq,
165-
LoadParticleAttributesFromOpenPMD<boost::mpl::_1>>
166-
loadAttributes;
167-
loadAttributes(
168-
params,
169-
mappedFrame,
170-
particleSpecies,
171-
particleLoadOffset,
172-
numParticlesCurrentBatch);
173-
174-
175-
pmacc::particles::operations::splitIntoListOfFrames(
176-
*speciesTmp,
177-
mappedFrame,
178-
numParticlesCurrentBatch,
179-
cellOffsetToTotalDomain,
180-
totalCellIdx_,
181-
*(params->cellDescription),
182-
picLog::INPUT_OUTPUT());
160+
auto particleLoadOffset = particleOffset + loadRound * maxChunkSize;
161+
auto numLeftParticles = numParticles - loadRound * maxChunkSize;
162+
163+
auto numParticlesCurrentBatch = std::min(numLeftParticles, maxChunkSize);
164+
165+
log<picLog::INPUT_OUTPUT>("openPMD: (begin) load species %1% round: %2%/%3%") % speciesName
166+
% (loadRound + 1) % numLoadIterations;
167+
if(numParticlesCurrentBatch != 0)
168+
{
169+
meta::ForEach<
170+
typename NewParticleDescription::ValueTypeSeq,
171+
LoadParticleAttributesFromOpenPMD<boost::mpl::_1>>
172+
loadAttributes;
173+
loadAttributes(
174+
params,
175+
mappedFrame,
176+
particleSpecies,
177+
particleLoadOffset,
178+
numParticlesCurrentBatch);
179+
180+
181+
pmacc::particles::operations::splitIntoListOfFrames(
182+
*speciesTmp,
183+
mappedFrame,
184+
numParticlesCurrentBatch,
185+
cellOffsetToTotalDomain,
186+
totalCellIdx_,
187+
*(params->cellDescription),
188+
picLog::INPUT_OUTPUT());
189+
}
190+
log<picLog::INPUT_OUTPUT>("openPMD: ( end ) load species %1% round: %2%/%3%") % speciesName
191+
% (loadRound + 1) % numLoadIterations;
183192
}
184-
log<picLog::INPUT_OUTPUT>("openPMD: ( end ) load species %1% round: %2%/%3%") % speciesName
185-
% (loadRound + 1) % numLoadIterations;
186193
}
187194
log<picLog::INPUT_OUTPUT>("openPMD: ( end ) load species: %1%") % speciesName;
188195
}
@@ -220,7 +227,9 @@ namespace picongpu
220227
*
221228
* @return index of the particle patch within the openPMD data
222229
*/
223-
HINLINE size_t getPatchIdx(ThreadParams* params, ::openPMD::ParticleSpecies particleSpecies)
230+
HINLINE std::pair<std::deque<size_t>, std::deque<size_t>> getPatchIdx(
231+
ThreadParams* params,
232+
::openPMD::ParticleSpecies particleSpecies)
224233
{
225234
std::string const name_lookup[] = {"x", "y", "z"};
226235

@@ -297,15 +306,7 @@ namespace picongpu
297306
<< fullMatches.size() << " full matches, " << partialMatches.size() << " partial matches, "
298307
<< noMatches << " unmatched." << std ::endl;
299308

300-
// If no patch fits the conditions, something went wrong before
301-
if(fullMatches.empty())
302-
{
303-
throw std::runtime_error(
304-
"Error while restarting: no particle patch matches the required offset and extent");
305-
}
306-
307-
// For now, ignore all the others
308-
return *fullMatches.begin();
309+
return std::make_pair(std::move(fullMatches), std::move(partialMatches));
309310
}
310311
};
311312

0 commit comments

Comments
 (0)