4 #include <unordered_map>
40 std::vector<int>
cnt{};
46 std::partial_sum(
cnt.cbegin(),
cnt.cend(), displ.begin() + 1);
52 nrnmpi_int_alltoall(srccnt.data(), destcnt.data(), 1);
56 template <
typename T,
typename F>
58 F alltoall_function) {
63 s.cnt = std::vector<int>(
nhost);
65 for (
const auto& e:
data) {
66 int r = rendezvous_rank<T>(e);
71 s.data.resize(
s.displ[
nhost] + 1);
78 std::fill(
s.cnt.begin(),
s.cnt.end(), 0);
79 for (
const auto& e:
data) {
80 int rank = rendezvous_rank<T>(e);
81 s.data[
s.displ[rank] +
s.cnt[rank]] = e;
84 alltoall_function(
s, r);
88 template <
typename T,
typename F>
90 const std::vector<T>& want,
91 F alltoall_function) {
102 std::unordered_map<T, int> havekey2rank{};
104 auto [_, have_r] = rendezvous_rank_get<T>(have, alltoall_function);
106 havekey2rank.reserve(have_r.displ[
nhost] + 1);
107 for (
int r = 0; r <
nhost; ++r) {
108 for (
int i = 0;
i < have_r.cnt[r]; ++
i) {
109 T
key = have_r.data[have_r.displ[r] +
i];
110 if (havekey2rank.find(
key) != havekey2rank.end()) {
112 "internal error in have_to_want: key %lld owned by multiple ranks\n",
115 havekey2rank[
key] = r;
120 auto [want_s, want_r] = rendezvous_rank_get<T>(want, alltoall_function);
126 int n = want_r.displ[
nhost];
127 std::vector<int> want_r_ownerranks(
n);
128 for (
int r = 0; r <
nhost; ++r) {
129 for (
int i = 0;
i < want_r.cnt[r]; ++
i) {
130 int ix = want_r.displ[r] +
i;
131 T
key = want_r.data[ix];
132 auto search = havekey2rank.find(
key);
133 if (search == havekey2rank.end()) {
135 "internal error in have_to_want: key = %lld is wanted but does not exist\n",
138 want_r_ownerranks[ix] = search->second;
147 std::vector<int> want_s_ownerranks(want_s.displ[
nhost]);
149 nrnmpi_int_alltoallv_sparse(want_r_ownerranks.data(),
152 want_s_ownerranks.data(),
154 want_s.displ.data());
159 want_s_ownerranks.data(),
161 want_s.displ.data());
175 std::vector<T> old_want_s_data(
n);
176 std::swap(old_want_s_data, want_s.data);
178 for (
int i = 0;
i <
n; ++
i) {
179 int r = want_s_ownerranks[
i];
186 for (
int i = 0;
i <
n; ++
i) {
187 int r = want_s_ownerranks[
i];
188 T
key = old_want_s_data[
i];
189 want_s.data[want_s.displ[r] + want_s.cnt[r]] =
key;
195 new_want_r.displ =
cnt2displ(new_want_r.cnt);
196 new_want_r.data.resize(new_want_r.displ[
nhost]);
197 alltoall_function(want_s, new_want_r);
201 return {new_want_r, want_s};
static void nrnmpi_int_alltoallv(const int *s, const int *scnt, const int *sdispl, int *r, int *rcnt, int *rdispl)
void hoc_execerr_ext(const char *fmt,...)
printf style specification of hoc_execerror message.
static std::vector< int > srccnt2destcnt(std::vector< int > srccnt)
static std::tuple< Data< T >, Data< T > > rendezvous_rank_get(const std::vector< T > &data, F alltoall_function)
int rendezvous_rank(const T &key)
std::pair< Data< T >, Data< T > > have_to_want(const std::vector< T > &have, const std::vector< T > &want, F alltoall_function)
static std::vector< int > cnt2displ(const std::vector< int > &cnt)
int const size_t const size_t n
static double nhost(void *v)