19 #include <deal.II/base/config.h> 20 #include <deal.II/base/array_view.h> 25 #if !defined(DEAL_II_WITH_MPI) && !defined(DEAL_II_WITH_PETSC) 30 typedef int MPI_Datatype;
32 # ifndef MPI_COMM_WORLD 33 # define MPI_COMM_WORLD 0 35 # ifndef MPI_COMM_SELF 36 # define MPI_COMM_SELF 0 49 DEAL_II_NAMESPACE_OPEN
53 template <
int rank,
int dim,
typename Number>
class Tensor;
109 std::vector<unsigned int>
111 const std::vector<unsigned int> &destinations);
155 #ifdef DEAL_II_WITH_MPI 157 const MPI_Group &group,
181 template <
typename T>
183 const MPI_Comm &mpi_communicator);
194 template <
typename T,
typename U>
195 void sum (
const T &values,
196 const MPI_Comm &mpi_communicator,
208 template <
typename T>
210 const MPI_Comm &mpi_communicator,
218 template <
int rank,
int dim,
typename Number>
221 const MPI_Comm &mpi_communicator);
228 template <
int rank,
int dim,
typename Number>
231 const MPI_Comm &mpi_communicator);
241 template <
typename Number>
244 const MPI_Comm &mpi_communicator,
266 template <
typename T>
268 const MPI_Comm &mpi_communicator);
279 template <
typename T,
typename U>
280 void max (
const T &values,
281 const MPI_Comm &mpi_communicator,
293 template <
typename T>
295 const MPI_Comm &mpi_communicator,
317 template <
typename T>
319 const MPI_Comm &mpi_communicator);
330 template <
typename T,
typename U>
331 void min (
const T &values,
332 const MPI_Comm &mpi_communicator,
344 template <
typename T>
346 const MPI_Comm &mpi_communicator,
426 const MPI_Comm &mpi_communicator);
559 template <
typename T>
560 std::map<unsigned int, T>
562 const std::map <unsigned int, T> &objects_to_send);
579 template <
typename T>
582 const T &object_to_send);
601 template <
typename T>
603 gather(
const MPI_Comm &comm,
604 const T &object_to_send,
605 const unsigned int root_process=0);
611 template <
typename T>
612 void all_reduce (
const MPI_Op &mpi_op,
614 const MPI_Comm &mpi_communicator,
619 template <
typename T,
unsigned int N>
620 void sum (
const T (&values)[N],
621 const MPI_Comm &mpi_communicator,
628 template <
typename T,
unsigned int N>
629 void max (
const T (&values)[N],
630 const MPI_Comm &mpi_communicator,
637 template <
typename T,
unsigned int N>
638 void min (
const T (&values)[N],
639 const MPI_Comm &mpi_communicator,
647 std::map<unsigned int, T>
649 const std::map<unsigned int, T> &objects_to_send)
651 #ifndef DEAL_II_WITH_MPI 653 Assert(objects_to_send.size() == 0,
ExcMessage(
"Cannot send to more than one processor."));
654 Assert(objects_to_send.find(0) != objects_to_send.end() || objects_to_send.size() == 0,
655 ExcMessage(
"Can only send to myself or to nobody."));
656 return objects_to_send;
659 std::vector<unsigned int> send_to(objects_to_send.size());
662 for (
const auto &m: objects_to_send)
663 send_to[i++] = m.first;
667 const auto receive_from =
671 std::vector<std::vector<char> > buffers_to_send(send_to.size());
672 std::vector<MPI_Request> buffer_send_requests(send_to.size());
675 for (
const auto &rank_obj : objects_to_send)
677 const auto &rank = rank_obj.first;
679 const int ierr = MPI_Isend(buffers_to_send[i].data(),
680 buffers_to_send[i].size(), MPI_CHAR,
681 rank, 21, comm, &buffer_send_requests[i]);
688 std::map<unsigned int, T> received_objects;
690 std::vector<char> buffer;
692 for (
unsigned int i = 0; i<receive_from.size(); ++i)
696 int ierr = MPI_Probe(MPI_ANY_SOURCE, 21, comm, &status);
701 ierr = MPI_Get_count(&status, MPI_CHAR, &len);
706 const unsigned int rank = status.MPI_SOURCE;
709 ierr = MPI_Recv(buffer.data(), len, MPI_CHAR,
710 rank, 21, comm, MPI_STATUS_IGNORE);
712 Assert(received_objects.find(rank) == received_objects.end(),
714 received_objects[rank] = Utilities::unpack<T>(buffer);
719 MPI_Waitall(send_to.size(), buffer_send_requests.data(),MPI_STATUSES_IGNORE);
721 return received_objects;
722 #endif // deal.II with MPI 726 std::vector<T>
all_gather(
const MPI_Comm &comm,
729 #ifndef DEAL_II_WITH_MPI 731 std::vector<T> v(1,
object);
734 const auto n_procs = ::Utilities::MPI::n_mpi_processes(comm);
738 int n_local_data = buffer.size();
741 std::vector<int> size_all_data(n_procs,0);
744 MPI_Allgather(&n_local_data, 1, MPI_INT,
745 &(size_all_data[0]), 1, MPI_INT,
750 std::vector<int> rdispls(n_procs);
752 for (
unsigned int i=1; i < n_procs; ++i)
753 rdispls[i] = rdispls[i-1] + size_all_data[i-1];
756 std::vector<char> received_unrolled_buffer(rdispls.back() + size_all_data.back());
758 MPI_Allgatherv(buffer.data(), n_local_data, MPI_CHAR,
759 received_unrolled_buffer.data(), size_all_data.data(),
760 rdispls.data(), MPI_CHAR, comm);
762 std::vector<T> received_objects(n_procs);
763 for (
unsigned int i= 0; i < n_procs; ++i)
765 std::vector<char> local_buffer(received_unrolled_buffer.begin()+rdispls[i],
766 received_unrolled_buffer.begin()+rdispls[i]+size_all_data[i]);
767 received_objects[i] = Utilities::unpack<T>(local_buffer);
770 return received_objects;
774 template <
typename T>
776 gather(
const MPI_Comm &comm,
777 const T &object_to_send,
778 const unsigned int root_process)
780 #ifndef DEAL_II_WITH_MPI 783 std::vector<T> v(1, object_to_send);
786 const auto n_procs = ::Utilities::MPI::n_mpi_processes(comm);
787 const auto my_rank = ::Utilities::MPI::this_mpi_process(comm);
792 int n_local_data = buffer.size();
796 std::vector<int> size_all_data;
797 if (my_rank==root_process)
798 size_all_data.resize(n_procs,0);
801 int ierr = MPI_Gather(&n_local_data, 1, MPI_INT,
802 size_all_data.data(), 1, MPI_INT,
808 std::vector<int> rdispls;
809 if (my_rank==root_process)
811 rdispls.resize(n_procs,0);
812 for (
unsigned int i=1; i<n_procs; ++i)
813 rdispls[i] = rdispls[i-1] + size_all_data[i-1];
816 std::vector<char> received_unrolled_buffer;
817 if (my_rank==root_process)
818 received_unrolled_buffer.resize(rdispls.back() + size_all_data.back());
820 ierr = MPI_Gatherv(buffer.data(), n_local_data, MPI_CHAR,
821 received_unrolled_buffer.data(), size_all_data.data(),
822 rdispls.data(), MPI_CHAR,
826 std::vector<T> received_objects;
828 if (my_rank==root_process)
830 received_objects.resize(n_procs);
832 for (
unsigned int i=0; i<n_procs; ++i)
834 const std::vector<char> local_buffer(received_unrolled_buffer.begin()+rdispls[i],
835 received_unrolled_buffer.begin()+rdispls[i]+size_all_data[i]);
836 received_objects[i] = Utilities::unpack<T>(local_buffer);
839 return received_objects;
848 DEAL_II_NAMESPACE_CLOSE
static const unsigned int invalid_unsigned_int
#define AssertDimension(dim1, dim2)
MPI_InitFinalize(int &argc, char **&argv, const unsigned int max_num_threads=numbers::invalid_unsigned_int)
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
static ::ExceptionBase & ExcMessage(std::string arg1)
T sum(const T &t, const MPI_Comm &mpi_communicator)
#define Assert(cond, exc)
std::vector< T > gather(const MPI_Comm &comm, const T &object_to_send, const unsigned int root_process=0)
int create_group(const MPI_Comm &comm, const MPI_Group &group, const int tag, MPI_Comm *new_comm)
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
#define AssertThrowMPI(error_code)
MPI_Comm duplicate_communicator(const MPI_Comm &mpi_communicator)
size_t pack(const T &object, std::vector< char > &dest_buffer)
T min(const T &t, const MPI_Comm &mpi_communicator)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
std::vector< T > all_gather(const MPI_Comm &comm, const T &object_to_send)
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
std::vector< unsigned int > compute_point_to_point_communication_pattern(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
std::map< unsigned int, T > some_to_some(const MPI_Comm &comm, const std::map< unsigned int, T > &objects_to_send)
T max(const T &t, const MPI_Comm &mpi_communicator)
static ::ExceptionBase & ExcInternalError()