Skip to content

Commit adbdfaa

Browse files
committed
Add Blocks distribution strategy
1 parent 82e771e commit adbdfaa

File tree

6 files changed

+85
-22
lines changed

6 files changed

+85
-22
lines changed

include/openPMD/ChunkInfo.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,22 @@ namespace chunk_assignment
235235
virtual std::unique_ptr<Strategy> clone() const override;
236236
};
237237

238+
struct Blocks : Strategy
239+
{
240+
private:
241+
unsigned int mpi_size, mpi_rank;
242+
243+
public:
244+
Blocks(unsigned int mpi_rank, unsigned int mpi_size);
245+
246+
Assignment assign(
247+
PartialAssignment,
248+
RankMeta const &in,
249+
RankMeta const &out) override;
250+
251+
[[nodiscard]] std::unique_ptr<Strategy> clone() const override;
252+
};
253+
238254
/**
239255
* @brief Strategy that assigns chunks to be read by processes within
240256
* the same host that produced the chunk.

include/openPMD/benchmark/mpi/OneDimensionalBlockSlicer.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class OneDimensionalBlockSlicer : public BlockSlicer
3333

3434
explicit OneDimensionalBlockSlicer(Extent::value_type dim = 0);
3535

36+
static std::pair<size_t, size_t>
37+
n_th_block_inside(size_t length, size_t rank, size_t size);
38+
3639
std::pair<Offset, Extent>
3740
sliceBlock(Extent &totalExtent, int size, int rank) override;
3841

src/ChunkInfo.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,15 @@
2222
#include "openPMD/ChunkInfo_internal.hpp"
2323

2424
#include "openPMD/auxiliary/Mpi.hpp"
25+
#include "openPMD/benchmark/mpi/OneDimensionalBlockSlicer.hpp"
2526

2627
#include <algorithm> // std::sort
2728
#include <deque>
2829
#include <iostream>
2930
#include <iterator>
3031
#include <list>
3132
#include <map>
33+
#include <memory>
3234
#include <optional>
3335
#include <set>
3436
#include <utility>
@@ -335,6 +337,30 @@ namespace chunk_assignment
335337
return std::unique_ptr<Strategy>(new RoundRobinOfSourceRanks);
336338
}
337339

340+
Blocks::Blocks(unsigned int mpi_rank_in, unsigned int mpi_size_in)
341+
: mpi_size(mpi_size_in), mpi_rank(mpi_rank_in)
342+
{}
343+
344+
Assignment
345+
Blocks::assign(PartialAssignment pa, RankMeta const &, RankMeta const &)
346+
{
347+
auto [notAssigned, res] = std::move(pa);
348+
auto [myChunksFrom, myChunksTo] =
349+
OneDimensionalBlockSlicer::n_th_block_inside(
350+
notAssigned.size(), mpi_rank, mpi_size);
351+
std::transform(
352+
notAssigned.begin() + myChunksFrom,
353+
notAssigned.begin() + (myChunksFrom + myChunksTo),
354+
std::back_inserter(res[mpi_rank]),
355+
[](WrittenChunkInfo &chunk) { return std::move(chunk); });
356+
return res;
357+
}
358+
359+
std::unique_ptr<Strategy> Blocks::clone() const
360+
{
361+
return std::unique_ptr<Strategy>(new Blocks(*this));
362+
}
363+
338364
ByHostname::ByHostname(std::unique_ptr<Strategy> withinNode)
339365
: m_withinNode(std::move(withinNode))
340366
{}

src/benchmark/mpi/OneDimensionalBlockSlicer.cpp

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,29 +29,23 @@ OneDimensionalBlockSlicer::OneDimensionalBlockSlicer(Extent::value_type dim)
2929
: m_dim{dim}
3030
{}
3131

32-
std::pair<Offset, Extent>
33-
OneDimensionalBlockSlicer::sliceBlock(Extent &totalExtent, int size, int rank)
32+
std::pair<size_t, size_t> OneDimensionalBlockSlicer::n_th_block_inside(
33+
size_t length, size_t rank, size_t size)
3434
{
35-
Offset offs(totalExtent.size(), 0);
36-
3735
if (rank >= size)
3836
{
39-
Extent extent(totalExtent.size(), 0);
40-
return std::make_pair(std::move(offs), std::move(extent));
37+
return {length, 0};
4138
}
4239

43-
auto dim = this->m_dim;
44-
4540
// for more equal balancing, we want the start index
4641
// at the upper gaussian bracket of (N/n*rank)
4742
// where N the size of the dataset in dimension dim
4843
// and n the MPI size
4944
// for avoiding integer overflow, this is the same as:
5045
// (N div n)*rank + round((N%n)/n*rank)
51-
auto f = [&totalExtent, size, dim](int threadRank) {
52-
auto N = totalExtent[dim];
53-
auto res = (N / size) * threadRank;
54-
auto padDivident = (N % size) * threadRank;
46+
auto f = [length, size](size_t rank_lambda) {
47+
auto res = (length / size) * rank_lambda;
48+
auto padDivident = (length % size) * rank_lambda;
5549
auto pad = padDivident / size;
5650
if (pad * size < padDivident)
5751
{
@@ -60,17 +54,31 @@ OneDimensionalBlockSlicer::sliceBlock(Extent &totalExtent, int size, int rank)
6054
return res + pad;
6155
};
6256

63-
offs[dim] = f(rank);
57+
size_t offset = f(rank);
58+
size_t extent = [&]() {
59+
if (rank >= size - 1)
60+
{
61+
return length - offset;
62+
}
63+
else
64+
{
65+
return f(rank + 1) - offset;
66+
}
67+
}();
68+
return {offset, extent};
69+
}
70+
71+
std::pair<Offset, Extent>
72+
OneDimensionalBlockSlicer::sliceBlock(Extent &totalExtent, int size, int rank)
73+
{
74+
Offset localOffset(totalExtent.size(), 0);
6475
Extent localExtent{totalExtent};
65-
if (rank >= size - 1)
66-
{
67-
localExtent[dim] -= offs[dim];
68-
}
69-
else
70-
{
71-
localExtent[dim] = f(rank + 1) - offs[dim];
72-
}
73-
return std::make_pair(std::move(offs), std::move(localExtent));
76+
77+
auto [offset_dim, extent_dim] =
78+
n_th_block_inside(totalExtent.at(this->m_dim), rank, size);
79+
localOffset[m_dim] = offset_dim;
80+
localExtent[m_dim] = extent_dim;
81+
return std::make_pair(std::move(localOffset), std::move(localExtent));
7482
}
7583

7684
std::unique_ptr<BlockSlicer> OneDimensionalBlockSlicer::clone() const

src/binding/python/ChunkInfo.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,11 @@ void init_Chunk(py::module &m)
300300
py::class_<RoundRobin, Strategy>(m, "RoundRobin").def(py::init<>());
301301
py::class_<RoundRobinOfSourceRanks, Strategy>(m, "RoundRobinOfSourceRanks")
302302
.def(py::init<>());
303+
py::class_<Blocks, Strategy>(m, "Blocks")
304+
.def(
305+
py::init<unsigned int, unsigned int>(),
306+
py::arg("mpi_rank"),
307+
py::arg("mpi_size"));
303308

304309
py::class_<ByHostname, PartialStrategy>(m, "ByHostname")
305310
.def(

test/ParallelIOTest.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2455,6 +2455,11 @@ void adios2_chunk_distribution()
24552455
chunkTable, rankMetaIn, readingRanksHostnames);
24562456
printAssignment(
24572457
"CUBOID SLICE", cuboidSliceAssignment, readingRanksHostnames);
2458+
2459+
Blocks blocksStrategy(mpi_rank, mpi_size);
2460+
auto blocksAssignment = blocksStrategy.assign(
2461+
chunkTable, rankMetaIn, readingRanksHostnames);
2462+
printAssignment("BLOCKS", blocksAssignment, readingRanksHostnames);
24582463
}
24592464
}
24602465

0 commit comments

Comments
 (0)