16 #ifndef dealii_base_mpi_compute_index_owner_internal_h 17 #define dealii_base_mpi_compute_index_owner_internal_h 36 namespace ComputeIndexOwner
47 std::pair<types::global_dof_index, types::global_dof_index>,
55 const std::map<
unsigned int,
60 const std::pair<types::global_dof_index, types::global_dof_index>
64 , actually_owning_ranks(actually_owning_ranks)
65 , local_range(local_range)
66 , actually_owning_rank_list(actually_owning_rank_list)
73 virtual std::vector<unsigned int>
76 std::vector<unsigned int> targets;
77 for (
const auto &rank_pair :
buffers)
78 targets.push_back(rank_pair.first);
91 &send_buffer)
override 93 send_buffer = this->
buffers.at(other_rank);
102 const unsigned int other_rank,
105 std::vector<unsigned int> &request_buffer)
override 107 (void)request_buffer;
111 for (
auto interval : buffer_recv)
137 const std::map<
unsigned int,
139 types::global_dof_index>>>
144 const std::pair<types::global_dof_index, types::global_dof_index>
162 static const unsigned int range_minimum_grain_size = 4096;
191 std::pair<types::global_dof_index, types::global_dof_index>
230 #ifdef DEAL_II_WITH_MPI 234 std::map<
unsigned int,
236 types::global_dof_index>>>
239 std::fill(actually_owning_ranks.begin(),
240 actually_owning_ranks.end(),
252 std::pair<types::global_dof_index, types::global_dof_index>
253 index_range(*interval->begin(), interval->last() + 1);
254 const unsigned int owner_last =
255 dof_to_dict_rank(interval->last());
257 while (owner_first != owner_last)
259 Assert(index_range.first < index_range.second,
262 owner_first = dof_to_dict_rank(index_range.first);
266 types::global_dof_index next_index =
267 std::min(get_index_offset(owner_first + 1),
275 for (types::global_dof_index i = index_range.first + 1;
283 if (owner_first == my_rank)
285 std::fill(actually_owning_ranks.data() +
287 actually_owning_ranks.data() + next_index -
290 dic_local_received += next_index - index_range.first;
291 if (actually_owning_rank_list.empty())
292 actually_owning_rank_list.push_back(my_rank);
295 buffers[owner_first].emplace_back(index_range.first,
298 index_range.first = next_index;
302 n_dict_procs_in_owned_indices = buffers.size();
303 std::vector<MPI_Request> request;
307 owned_indices.
size())
315 request.reserve(n_dict_procs_in_owned_indices);
326 for (
const auto &rank_pair : buffers)
329 const int ierr = MPI_Isend(rank_pair.second.data(),
330 rank_pair.second.size() * 2,
340 while (this->local_size != dic_local_received)
345 MPI_Probe(MPI_ANY_SOURCE, mpi_tag, comm, &status);
350 ierr = MPI_Get_count(&status,
355 const auto other_rank = status.MPI_SOURCE;
356 actually_owning_rank_list.push_back(other_rank);
361 types::global_dof_index>>
362 buffer(number_amount / 2);
363 ierr = MPI_Recv(buffer.data(),
372 for (
auto interval : buffer)
375 for (types::global_dof_index i = interval.first;
389 std::fill(actually_owning_ranks.data() +
391 actually_owning_ranks.data() +
394 dic_local_received += interval.second - interval.first;
406 actually_owning_ranks,
408 actually_owning_rank_list);
411 std::pair<types::global_dof_index, types::global_dof_index>,
413 consensus_algo(temp, comm);
414 consensus_algo.run();
417 std::sort(actually_owning_rank_list.begin(),
418 actually_owning_rank_list.end());
420 for (
unsigned int i = 1; i < actually_owning_rank_list.size(); ++i)
421 Assert(actually_owning_rank_list[i] >
422 actually_owning_rank_list[i - 1],
426 if (request.size() > 0)
428 const int ierr = MPI_Waitall(request.size(),
430 MPI_STATUSES_IGNORE);
450 return (i / dofs_per_process) * stride_small_size;
461 static_cast<types::global_dof_index>(
462 (rank + stride_small_size - 1) /
474 const unsigned int guess = 0)
477 if (actually_owning_rank_list[guess] == rank_in_owned_indices)
482 actually_owning_rank_list.end(),
483 rank_in_owned_indices);
484 Assert(it != actually_owning_rank_list.end(),
487 return it - actually_owning_rank_list.begin();
499 #ifdef DEAL_II_WITH_MPI 503 size = owned_indices.
size();
507 dofs_per_process = (size + n_procs - 1) / n_procs;
508 if (dofs_per_process < range_minimum_grain_size)
510 dofs_per_process = range_minimum_grain_size;
511 stride_small_size = dofs_per_process * n_procs / size;
514 stride_small_size = 1;
516 local_range.second = get_index_offset(my_rank + 1);
520 actually_owning_ranks = {};
521 actually_owning_ranks.resize(local_size,
540 std::pair<types::global_dof_index, types::global_dof_index>,
549 const MPI_Comm &comm,
550 std::vector<unsigned int> &owning_ranks,
551 const bool track_index_requests =
false)
552 : owned_indices(owned_indices)
553 , indices_to_look_up(indices_to_look_up)
557 , track_index_requests(track_index_requests)
558 , owning_ranks(owning_ranks)
560 dict.reinit(owned_indices, comm);
561 requesters.resize(dict.actually_owning_rank_list.size());
614 std::vector<std::vector<
615 std::pair<
unsigned int,
616 std::vector<std::pair<unsigned int, unsigned int>>>>>
628 std::map<unsigned int, std::vector<types::global_dof_index>>
646 const unsigned int other_rank,
649 std::vector<unsigned int> &request_buffer)
override 651 unsigned int owner_index = 0;
652 for (
const auto &interval : buffer_recv)
653 for (
auto i = interval.first; i < interval.second; ++i)
655 const unsigned int actual_owner =
657 request_buffer.push_back(actual_owner);
659 if (track_index_requests)
660 append_index_origin(i, owner_index, other_rank);
668 virtual std::vector<unsigned int>
671 std::vector<unsigned int> targets;
675 unsigned int index = 0;
676 unsigned int owner_index = 0;
677 for (
auto i : indices_to_look_up)
680 if (other_rank == my_rank)
682 owning_ranks[index] =
684 if (track_index_requests)
685 append_index_origin(i, owner_index, my_rank);
687 else if (targets.empty() || targets.back() != other_rank)
688 targets.push_back(other_rank);
694 for (
auto i : targets)
696 recv_indices[i] = {};
697 indices_to_look_up_by_dict_rank[i] = {};
702 unsigned int index = 0;
703 for (
auto i : indices_to_look_up)
706 if (other_rank != my_rank)
708 recv_indices[other_rank].push_back(index);
709 indices_to_look_up_by_dict_rank[other_rank].push_back(i);
715 Assert(targets.size() == recv_indices.size() &&
716 targets.size() == indices_to_look_up_by_dict_rank.size(),
730 &send_buffer)
override 733 auto & indices_i = indices_to_look_up_by_dict_rank[other_rank];
735 is.
add_indices(indices_i.begin(), indices_i.end());
741 send_buffer.emplace_back(*interval->begin(),
742 interval->last() + 1);
751 const unsigned int other_rank,
752 std::vector<unsigned int> &recv_buffer)
override 754 recv_buffer.resize(recv_indices[other_rank].size());
763 const std::vector<unsigned int> &recv_buffer)
override 765 Assert(recv_indices[other_rank].size() == recv_buffer.size(),
768 for (
unsigned int j = 0; j < recv_indices[other_rank].size(); j++)
769 owning_ranks[recv_indices[other_rank][j]] = recv_buffer[j];
781 std::map<unsigned int, IndexSet>
784 Assert(track_index_requests,
785 ExcMessage(
"Must enable index range tracking in " 786 "constructor of ConsensusAlgorithmProcess"));
788 std::map<unsigned int, ::IndexSet> requested_indices;
790 #ifdef DEAL_II_WITH_MPI 802 std::vector<MPI_Request> send_requests;
803 send_requests.reserve(requesters.size());
813 std::vector<std::vector<unsigned int>> send_data(requesters.size());
814 for (
unsigned int i = 0; i < requesters.size(); ++i)
819 for (
const auto &j : requesters[i])
823 IndexSet &my_index_set = requested_indices[j.first];
825 for (
const auto &interval : j.second)
826 my_index_set.
add_range(index_offset + interval.first,
833 for (
const auto &j : requesters[i])
835 send_data[i].push_back(j.first);
836 send_data[i].push_back(j.second.size());
837 for (
const auto &interval : j.second)
839 send_data[i].push_back(interval.first);
840 send_data[i].push_back(interval.second);
845 MPI_Isend(send_data[i].data(),
851 &send_requests.back());
863 MPI_Probe(MPI_ANY_SOURCE, mpi_tag, comm, &status);
868 ierr = MPI_Get_count(&status, MPI_UNSIGNED, &number_amount);
873 std::vector<std::pair<unsigned int, unsigned int>> buffer(
875 ierr = MPI_Recv(buffer.data(),
888 unsigned int offset = 0;
889 while (offset < buffer.size())
895 for (
unsigned int i = offset + 1;
896 i < offset + buffer[offset].second + 1;
898 my_index_set.
add_range(index_offset + buffer[i].first,
899 index_offset + buffer[i].second);
905 requested_indices[buffer[offset].first];
906 if (index_set.
size() == 0)
910 offset += buffer[offset].second + 1;
915 if (send_requests.size() > 0)
917 const auto ierr = MPI_Waitall(send_requests.size(),
918 send_requests.data(),
919 MPI_STATUSES_IGNORE);
925 for (
const auto &it : requested_indices)
931 "The indices requested from the current " 932 "MPI rank should be locally owned here!"));
936 #endif // DEAL_II_WITH_MPI 938 return requested_indices;
957 unsigned int & owner_index,
958 const unsigned int rank_of_request)
964 const unsigned int rank_of_owner =
968 if (requesters[owner_index].empty() ||
969 requesters[owner_index].back().
first != rank_of_request)
970 requesters[owner_index].emplace_back(
972 std::vector<std::pair<unsigned int, unsigned int>>());
973 if (requesters[owner_index].back().
second.empty() ||
974 requesters[owner_index].back().second.back().second !=
976 requesters[owner_index].back().second.emplace_back(
980 ++requesters[owner_index].back().second.back().second;
Iterator lower_bound(Iterator first, Iterator last, const T &val)
void append_index_origin(const types::global_dof_index index, unsigned int &owner_index, const unsigned int rank_of_request)
const IndexSet & owned_indices
static const unsigned int invalid_unsigned_int
#define AssertDimension(dim1, dim2)
const types::subdomain_id invalid_subdomain_id
types::global_dof_index dofs_per_process
types::global_dof_index get_index_offset(const unsigned int rank)
unsigned int dof_to_dict_rank(const types::global_dof_index i)
const IndexSet & indices_to_look_up
#define AssertIndexRange(index, range)
void add_indices(const ForwardIterator &begin, const ForwardIterator &end)
types::global_dof_index local_size
#define DEAL_II_DOF_INDEX_MPI_TYPE
const unsigned int my_rank
std::map< unsigned int, std::vector< unsigned int > > recv_indices
ConsensusAlgorithmsPayload(const IndexSet &owned_indices, const IndexSet &indices_to_look_up, const MPI_Comm &comm, std::vector< unsigned int > &owning_ranks, const bool track_index_requests=false)
std::vector< unsigned int > actually_owning_rank_list
virtual std::vector< unsigned int > compute_targets() override
virtual void create_request(const unsigned int other_rank, std::vector< std::pair< types::global_dof_index, types::global_dof_index >> &send_buffer) override
virtual void create_request(const unsigned int other_rank, std::vector< std::pair< types::global_dof_index, types::global_dof_index >> &send_buffer) override
static ::ExceptionBase & ExcMessage(std::string arg1)
T sum(const T &t, const MPI_Comm &mpi_communicator)
void subtract_set(const IndexSet &other)
std::map< unsigned int, IndexSet > get_requesters()
std::vector< unsigned int > actually_owning_ranks
#define Assert(cond, exc)
const std::map< unsigned int, std::vector< std::pair< types::global_dof_index, types::global_dof_index > > > & buffers
const std::pair< types::global_dof_index, types::global_dof_index > & local_range
virtual void answer_request(const unsigned int other_rank, const std::vector< std::pair< types::global_dof_index, types::global_dof_index >> &buffer_recv, std::vector< unsigned int > &request_buffer) override
const unsigned int n_procs
#define DEAL_II_NAMESPACE_CLOSE
unsigned int n_dict_procs_in_owned_indices
unsigned int get_owning_rank_index(const unsigned int rank_in_owned_indices, const unsigned int guess=0)
std::vector< unsigned int > & actually_owning_ranks
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
void add_range(const size_type begin, const size_type end)
void set_size(const size_type size)
unsigned int global_dof_index
virtual void prepare_buffer_for_answer(const unsigned int other_rank, std::vector< unsigned int > &recv_buffer) override
virtual void answer_request(const unsigned int other_rank, const std::vector< std::pair< types::global_dof_index, types::global_dof_index >> &buffer_recv, std::vector< unsigned int > &request_buffer) override
types::global_dof_index size
std::map< unsigned int, std::vector< types::global_dof_index > > indices_to_look_up_by_dict_rank
std::pair< types::global_dof_index, types::global_dof_index > local_range
IntervalIterator begin_intervals() const
#define AssertThrowMPI(error_code)
const bool track_index_requests
#define DEAL_II_NAMESPACE_OPEN
T min(const T &t, const MPI_Comm &mpi_communicator)
IntervalIterator end_intervals() const
std::vector< std::vector< std::pair< unsigned int, std::vector< std::pair< unsigned int, unsigned int > > > > > requesters
void reinit(const IndexSet &owned_indices, const MPI_Comm &comm)
void partition(const IndexSet &owned_indices, const MPI_Comm &comm)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
static ::ExceptionBase & ExcNotImplemented()
std::vector< unsigned int > & actually_owning_rank_list
virtual std::vector< unsigned int > compute_targets() override
std::vector< unsigned int > & owning_ranks
virtual void read_answer(const unsigned int other_rank, const std::vector< unsigned int > &recv_buffer) override
DictionaryPayLoad(const std::map< unsigned int, std::vector< std::pair< types::global_dof_index, types::global_dof_index >>> &buffers, std::vector< unsigned int > &actually_owning_ranks, const std::pair< types::global_dof_index, types::global_dof_index > &local_range, std::vector< unsigned int > &actually_owning_rank_list)
size_type n_elements() const
unsigned int stride_small_size
static ::ExceptionBase & ExcInternalError()