Reference documentation for deal.II version Git 08a245e9a2 2021-03-07 21:13:37 +0100
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
mpi_consensus_algorithms.h
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2020 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_mpi_consensus_algorithm_h
17 #define dealii_mpi_consensus_algorithm_h
18 
19 #include <deal.II/base/config.h>
20 
21 #include <deal.II/base/mpi.h>
22 #include <deal.II/base/mpi.templates.h>
23 
25 
26 
27 namespace Utilities
28 {
29  namespace MPI
30  {
37  namespace ConsensusAlgorithms
38  {
61  template <typename T1, typename T2>
62  class Process
63  {
64  public:
68  virtual ~Process() = default;
69 
76  virtual std::vector<unsigned int>
77  compute_targets() = 0;
78 
88  virtual void
89  create_request(const unsigned int other_rank,
90  std::vector<T1> & send_buffer);
91 
102  virtual void
103  prepare_buffer_for_answer(const unsigned int other_rank,
104  std::vector<T2> & recv_buffer);
105 
118  virtual void
119  answer_request(const unsigned int other_rank,
120  const std::vector<T1> &buffer_recv,
121  std::vector<T2> & request_buffer);
122 
130  virtual void
131  read_answer(const unsigned int other_rank,
132  const std::vector<T2> &recv_buffer);
133  };
134 
135 
136 
165  template <typename T1, typename T2>
166  class Interface
167  {
168  public:
169  Interface(Process<T1, T2> &process, const MPI_Comm &comm);
170 
174  virtual ~Interface() = default;
175 
179  virtual void
180  run() = 0;
181 
182  protected:
187 
191  const MPI_Comm &comm;
192 
196  const bool job_supports_mpi;
197 
201  const unsigned int my_rank;
202 
206  const unsigned int n_procs;
207  };
208 
209 
226  template <typename T1, typename T2>
227  class NBX : public Interface<T1, T2>
228  {
229  public:
236  NBX(Process<T1, T2> &process, const MPI_Comm &comm);
237 
241  virtual ~NBX() = default;
242 
246  virtual void
247  run() override;
248 
249  private:
250 #ifdef DEAL_II_WITH_MPI
251 
254  std::vector<unsigned int> targets;
255 
259  std::vector<std::vector<T1>> send_buffers;
260 
264  std::vector<MPI_Request> send_requests;
265 
269  std::vector<std::vector<T2>> recv_buffers;
270 
271 
275  std::vector<MPI_Request> recv_requests;
276 
280  std::vector<std::unique_ptr<std::vector<T2>>> request_buffers;
281 
285  std::vector<std::unique_ptr<MPI_Request>> request_requests;
286 
287  // request for barrier
289 #endif
290 
291 #ifdef DEBUG
292 
295  std::set<unsigned int> requesting_processes;
296 #endif
297 
301  bool
302  check_own_state();
303 
308  void
309  signal_finish();
310 
315  bool
316  check_global_state();
317 
322  void
323  answer_requests();
324 
329  void
330  start_communication();
331 
336  void
337  clean_up_and_end_communication();
338  };
339 
363  template <typename T1, typename T2>
364  class PEX : public Interface<T1, T2>
365  {
366  public:
373  PEX(Process<T1, T2> &process, const MPI_Comm &comm);
374 
378  virtual ~PEX() = default;
379 
383  virtual void
384  run() override;
385 
386  private:
387 #ifdef DEAL_II_WITH_MPI
388 
391  std::vector<unsigned int> targets;
392 
396  std::vector<unsigned int> sources;
397 
398  // data structures to send and receive requests
399 
403  std::vector<std::vector<T1>> send_buffers;
404 
408  std::vector<std::vector<T2>> recv_buffers;
409 
413  std::vector<MPI_Request> send_and_recv_buffers;
414 
418  std::vector<std::vector<T2>> requests_buffers;
419 
423  std::vector<MPI_Request> requests_answers;
424 #endif
425 
430  void
431  answer_requests(int index);
432 
437  unsigned int
438  start_communication();
439 
444  void
445  clean_up_and_end_communication();
446  };
447 
452  template <typename T1, typename T2>
453  class Serial : public Interface<T1, T2>
454  {
455  public:
462  Serial(Process<T1, T2> &process, const MPI_Comm &comm);
463 
467  virtual void
468  run() override;
469  };
470 
481  template <typename T1, typename T2>
482  class Selector : public Interface<T1, T2>
483  {
484  public:
491  Selector(Process<T1, T2> &process, const MPI_Comm &comm);
492 
496  virtual ~Selector() = default;
497 
503  virtual void
504  run() override;
505 
506  private:
507  // Pointer to the actual ConsensusAlgorithms::Interface implementation.
508  std::shared_ptr<Interface<T1, T2>> consensus_algo;
509  };
510 
517  template <typename T1, typename T2>
518  class AnonymousProcess : public Process<T1, T2>
519  {
520  public:
533  const std::function<std::vector<unsigned int>()>
534  &function_compute_targets,
535  const std::function<void(const unsigned int, std::vector<T1> &)>
536  &function_create_request =
537  [](const unsigned int, std::vector<T1> &) {},
538  const std::function<void(const unsigned int,
539  const std::vector<T1> &,
540  std::vector<T2> &)>
541  &function_answer_request = [](const unsigned int,
542  const std::vector<T1> &,
543  std::vector<T2> &) {},
544  const std::function<void(const unsigned int, std::vector<T2> &)>
545  &function_prepare_buffer_for_answer =
546  [](const unsigned int, std::vector<T2> &) {},
547  const std::function<void(const unsigned int, const std::vector<T2> &)>
548  &function_read_answer =
549  [](const unsigned int, const std::vector<T2> &) {});
550 
554  std::vector<unsigned int>
555  compute_targets() override;
556 
560  void
561  create_request(const unsigned int other_rank,
562  std::vector<T1> & send_buffer) override;
563 
567  void
568  answer_request(const unsigned int other_rank,
569  const std::vector<T1> &buffer_recv,
570  std::vector<T2> & request_buffer) override;
571 
575  void
576  prepare_buffer_for_answer(const unsigned int other_rank,
577  std::vector<T2> & recv_buffer) override;
578 
582  void
583  read_answer(const unsigned int other_rank,
584  const std::vector<T2> &recv_buffer) override;
585 
586  private:
587  const std::function<std::vector<unsigned int>()>
588  function_compute_targets;
589  const std::function<void(const int, std::vector<T1> &)>
590  function_create_request;
591  const std::function<
592  void(const unsigned int, const std::vector<T1> &, std::vector<T2> &)>
594  const std::function<void(const int, std::vector<T2> &)>
595  function_prepare_buffer_for_answer;
596  const std::function<void(const int, const std::vector<T2> &)>
597  function_read_answer;
598  };
599 
600 
601 
602  template <typename T1, typename T2>
604  const std::function<std::vector<unsigned int>()>
605  &function_compute_targets,
606  const std::function<void(const unsigned int, std::vector<T1> &)>
607  & function_create_request,
608  const std::function<void(const unsigned int,
609  const std::vector<T1> &,
610  std::vector<T2> &)> &function_answer_request,
611  const std::function<void(const unsigned int, std::vector<T2> &)>
612  &function_prepare_buffer_for_answer,
613  const std::function<void(const unsigned int, const std::vector<T2> &)>
614  &function_read_answer)
615  : function_compute_targets(function_compute_targets)
616  , function_create_request(function_create_request)
617  , function_answer_request(function_answer_request)
618  , function_prepare_buffer_for_answer(function_prepare_buffer_for_answer)
619  , function_read_answer(function_read_answer)
620  {}
621 
622 
623 
624  template <typename T1, typename T2>
625  std::vector<unsigned int>
627  {
628  return function_compute_targets();
629  }
630 
631 
632 
633  template <typename T1, typename T2>
634  void
635  AnonymousProcess<T1, T2>::create_request(const unsigned int other_rank,
636  std::vector<T1> & send_buffer)
637  {
638  function_create_request(other_rank, send_buffer);
639  }
640 
641 
642 
643  template <typename T1, typename T2>
644  void
646  const unsigned int other_rank,
647  const std::vector<T1> &buffer_recv,
648  std::vector<T2> & request_buffer)
649  {
650  function_answer_request(other_rank, buffer_recv, request_buffer);
651  }
652 
653 
654 
655  template <typename T1, typename T2>
656  void
658  const unsigned int other_rank,
659  std::vector<T2> & recv_buffer)
660  {
661  function_prepare_buffer_for_answer(other_rank, recv_buffer);
662  }
663 
664 
665 
666  template <typename T1, typename T2>
667  void
668  AnonymousProcess<T1, T2>::read_answer(const unsigned int other_rank,
669  const std::vector<T2> &recv_buffer)
670  {
671  function_read_answer(other_rank, recv_buffer);
672  }
673 
674 
675 
676  } // namespace ConsensusAlgorithms
677  } // end of namespace MPI
678 } // end of namespace Utilities
679 
680 
682 
683 #endif
std::vector< std::vector< T2 > > requests_buffers
void answer_request(const unsigned int other_rank, const std::vector< T1 > &buffer_recv, std::vector< T2 > &request_buffer) override
std::vector< std::vector< T1 > > send_buffers
virtual std::vector< unsigned int > compute_targets()=0
void create_request(const unsigned int other_rank, std::vector< T1 > &send_buffer) override
void read_answer(const unsigned int other_rank, const std::vector< T2 > &recv_buffer) override
const std::function< void(const int, std::vector< T2 > &)> function_prepare_buffer_for_answer
virtual void create_request(const unsigned int other_rank, std::vector< T1 > &send_buffer)
std::vector< std::vector< T2 > > recv_buffers
const std::function< void(const int, const std::vector< T2 > &)> function_read_answer
virtual void prepare_buffer_for_answer(const unsigned int other_rank, std::vector< T2 > &recv_buffer)
virtual void answer_request(const unsigned int other_rank, const std::vector< T1 > &buffer_recv, std::vector< T2 > &request_buffer)
const std::function< void(const int, std::vector< T1 > &)> function_create_request
const std::function< void(const unsigned int, const std::vector< T1 > &, std::vector< T2 > &)> function_answer_request
const std::function< std::vector< unsigned int >)> function_compute_targets
#define DEAL_II_NAMESPACE_CLOSE
Definition: config.h:394
std::shared_ptr< Interface< T1, T2 > > consensus_algo
virtual void read_answer(const unsigned int other_rank, const std::vector< T2 > &recv_buffer)
std::vector< std::vector< T1 > > send_buffers
*braid_SplitCommworld & comm
std::vector< std::vector< T2 > > recv_buffers
#define DEAL_II_NAMESPACE_OPEN
Definition: config.h:393
std::vector< std::unique_ptr< std::vector< T2 > > > request_buffers
AnonymousProcess(const std::function< std::vector< unsigned int >()> &function_compute_targets, const std::function< void(const unsigned int, std::vector< T1 > &)> &function_create_request=[](const unsigned int, std::vector< T1 > &) {}, const std::function< void(const unsigned int, const std::vector< T1 > &, std::vector< T2 > &)> &function_answer_request=[](const unsigned int, const std::vector< T1 > &, std::vector< T2 > &) {}, const std::function< void(const unsigned int, std::vector< T2 > &)> &function_prepare_buffer_for_answer=[](const unsigned int, std::vector< T2 > &) {}, const std::function< void(const unsigned int, const std::vector< T2 > &)> &function_read_answer=[](const unsigned int, const std::vector< T2 > &) {})
std::vector< std::unique_ptr< MPI_Request > > request_requests
void prepare_buffer_for_answer(const unsigned int other_rank, std::vector< T2 > &recv_buffer) override
void run(const Iterator &begin, const typename identity< Iterator >::type &end, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length, const unsigned int chunk_size)
Definition: work_stream.h:691