Block-Structured AMR Software Framework
AMReX_ForkJoin.H
Go to the documentation of this file.
1 #ifndef AMREX_FORKJOIN_H
2 #define AMREX_FORKJOIN_H
3 #include <AMReX_Config.H>
4 
6 #include <AMReX_MultiFab.H>
7 #include <utility>
8 
9 namespace amrex {
10 
11 class ForkJoin
12 {
13  public:
14 
15  enum class Strategy {
16  single,
17  duplicate,
18  split,
19  };
20  enum class Intent { in, out, inout };
21 
23  struct ComponentSet {
27  ComponentSet() = default;
28  ComponentSet(int lo_, int hi_) : lo(lo_), hi(hi_) {}
29  int lo;
30  int hi;
31  };
32 
33  ForkJoin (const Vector<int> &task_rank_n);
34 
35  ForkJoin (const Vector<double> &task_rank_pct);
36 
37  ForkJoin (int ntasks)
38  : ForkJoin( Vector<double>(ntasks, 1.0 / ntasks) ) { }
39 
40  int NTasks () const { return static_cast<int>(split_bounds.size() - 1); }
41 
42  int MyTask () const { return task_me; }
43 
44  bool Verbose () const { return flag_verbose; }
45 
46  void SetVerbose (bool verbose_in) { flag_verbose = verbose_in; }
47 
48  ComponentSet ComponentBounds(const std::string& name, int idx=0) const;
49 
50  int NProcsTask (int task) const {
51  AMREX_ASSERT(task + 1 < split_bounds.size());
52  return split_bounds[task + 1] - split_bounds[task];
53  }
54 
55  void reg_mf (MultiFab &mf, const std::string &name, int idx,
56  Strategy strategy, Intent intent, int owner = -1);
57 
58  void reg_mf (MultiFab &mf, const std::string &name,
59  Strategy strategy, Intent intent, int owner = -1) {
60  reg_mf(mf, name, 0, strategy, intent, owner);
61  }
62 
66  void reg_mf (const MultiFab &mf, const std::string &name, int idx,
67  Strategy strategy, Intent intent, int owner = -1) {
69  "const MultiFab must be registered read-only");
70  reg_mf(const_cast<MultiFab&>(mf), name, idx, strategy, intent, owner);
71  }
72  void reg_mf (const MultiFab &mf, const std::string &name,
73  Strategy strategy, Intent intent, int owner = -1) {
74  reg_mf(mf, name, 0, strategy, intent, owner);
75  }
76 
77  void reg_mf_vec (const Vector<MultiFab *> &mfs, const std::string &name,
78  Strategy strategy, Intent intent, int owner = -1) {
79  data[name].reserve(mfs.size());
80  for (int i = 0; i < mfs.size(); ++i) {
81  reg_mf(*mfs[i], name, i, strategy, intent, owner);
82  }
83  }
84 
86  void reg_mf_vec (const Vector<MultiFab const *> &mfs, const std::string &name,
87  Strategy strategy, Intent intent, int owner = -1) {
88  data[name].reserve(mfs.size());
89  for (int i = 0; i < mfs.size(); ++i) {
90  reg_mf(*mfs[i], name, i, strategy, intent, owner);
91  }
92  }
93 
95  void modify_ngrow (const std::string &name, int idx, IntVect ngrow);
96  void modify_ngrow (const std::string &name, IntVect ngrow) {
97  modify_ngrow(name, 0, ngrow);
98  }
99 
101  void modify_split (const std::string &name, int idx, Vector<ComponentSet> comp_split);
102  void modify_split (const std::string &name, Vector<ComponentSet> comp_split) {
103  modify_split(name, 0, std::move(comp_split));
104  }
105 
106  // TODO: may want to de-register MFs if they change across invocations
107 
108  MultiFab &get_mf (const std::string &name, int idx = 0) {
109  AMREX_ASSERT_WITH_MESSAGE(data.count(name) > 0 && idx < data[name].size(), "get_mf(): name or index not found");
110  AMREX_ASSERT(task_me >= 0 && task_me < data[name][idx].forked.size());
111  return data[name][idx].forked[task_me];
112  }
113 
115  Vector<MultiFab *> get_mf_vec (const std::string &name) {
116  int dim = static_cast<int>(data.at(name).size());
117  Vector<MultiFab *> result(dim);
118  for (int idx = 0; idx < dim; ++idx) {
119  result[idx] = &get_mf(name, idx);
120  }
121  return result;
122  }
123 
124  void set_task_output_dir (const std::string & dir)
125  {
126  task_output_dir = dir;
127  }
128 
129  static void set_task_output_file (const std::string & filename)
130  {
132  }
133 
134  template <class F>
135  void fork_join (const F &fn)
136  {
137  flag_invoked = true; // set invoked flag
138  const int io_rank = 0; // team's sub-rank 0 does IO
140  MPI_Comm task_comm = split_tasks();
141  copy_data_to_tasks(); // move data to local tasks
142  ParallelContext::push(task_comm, task_me, io_rank);
144  fn(*this);
146 #ifdef BL_USE_MPI
147  MPI_Comm_free(&task_comm);
148 #endif
149  copy_data_from_tasks(); // move local data back
150  }
151 
152  private:
153 
154  struct MFFork
155  {
156  MultiFab *orig = nullptr;
163 
164  MFFork () = default;
165  ~MFFork () = default;
166  MFFork (const MFFork&) = delete;
167  MFFork& operator= (const MFFork&) = delete;
168  MFFork (MFFork&&) = default;
169  MFFork& operator= (MFFork&&) = default;
170  MFFork (MultiFab *omf, Strategy s, Intent i, int own,
171  const IntVect &ng,
173  : orig(omf), strategy(s), intent(i), owner_task(own), ngrow(ng), comp_split(std::move(cs)) {}
174 
175  [[nodiscard]] bool empty() const { return orig == nullptr; }
176  };
177 
178  bool flag_verbose = false;
179  bool flag_invoked = false;
181  int task_me = -1;
182  std::map<BoxArray::RefID, Vector<std::unique_ptr<DistributionMapping>>> dms;
183  std::unordered_map<std::string, Vector<MFFork>> data;
184  std::string task_output_dir;
185 
186  void init(const Vector<int> &task_rank_n);
187 
192  const DistributionMapping &get_dm (const BoxArray& ba, int task_idx,
193  const DistributionMapping& dm_orig);
194 
198  void copy_data_to_tasks ();
199 
203  void copy_data_from_tasks ();
204 
207 
209  void create_task_output_dir ();
210 
212  std::string get_io_filename (bool flag_unique = false);
213 };
214 
215 }
216 
217 #endif // AMREX_FORKJOIN_H
#define AMREX_ASSERT_WITH_MESSAGE(EX, MSG)
Definition: AMReX_BLassert.H:37
#define AMREX_ASSERT(EX)
Definition: AMReX_BLassert.H:38
int MPI_Comm
Definition: AMReX_ccse-mpi.H:47
A collection of Boxes stored in an Array.
Definition: AMReX_BoxArray.H:549
Calculates the distribution of FABs to MPI processes.
Definition: AMReX_DistributionMapping.H:41
Definition: AMReX_ForkJoin.H:12
ForkJoin(const Vector< int > &task_rank_n)
Definition: AMReX_ForkJoin.cpp:46
int NTasks() const
Definition: AMReX_ForkJoin.H:40
std::unordered_map< std::string, Vector< MFFork > > data
Definition: AMReX_ForkJoin.H:183
ForkJoin(int ntasks)
Definition: AMReX_ForkJoin.H:37
void fork_join(const F &fn)
Definition: AMReX_ForkJoin.H:135
void reg_mf(const MultiFab &mf, const std::string &name, int idx, Strategy strategy, Intent intent, int owner=-1)
Definition: AMReX_ForkJoin.H:66
Intent
Definition: AMReX_ForkJoin.H:20
int NProcsTask(int task) const
Definition: AMReX_ForkJoin.H:50
void reg_mf_vec(const Vector< MultiFab * > &mfs, const std::string &name, Strategy strategy, Intent intent, int owner=-1)
Definition: AMReX_ForkJoin.H:77
void reg_mf(MultiFab &mf, const std::string &name, int idx, Strategy strategy, Intent intent, int owner=-1)
Definition: AMReX_ForkJoin.cpp:107
Vector< int > split_bounds
task i has ranks over the interval [result[i], result[i+1])
Definition: AMReX_ForkJoin.H:180
std::map< BoxArray::RefID, Vector< std::unique_ptr< DistributionMapping > > > dms
DM cache.
Definition: AMReX_ForkJoin.H:182
Strategy
Definition: AMReX_ForkJoin.H:15
@ duplicate
all tasks get a copy of whole MF
@ single
one task gets a copy of whole MF
@ split
split MF components across tasks
void copy_data_to_tasks()
Definition: AMReX_ForkJoin.cpp:179
MultiFab & get_mf(const std::string &name, int idx=0)
Definition: AMReX_ForkJoin.H:108
void modify_ngrow(const std::string &name, IntVect ngrow)
Definition: AMReX_ForkJoin.H:96
Vector< MultiFab * > get_mf_vec(const std::string &name)
vector of pointers to all MFs under a name
Definition: AMReX_ForkJoin.H:115
bool flag_verbose
for debugging
Definition: AMReX_ForkJoin.H:178
void modify_ngrow(const std::string &name, int idx, IntVect ngrow)
modify the number of grow cells associated with the multifab
Definition: AMReX_ForkJoin.cpp:141
void set_task_output_dir(const std::string &dir)
Definition: AMReX_ForkJoin.H:124
ComponentSet ComponentBounds(const std::string &name, int idx=0) const
Definition: AMReX_ForkJoin.cpp:171
void reg_mf(const MultiFab &mf, const std::string &name, Strategy strategy, Intent intent, int owner=-1)
Definition: AMReX_ForkJoin.H:72
bool Verbose() const
Definition: AMReX_ForkJoin.H:44
std::string task_output_dir
where to write task output
Definition: AMReX_ForkJoin.H:184
const DistributionMapping & get_dm(const BoxArray &ba, int task_idx, const DistributionMapping &dm_orig)
Definition: AMReX_ForkJoin.cpp:283
int task_me
which forked task the rank belongs to
Definition: AMReX_ForkJoin.H:181
void SetVerbose(bool verbose_in)
Definition: AMReX_ForkJoin.H:46
static void set_task_output_file(const std::string &filename)
Definition: AMReX_ForkJoin.H:129
void modify_split(const std::string &name, int idx, Vector< ComponentSet > comp_split)
modify how the multifab is split along components across the tasks
Definition: AMReX_ForkJoin.cpp:155
void create_task_output_dir()
create the task output directory
Definition: AMReX_ForkJoin.cpp:349
void copy_data_from_tasks()
Definition: AMReX_ForkJoin.cpp:241
bool flag_invoked
track if object has been invoked yet
Definition: AMReX_ForkJoin.H:179
void reg_mf_vec(const Vector< MultiFab const * > &mfs, const std::string &name, Strategy strategy, Intent intent, int owner=-1)
overload in case of vector of pointer to const MultiFab
Definition: AMReX_ForkJoin.H:86
std::string get_io_filename(bool flag_unique=false)
unique output file for this sub-task
Definition: AMReX_ForkJoin.cpp:364
void reg_mf(MultiFab &mf, const std::string &name, Strategy strategy, Intent intent, int owner=-1)
Definition: AMReX_ForkJoin.H:58
int MyTask() const
Definition: AMReX_ForkJoin.H:42
void modify_split(const std::string &name, Vector< ComponentSet > comp_split)
Definition: AMReX_ForkJoin.H:102
MPI_Comm split_tasks()
split top frame of stack
Definition: AMReX_ForkJoin.cpp:327
void init(const Vector< int > &task_rank_n)
Definition: AMReX_ForkJoin.cpp:69
A collection (stored as an array) of FArrayBox objects.
Definition: AMReX_MultiFab.H:38
Long size() const noexcept
Definition: AMReX_Vector.H:50
void push(MPI_Comm c)
Definition: AMReX_ParallelContext.H:102
void pop()
Note that it's the user's responsibility to free the MPI_Comm.
Definition: AMReX_ParallelContext.H:108
void set_last_frame_ofs(const std::string &filename)
Definition: AMReX_ParallelContext.H:104
Definition: AMReX_Amr.cpp:49
if strategy == split, use this to specify how to split components across tasks
Definition: AMReX_ForkJoin.H:23
int lo
inclusive bound
Definition: AMReX_ForkJoin.H:29
ComponentSet(int lo_, int hi_)
Definition: AMReX_ForkJoin.H:28
int hi
exclusive bound
Definition: AMReX_ForkJoin.H:30
Definition: AMReX_ForkJoin.H:155
Vector< ComponentSet > comp_split
if strategy == split, how to split components to tasks
Definition: AMReX_ForkJoin.H:161
Vector< MultiFab > forked
holds new multifab for each task in fork
Definition: AMReX_ForkJoin.H:162
bool empty() const
Definition: AMReX_ForkJoin.H:175
MFFork(MultiFab *omf, Strategy s, Intent i, int own, const IntVect &ng, Vector< ComponentSet > cs)
Definition: AMReX_ForkJoin.H:170
Strategy strategy
Definition: AMReX_ForkJoin.H:157
MFFork(const MFFork &)=delete
MFFork(MFFork &&)=default
int owner_task
only used if strategy == single or duplicate
Definition: AMReX_ForkJoin.H:159
IntVect ngrow
Definition: AMReX_ForkJoin.H:160
MFFork & operator=(const MFFork &)=delete
Intent intent
Definition: AMReX_ForkJoin.H:158
MultiFab * orig
Definition: AMReX_ForkJoin.H:156