OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
GeometricStrategy.h
Go to the documentation of this file.
1 #ifndef __GEOMETRIC_STRATEGY_H__
2 #define __GEOMETRIC_STRATEGY_H__
3 
4 #include <set>
5 #include <vector>
6 
8 
9 typedef std::vector<int> coordinates_t;
10 
11 typedef struct {
14  MPI_Comm comm;
16  std::vector<int> worker_pids;
17 } region_t;
18 
24 class GeometricStrategy : protected SplitStrategy {
25 
26 public:
27 
28  GeometricStrategy(size_t num_masters,
29  boost::shared_ptr<CommTopology> topology, MPI_Comm comm)
30  : Strategy(num_masters, topology, comm)
31  {}
32 
34  {}
35 
36  void split() {
37 
38  // 1. Initialize the region list with the initial topology
39  region_t initial_region;
40  for(int dim=0; dim < topology_.getNumDimensions(); dim++) {
41  initial_region.origin.push_back(0);
42  initial_region.extensions.push_back(dims_[dim]);
43  }
44  regions_.push_back(initial_region);
45 
46  // 2. Build num_masters_ partitions of the topology
47  while(regions_.size() < num_masters_) {
49  }
50 
51  // 3. Compute centroids of partition and assign master
52  for(region_t & region : regions_) {
53  computeCentroid(region);
54  }
55 
56  // 4. Create communicator groups
57  for(region_t & region : regions_) {
58  bool is_worker = false;
59 
60  coordinates_t iter = region.origin;
61  for(int x = 0; x < region.extensions[0]; x++) {
62  iter[0] = region.origin[0] + x;
63  for(int y = 0; y < region.extensions[1]; y++) {
64  iter[1] = region.origin[1] + y;
65  for(int z = 0; z < region.extensions[2]; z++) {
66  iter[2] = region.origin[2] + z;
67 
68  std::vector<int> worker_pids;
69  coordinatesToPID(iter, worker_pids);
70 
71  if(worker_pids[0] != region.master_pid)
72  region.worker_pids.push_back(worker_pids[0]);
73 
74  region.worker_pids.push_back(worker_pids[1]);
75  region.worker_pids.push_back(worker_pids[2]);
76  region.worker_pids.push_back(worker_pids[3]);
77 
78  if(rank_ == worker_pids[0] ||
79  rank_ == worker_pids[1] ||
80  rank_ == worker_pids[2] ||
81  rank_ == worker_pids[3] ) {
82  is_worker = true;
83  }
84 
85  }
86  }
87  }
88 
89  if(rank_ == region.master_pid || is_worker)
90  addCommGroup(region.master_pid, region.worker_pids);
91 
92  MPI_Barrier(comm_);
93  }
94  }
95 
96 protected:
97 
98  std::vector<region_t> regions_;
99 
101 
102  // first we determine the largest extension of all remaining regions
103  int origin = 0;
104  int split_in_direction = 0;
105  int max_ext_dir = 0;
106 
107  for(region_t region : regions_) {
108  for(int dim = 0; dim < topology_.getNumDimensions(); dim++) {
109  if(region.extensions[dim] > max_ext_dir) {
110  split_in_direction = dim;
111  origin = region.origin[dim];
112  max_ext_dir = region.extensions[dim];
113  }
114  }
115  }
116 
117  // now we can perform splits as long as the number of requested
118  // regions is not reached
119  int split_at_coordinate = origin;
120  split_at_coordinate += (int)(max_ext_dir / 2.0);
121 
122  splitRegionAt(split_at_coordinate, split_in_direction);
123  }
124 
125  void splitRegionAt(int split_at_coordinate, int split_in_direction) {
126 
127  int removed = 0;
128  bool continue_splitting = true;
129  std::vector<region_t> new_regions;
131  for(itr = regions_.begin(); itr != regions_.end(); itr++) {
132 
133  if(regions_.size() + new_regions.size() - removed == num_masters_)
134  continue_splitting = false;
135 
136  double origin = itr->origin[split_in_direction];
137  double extension = itr->extensions[split_in_direction];
138  if( continue_splitting &&
139  isSplittable(origin, split_at_coordinate, extension) ) {
140 
141  // clone region
142  region_t second = *itr;
143 
144  // and split
145  second.origin[split_in_direction] = split_at_coordinate;
146  second.extensions[split_in_direction] = extension - (split_at_coordinate - origin);
147 
148  itr->extensions[split_in_direction] = split_at_coordinate - origin;
149 
150  new_regions.push_back(*itr);
151  new_regions.push_back(second);
152  removed++;
153 
154  } else {
155 
156  new_regions.push_back(*itr);
157  removed++;
158  }
159  }
160 
161  regions_ = new_regions;
162  }
163 
164  bool isSplittable(double origin, double split_at_coordinate, double extension) {
165  return (origin < split_at_coordinate &&
166  split_at_coordinate < origin + extension);
167  }
168 
169  void computeCentroid(region_t &region) {
170 
171  coordinates_t centroid;
172  centroid.resize(3, 0);
173 
174  for(unsigned int pos=0; pos < region.extensions.size(); pos++) {
175  int centroid_coordinate = (int)(region.origin[pos]*1.0 + region.extensions[pos]/2.0);
176  centroid[pos] = centroid_coordinate;
177  }
178 
179  std::vector<int> pids;
180  coordinatesToPID(centroid, pids);
181  region.master_pid = pids[0];
182  }
183 
184  void coordinatesToPID(coordinates_t coordinate, std::vector<int> &pid) {
185 
186  pid.resize(4, 0);
187 
188  if(coords_[0] == coordinate[0] &&
189  coords_[1] == coordinate[1] &&
190  coords_[2] == coordinate[2] ) {
191  pid[my_core_] = rank_;
192  }
193 
194  MPI_Allreduce(MPI_IN_PLACE, &pid[0], 4, MPI_INT, MPI_SUM, comm_);
195  }
196 
197  void printRegion(region_t region) {
198  if(rank_ == 0) {
199  std::cout << "region: ";
200  std::cout << "[" << region.origin[0] << ", " << region.origin[1] << ", " << region.origin[2] << "], ";
201  std::cout << "[" << region.extensions[0] << ", " << region.extensions[1] << ", " << region.extensions[2] << "]";
202  std::cout << std::endl;
203  }
204  }
205 
206 };
207 
208 #endif
void computeCentroid(region_t &region)
std::vector< region_t > regions_
std::vector< int > worker_pids
bool isSplittable(double origin, double split_at_coordinate, double extension)
void splitRegionAt(int split_at_coordinate, int split_in_direction)
MPI_Comm comm_
communicator we are splitting
Definition: SplitStrategy.h:63
std::vector< int > coordinates_t
void printRegion(region_t region)
MPI_Comm comm
void coordinatesToPID(coordinates_t coordinate, std::vector< int > &pid)
GeometricStrategy(size_t num_masters, boost::shared_ptr< CommTopology > topology, MPI_Comm comm)
coordinates_t origin
std::string::iterator iterator
Definition: MSLang.h:16
virtual ~GeometricStrategy()
Defines an interface for splitter strategy implementations.
Definition: SplitStrategy.h:13
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
coordinates_t extensions