Skip to content

Commit 47a31c7

Browse files
authored
Merge pull request #1259 from parthenon-hpc-lab/jmm/packs-per-rank
Add default num partitions per rank
2 parents 80e337a + be5d8f2 commit 47a31c7

File tree

3 files changed

+103
-4
lines changed

3 files changed

+103
-4
lines changed

doc/sphinx/src/tasks.rst

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,68 @@ NOTE: Work remains to make the rest of
138138
Parthenon thread-safe, so it is currently required to use a ``ThreadPool``
139139
with one thread.
140140

141+
Mesh data and Packing over collections of meshblocks
142+
-----------------------------------------------------
143+
144+
The most common way to interact with collections of mesh blocks is the
145+
`MeshData` type, which collects ``MeshBlockData`` across a collection
146+
of blocks. It is through ``MeshData`` that sparse packs can be built,
147+
and multiple integrator stages, e.g., for a Runge-Kutte integrator,
148+
may be exposed.
149+
150+
When building a set of task lists over a collection of mesh blocks,
151+
you may choose the number of blocks per task list by hand, but
152+
defaults can be set at runtime in one of two ways. The run time
153+
parameter
154+
155+
.. code::
156+
157+
<parthenon/mesh>
158+
pack_size = 1
159+
160+
specifies the number of blocks per pack. For example, a value of 1
161+
indicates that each task list, even in synchronous regions, is over
162+
only 1 block. A value of -1 indicates it is all blocks per rank. You
163+
may choose -1 or any positive finite value.
164+
165+
Alternatively, you may set
166+
167+
.. code::
168+
169+
<parthenon/mesh>
170+
packs_per_rank = 1
171+
172+
which specifies the number of packs on a given rank. A value of 1
173+
indicates each task list contains all blocks on a given rank. A value
174+
of 2 indicates each list contains half, etc.
175+
176+
If both of these parameters are set, then ``pack_size`` takes
177+
precedent. If neither are set, the default is ``pack_size=-1``, which
178+
is equivalent to ``packs_per_rank=1``.
179+
180+
In a task list, you may access this information as, for example,
181+
182+
.. code::
183+
184+
const int num_partitions = pmesh->DefaultNumPartitions();
185+
186+
which will be equal to the pack size. Parthenon can automatically
187+
partition your list of meshblocks into smaller block lists and wrap it
188+
in a ``MeshData`` object with the ``GetOrAdd`` method. For example:
189+
190+
.. code::
191+
192+
TaskRegion &tr = tc.AddRegion(num_partitions);
193+
for (int i = 0; i < num_partitions; ++i) {
194+
auto &tl = tr[i];
195+
// mbase now points to the ith partition of the full block list
196+
// and is the equivalent of the ``MeshData`` object named "base"
197+
auto &mbase = pmesh->mesh_data.GetOrAdd("base", i);
198+
}
199+
200+
and ``GetOrAdd`` may be used on any "complete" ``MeshData`` object
201+
you've created on the entire block list.
202+
141203
TaskQualifier
142204
-------------
143205

src/mesh/mesh.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,41 @@ Mesh::Mesh(ParameterInput *pin, ApplicationInput *app_in, Packages_t &packages,
7979
: false),
8080
nbnew(), nbdel(), step_since_lb(), gflag(), packages(packages),
8181
resolved_packages(ResolvePackages(packages)),
82-
default_pack_size_(pin->GetOrAddInteger("parthenon/mesh", "pack_size", -1)),
8382
// private members:
8483
num_mesh_threads_(pin->GetOrAddInteger("parthenon/mesh", "num_threads", 1)),
8584
use_uniform_meshgen_fn_{true, true, true, true}, lb_flag_(true), lb_automatic_(),
8685
lb_manual_(), nslist(Globals::nranks), nblist(Globals::nranks),
8786
nref(Globals::nranks), nderef(Globals::nranks), rdisp(Globals::nranks),
8887
ddisp(Globals::nranks), bnref(Globals::nranks), bnderef(Globals::nranks),
8988
brdisp(Globals::nranks), bddisp(Globals::nranks) {
89+
// pack size
90+
bool pack_size_exists = pin->DoesParameterExist("parthenon/mesh", "pack_size");
91+
bool num_partitions_exists =
92+
pin->DoesParameterExist("parthenon/mesh", "packs_per_rank");
93+
// If both exists, the assumption is that packs_per_rank was added later on purpose (as
94+
// pack_size existed first) so the new value should take precedent.
95+
if (pack_size_exists && num_partitions_exists) {
96+
use_pack_size_ = false;
97+
default_num_packs_ = pin->GetInteger("parthenon/mesh", "packs_per_rank");
98+
auto pack_size = pin->GetInteger("parthenon/mesh", "pack_size");
99+
bool are_both_default = (default_num_packs_ == 1) && (pack_size == -1);
100+
if (!are_both_default && (Globals::my_rank == 0)) {
101+
PARTHENON_WARN("Both pack_size and packs_per_rank set to non default values! "
102+
"New packs_per_rank takes precedent.");
103+
}
104+
// Only one or none is set
105+
} else {
106+
if (pack_size_exists) {
107+
use_pack_size_ = true;
108+
default_pack_size_ = pin->GetInteger("parthenon/mesh", "pack_size");
109+
// use packs_per_rank (and set default value if not set)
110+
} else {
111+
use_pack_size_ = false;
112+
default_num_packs_ =
113+
std::max(1, pin->GetOrAddInteger("parthenon/mesh", "packs_per_rank", 1));
114+
}
115+
}
116+
90117
// Allow for user overrides to default Parthenon functions
91118
if (app_in->InitUserMeshData != nullptr) {
92119
InitUserMeshData = app_in->InitUserMeshData;

src/mesh/mesh.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,19 @@ class Mesh {
160160
void LoadBalancingAndAdaptiveMeshRefinement(ParameterInput *pin,
161161
ApplicationInput *app_in);
162162
int DefaultPackSize() {
163-
return default_pack_size_ < 1 ? std::max(static_cast<int>(block_list.size()), 1)
164-
: default_pack_size_;
163+
if (use_pack_size_) {
164+
return default_pack_size_ < 1 ? std::max(static_cast<int>(block_list.size()), 1)
165+
: default_pack_size_;
166+
} else {
167+
return partition::partition_impl::IntCeil(block_list.size(), default_num_packs_);
168+
}
165169
}
166170
int DefaultNumPartitions() {
167-
return partition::partition_impl::IntCeil(block_list.size(), DefaultPackSize());
171+
if (use_pack_size_) {
172+
return partition::partition_impl::IntCeil(block_list.size(), DefaultPackSize());
173+
} else {
174+
return std::min(default_num_packs_, block_list.size());
175+
}
168176
}
169177

170178
const std::vector<std::shared_ptr<BlockListPartition>> &
@@ -314,7 +322,9 @@ class Mesh {
314322
int lb_interval_;
315323

316324
// size of default MeshBlockPacks
325+
bool use_pack_size_;
317326
int default_pack_size_;
327+
std::size_t default_num_packs_;
318328

319329
int gmg_min_logical_level_ = 0;
320330

0 commit comments

Comments
 (0)