Reference documentation for deal.II version 8.4.2
mpi.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2011 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii__mpi_h
17 #define dealii__mpi_h
18 
19 #include <deal.II/base/config.h>
20 #include <vector>
21 
22 #if !defined(DEAL_II_WITH_MPI) && !defined(DEAL_II_WITH_PETSC)
23 // without MPI, we would still like to use
24 // some constructs with MPI data
25 // types. Therefore, create some dummies
26 typedef int MPI_Comm;
27 const int MPI_COMM_SELF = 0;
28 typedef int MPI_Datatype;
29 typedef int MPI_Op;
30 namespace MPI
31 {
32  static const unsigned int UNSIGNED = 0;
33  static const unsigned int LONG_DOUBLE = 0;
34  static const unsigned int LONG_DOUBLE_COMPLEX = 0;
35  static const unsigned int MAX = 0;
36  static const unsigned int MIN = 0;
37  static const unsigned int SUM = 0;
38 }
39 static const int MPI_MIN = 0;
40 static const int MPI_MAX = 0;
41 static const int MPI_SUM = 0;
42 #endif
43 
44 DEAL_II_NAMESPACE_OPEN
45 
46 
47 //Forward type declarations to allow MPI sums over tensorial types
48 template <int rank, int dim, typename Number> class Tensor;
49 template <int rank, int dim, typename Number> class SymmetricTensor;
50 
51 //Forward type declaration to allow MPI sums over Vector<number> type
52 template <typename Number> class Vector;
53 
54 
55 namespace Utilities
56 {
64  namespace MPI
65  {
71  unsigned int n_mpi_processes (const MPI_Comm &mpi_communicator);
72 
81  unsigned int this_mpi_process (const MPI_Comm &mpi_communicator);
82 
104  std::vector<unsigned int>
105  compute_point_to_point_communication_pattern (const MPI_Comm &mpi_comm,
106  const std::vector<unsigned int> &destinations);
107 
121  MPI_Comm duplicate_communicator (const MPI_Comm &mpi_communicator);
122 
142  template <typename T>
143  T sum (const T &t,
144  const MPI_Comm &mpi_communicator);
145 
154  template <typename T, unsigned int N>
155  inline
156  void sum (const T (&values)[N],
157  const MPI_Comm &mpi_communicator,
158  T (&sums)[N]);
159 
167  template <typename T>
168  inline
169  void sum (const std::vector<T> &values,
170  const MPI_Comm &mpi_communicator,
171  std::vector<T> &sums);
172 
179  template <typename T>
180  inline
181  void sum (const Vector<T> &values,
182  const MPI_Comm &mpi_communicator,
183  Vector<T> &sums);
184 
185 
191  template <int rank, int dim, typename Number>
192  inline
194  sum (const SymmetricTensor<rank,dim,Number> &local,
195  const MPI_Comm &mpi_communicator);
196 
202  template <int rank, int dim, typename Number>
203  inline
205  sum (const Tensor<rank,dim,Number> &local,
206  const MPI_Comm &mpi_communicator);
207 
227  template <typename T>
228  T max (const T &t,
229  const MPI_Comm &mpi_communicator);
230 
239  template <typename T, unsigned int N>
240  inline
241  void max (const T (&values)[N],
242  const MPI_Comm &mpi_communicator,
243  T (&maxima)[N]);
244 
253  template <typename T>
254  inline
255  void max (const std::vector<T> &values,
256  const MPI_Comm &mpi_communicator,
257  std::vector<T> &maxima);
258 
278  template <typename T>
279  T min (const T &t,
280  const MPI_Comm &mpi_communicator);
281 
290  template <typename T, unsigned int N>
291  inline
292  void min (const T (&values)[N],
293  const MPI_Comm &mpi_communicator,
294  T (&minima)[N]);
295 
304  template <typename T>
305  inline
306  void min (const std::vector<T> &values,
307  const MPI_Comm &mpi_communicator,
308  std::vector<T> &minima);
309 
310 
314  struct MinMaxAvg
315  {
316  // Note: We assume a POD property of this struct in the MPI calls in
317  // min_max_avg
318  double sum;
319  double min;
320  double max;
321  unsigned int min_index;
322  unsigned int max_index;
323  double avg;
324  };
325 
340  MinMaxAvg
341  min_max_avg (const double my_value,
342  const MPI_Comm &mpi_communicator);
343 
344 
345 
369  {
370  public:
416  MPI_InitFinalize (int &argc,
417  char ** &argv,
418  const unsigned int max_num_threads = numbers::invalid_unsigned_int);
419 
424  ~MPI_InitFinalize();
425  };
426 
438  bool job_supports_mpi ();
439 
440  namespace internal
441  {
442 #ifdef DEAL_II_WITH_MPI
443 
446  inline MPI_Datatype mpi_type_id (const int *)
447  {
448  return MPI_INT;
449  }
450 
451 
452  inline MPI_Datatype mpi_type_id (const long int *)
453  {
454  return MPI_LONG;
455  }
456 
457 
458  inline MPI_Datatype mpi_type_id (const unsigned int *)
459  {
460  return MPI_UNSIGNED;
461  }
462 
463 
464  inline MPI_Datatype mpi_type_id (const unsigned long int *)
465  {
466  return MPI_UNSIGNED_LONG;
467  }
468 
469 
470  inline MPI_Datatype mpi_type_id (const unsigned long long int *)
471  {
472  return MPI_UNSIGNED_LONG_LONG;
473  }
474 
475 
476  inline MPI_Datatype mpi_type_id (const float *)
477  {
478  return MPI_FLOAT;
479  }
480 
481 
482  inline MPI_Datatype mpi_type_id (const double *)
483  {
484  return MPI_DOUBLE;
485  }
486 
487 
488  inline MPI_Datatype mpi_type_id (const long double *)
489  {
490  return MPI_LONG_DOUBLE;
491  }
492 #endif
493 
494  template <typename T>
495  inline
496  T all_reduce (const MPI_Op &mpi_op,
497  const T &t,
498  const MPI_Comm &mpi_communicator)
499  {
500 #ifdef DEAL_II_WITH_MPI
501  if (job_supports_mpi())
502  {
503  T output;
504  MPI_Allreduce (const_cast<void *>(static_cast<const void *>(&t)),
505  &output, 1, internal::mpi_type_id(&t), mpi_op,
506  mpi_communicator);
507  return output;
508  }
509  else
510 #endif
511  {
512  (void)mpi_op;
513  (void)mpi_communicator;
514  return t;
515  }
516  }
517 
518  template <typename T, unsigned int N>
519  inline
520  void all_reduce (const MPI_Op &mpi_op,
521  const T (&values)[N],
522  const MPI_Comm &mpi_communicator,
523  T (&output)[N])
524  {
525 #ifdef DEAL_II_WITH_MPI
526  if (job_supports_mpi())
527  {
528  MPI_Allreduce ((&values[0] != &output[0]
529  ?
530  const_cast<void *>(static_cast<const void *>(&values[0]))
531  :
532  MPI_IN_PLACE),
533  &output[0], N, internal::mpi_type_id(values), mpi_op,
534  mpi_communicator);
535  }
536  else
537 #endif
538  {
539  (void)mpi_op;
540  (void)mpi_communicator;
541  for (unsigned int i=0; i<N; ++i)
542  output[i] = values[i];
543  }
544  }
545 
546  template <typename T>
547  inline
548  void all_reduce (const MPI_Op &mpi_op,
549  const std::vector<T> &values,
550  const MPI_Comm &mpi_communicator,
551  std::vector<T> &output)
552  {
553 #ifdef DEAL_II_WITH_MPI
554  if (job_supports_mpi())
555  {
556  output.resize (values.size());
557  MPI_Allreduce ((&values[0] != &output[0]
558  ?
559  const_cast<void *>(static_cast<const void *>(&values[0]))
560  :
561  MPI_IN_PLACE),
562  &output[0], values.size(), internal::mpi_type_id((T *)0), mpi_op,
563  mpi_communicator);
564  }
565  else
566 #endif
567  {
568  (void)mpi_op;
569  (void)mpi_communicator;
570  output = values;
571  }
572  }
573 
574  template <typename T>
575  inline
576  void all_reduce (const MPI_Op &mpi_op,
577  const Vector<T> &values,
578  const MPI_Comm &mpi_communicator,
579  Vector<T> &output)
580  {
581 #ifdef DEAL_II_WITH_MPI
582  if (job_supports_mpi())
583  {
584  if (values.begin() != output.begin())
585  output.reinit (values.size());
586 
587  MPI_Allreduce ((values.begin() != output.begin()
588  ?
589  const_cast<void *>(static_cast<const void *>(values.begin()))
590  :
591  MPI_IN_PLACE),
592  output.begin(), values.size(), internal::mpi_type_id((T *)0), mpi_op,
593  mpi_communicator);
594  }
595  else
596 #endif
597  {
598  (void)mpi_op;
599  (void)mpi_communicator;
600  output = values;
601  }
602  }
603 
604 
605 
606  }
607 
608 
609  template <typename T>
610  inline
611  T sum (const T &t,
612  const MPI_Comm &mpi_communicator)
613  {
614  return internal::all_reduce(MPI_SUM, t, mpi_communicator);
615  }
616 
617 
618  template <typename T, unsigned int N>
619  inline
620  void sum (const T (&values)[N],
621  const MPI_Comm &mpi_communicator,
622  T (&sums)[N])
623  {
624  internal::all_reduce(MPI_SUM, values, mpi_communicator, sums);
625  }
626 
627 
628  template <typename T>
629  inline
630  void sum (const std::vector<T> &values,
631  const MPI_Comm &mpi_communicator,
632  std::vector<T> &sums)
633  {
634  internal::all_reduce(MPI_SUM, values, mpi_communicator, sums);
635  }
636 
637  template <typename T>
638  inline
639  void sum (const Vector<T> &values,
640  const MPI_Comm &mpi_communicator,
641  Vector<T> &sums)
642  {
643  internal::all_reduce(MPI_SUM, values, mpi_communicator, sums);
644  }
645 
646 
647  template <int rank, int dim, typename Number>
648  inline
650  sum (const Tensor<rank,dim,Number> &local,
651  const MPI_Comm &mpi_communicator)
652  {
653  const unsigned int n_entries = Tensor<rank,dim,Number>::n_independent_components;
655 
656  for (unsigned int i=0; i< n_entries; ++i)
657  entries[i] = local[ local.unrolled_to_component_indices(i) ];
658 
659  Number global_entries[ Tensor<rank,dim,Number>::n_independent_components ];
660  ::Utilities::MPI::sum( entries, mpi_communicator, global_entries );
661 
663  for (unsigned int i=0; i< n_entries; ++i)
664  global[ global.unrolled_to_component_indices(i) ] = global_entries[i];
665 
666  return global;
667  }
668 
669  template <int rank, int dim, typename Number>
670  inline
673  const MPI_Comm &mpi_communicator)
674  {
675  const unsigned int n_entries = SymmetricTensor<rank,dim,Number>::n_independent_components;
677 
678  for (unsigned int i=0; i< n_entries; ++i)
679  entries[i] = local[ local.unrolled_to_component_indices(i) ];
680 
682  ::Utilities::MPI::sum( entries, mpi_communicator, global_entries );
683 
685  for (unsigned int i=0; i< n_entries; ++i)
686  global[ global.unrolled_to_component_indices(i) ] = global_entries[i];
687 
688  return global;
689  }
690 
691  template <typename T>
692  inline
693  T max (const T &t,
694  const MPI_Comm &mpi_communicator)
695  {
696  return internal::all_reduce(MPI_MAX, t, mpi_communicator);
697  }
698 
699 
700  template <typename T, unsigned int N>
701  inline
702  void max (const T (&values)[N],
703  const MPI_Comm &mpi_communicator,
704  T (&maxima)[N])
705  {
706  internal::all_reduce(MPI_MAX, values, mpi_communicator, maxima);
707  }
708 
709 
710  template <typename T>
711  inline
712  void max (const std::vector<T> &values,
713  const MPI_Comm &mpi_communicator,
714  std::vector<T> &maxima)
715  {
716  internal::all_reduce(MPI_MAX, values, mpi_communicator, maxima);
717  }
718 
719 
720  template <typename T>
721  inline
722  T min (const T &t,
723  const MPI_Comm &mpi_communicator)
724  {
725  return internal::all_reduce(MPI_MIN, t, mpi_communicator);
726  }
727 
728 
729  template <typename T, unsigned int N>
730  inline
731  void min (const T (&values)[N],
732  const MPI_Comm &mpi_communicator,
733  T (&minima)[N])
734  {
735  internal::all_reduce(MPI_MIN, values, mpi_communicator, minima);
736  }
737 
738 
739  template <typename T>
740  inline
741  void min (const std::vector<T> &values,
742  const MPI_Comm &mpi_communicator,
743  std::vector<T> &minima)
744  {
745  internal::all_reduce(MPI_MIN, values, mpi_communicator, minima);
746  }
747 
748 
749  inline
750  bool job_supports_mpi ()
751  {
752 #ifdef DEAL_II_WITH_MPI
753  int MPI_has_been_started = 0;
754  MPI_Initialized(&MPI_has_been_started);
755 
756  return (MPI_has_been_started > 0);
757 #else
758  return false;
759 #endif
760  }
761  } // end of namespace MPI
762 } // end of namespace Utilities
763 
764 
765 DEAL_II_NAMESPACE_CLOSE
766 
767 #endif
static const unsigned int invalid_unsigned_int
Definition: types.h:164
static TableIndices< rank > unrolled_to_component_indices(const unsigned int i)
T sum(const T &t, const MPI_Comm &mpi_communicator)
Definition: mpi.h:611
std::size_t size() const
iterator begin()
static TableIndices< rank_ > unrolled_to_component_indices(const unsigned int i)
Definition: tensor.h:1107
unsigned int n_mpi_processes(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:99
Definition: mpi.h:55
MPI_Comm duplicate_communicator(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:117
Definition: mpi.h:48
T min(const T &t, const MPI_Comm &mpi_communicator)
Definition: mpi.h:722
virtual void reinit(const size_type N, const bool omit_zeroing_entries=false)
unsigned int this_mpi_process(const MPI_Comm &mpi_communicator)
Definition: mpi.cc:108
MinMaxAvg min_max_avg(const double my_value, const MPI_Comm &mpi_communicator)
Definition: mpi.cc:239
std::vector< unsigned int > compute_point_to_point_communication_pattern(const MPI_Comm &mpi_comm, const std::vector< unsigned int > &destinations)
Definition: mpi.cc:126
bool job_supports_mpi()
Definition: mpi.h:750
T max(const T &t, const MPI_Comm &mpi_communicator)
Definition: mpi.h:693