core
1.5.0
Shared MPI block decomposition, asynchronous ghost-layer exchange, SDF geometry, load balancing (header-only C++20)
Loading...
Searching...
No Matches
gather_by_global_id.hpp
Go to the documentation of this file.
1
// core — the id-keyed replicated gather (amr/docs/amr_mg_core_boundary.md §3.1, §4): every rank
2
// contributes (global id, value) pairs and every rank receives the whole global vector, indexed by
3
// id. The one-liner that flow's GraphAMG bottom, amr's ReplicatedTailStage and voro's coming
4
// GraphAMG bottom each wrote inline. Pure copies, bitwise.
5
#ifndef PECLET_CORE_DECOMP_GATHER_BY_GLOBAL_ID_HPP
6
#define PECLET_CORE_DECOMP_GATHER_BY_GLOBAL_ID_HPP
7
8
#include <climits>
9
#include <cstddef>
10
#include <stdexcept>
11
#include <type_traits>
12
#include <vector>
13
14
#include "
peclet/core/common/mpi.hpp
"
15
16
namespace
peclet::core::decomp
{
17
30
template
<
class
T>
31
void
gatherByGlobalId
(
const
std::vector<long long>&
ids
,
const
std::vector<T>&
vals
,
32
long
long
nGlobal
, std::vector<T>&
out
,
MPI_Comm
comm) {
33
static_assert
(std::is_trivially_copyable_v<T>,
"gatherByGlobalId moves T as raw bytes"
);
34
if
(
ids
.size() !=
vals
.size())
35
throw
std::invalid_argument(
"gatherByGlobalId: ids and vals differ in length"
);
36
if
(
ids
.size() >
static_cast<
std::size_t
>
(
INT_MAX
/
sizeof
(
T
)) ||
37
ids
.size() >
static_cast<
std::size_t
>
(
INT_MAX
/
sizeof
(
long
long
)))
38
throw
std::overflow_error(
"gatherByGlobalId: a rank's contribution exceeds INT_MAX bytes"
);
39
int
size = 1;
40
MPI_Comm_size
(comm, &size);
41
const
int
n =
static_cast<
int
>
(
ids
.size());
42
std::vector<int>
counts
(
static_cast<
std::size_t
>
(size)),
displs
(
static_cast<
std::size_t
>
(size));
43
MPI_Allgather
(&n, 1,
MPI_INT
,
counts
.data(), 1,
MPI_INT
, comm);
44
long
long
tot
= 0;
45
for
(
int
r = 0; r < size; ++r) {
46
displs
[
static_cast<
std::size_t
>
(r)] =
static_cast<
int
>
(
tot
);
47
tot
+=
counts
[
static_cast<
std::size_t
>
(r)];
48
if
(
tot
>
INT_MAX
)
49
throw
std::overflow_error(
"gatherByGlobalId: the global vector exceeds INT_MAX entries"
);
50
}
51
if
(
tot
!=
nGlobal
)
52
throw
std::invalid_argument(
"gatherByGlobalId: the ids do not cover [0, nGlobal) once each"
);
53
std::vector<long long>
idAll
(
static_cast<
std::size_t
>
(
tot
));
54
MPI_Allgatherv
(
ids
.data(), n,
MPI_LONG_LONG
,
idAll
.data(),
counts
.data(),
displs
.data(),
55
MPI_LONG_LONG
, comm);
56
std::vector<T>
vAll
(
static_cast<
std::size_t
>
(
tot
));
57
std::vector<int>
bc
(
counts
.size()),
bd
(
displs
.size());
58
for
(std::size_t r = 0; r <
counts
.size(); ++r) {
59
if
(
static_cast<
std::size_t
>
(
counts
[r]) >
static_cast<
std::size_t
>
(
INT_MAX
) /
sizeof
(
T
) ||
60
static_cast<
std::size_t
>
(
displs
[r]) >
static_cast<
std::size_t
>
(
INT_MAX
) /
sizeof
(
T
))
61
throw
std::overflow_error(
"gatherByGlobalId: the global vector exceeds INT_MAX bytes"
);
62
bc
[r] =
counts
[r] *
static_cast<
int
>
(
sizeof
(
T
));
63
bd
[r] =
displs
[r] *
static_cast<
int
>
(
sizeof
(
T
));
64
}
65
MPI_Allgatherv
(
vals
.data(), n *
static_cast<
int
>
(
sizeof
(
T
)),
MPI_BYTE
,
vAll
.data(),
bc
.data(),
66
bd
.data(),
MPI_BYTE
, comm);
67
out
.assign(
static_cast<
std::size_t
>
(
nGlobal
),
T
{});
68
std::vector<char>
seen
(
static_cast<
std::size_t
>
(
nGlobal
), 0);
69
for
(std::size_t
k
= 0;
k
<
idAll
.size(); ++
k
) {
70
const
long
long
id
=
idAll
[
k
];
71
if
(
id < 0 || id >
=
nGlobal
||
seen
[
static_cast<
std::size_t
>
(
id
)])
72
throw
std::invalid_argument(
"gatherByGlobalId: the ids do not cover [0, nGlobal) once each"
);
73
seen
[
static_cast<
std::size_t
>
(
id
)] = 1;
74
out
[
static_cast<
std::size_t
>
(
id
)] =
vAll
[
k
];
75
}
76
}
77
78
}
// namespace peclet::core::decomp
79
80
#endif
// PECLET_CORE_DECOMP_GATHER_BY_GLOBAL_ID_HPP
mpi.hpp
MPI_Comm_size
int MPI_Comm_size(MPI_Comm, int *s)
Definition
mpi_stub.hpp:70
MPI_Comm
int MPI_Comm
Definition
mpi_stub.hpp:17
MPI_INT
#define MPI_INT
Definition
mpi_stub.hpp:39
MPI_BYTE
#define MPI_BYTE
Definition
mpi_stub.hpp:38
peclet::core::decomp
Definition
block_decomposer.hpp:19
peclet::core::decomp::gatherByGlobalId
void gatherByGlobalId(const std::vector< long long > &ids, const std::vector< T > &vals, long long nGlobal, std::vector< T > &out, MPI_Comm comm)
ids[i] is the global id of vals[i] on this rank.
Definition
gather_by_global_id.hpp:31
peclet::core::View
Kokkos::View< T *, MemSpace > View
1D device array.
Definition
view.hpp:26
include
peclet
core
decomp
gather_by_global_id.hpp
Generated by
1.9.8