Zoltan2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Zoltan2_MappingProblem.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Zoltan2: A package of combinatorial algorithms for scientific computing
4 //
5 // Copyright 2012 NTESS and the Zoltan2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
14 #ifndef _ZOLTAN2_MAPPINGPROBLEM_HPP_
15 #define _ZOLTAN2_MAPPINGPROBLEM_HPP_
16 
17 #include <Zoltan2_Standards.hpp>
18 
19 #include <Zoltan2_Problem.hpp>
23 
25 #include <Zoltan2_TaskMapping.hpp>
26 #include <string>
27 
28 namespace Zoltan2{
29 
31 
45 template<typename Adapter,
46  typename MachineRep = // Default MachineRep type
47  MachineRepresentation<typename Adapter::scalar_t,
48  typename Adapter::part_t> >
49 class MappingProblem : public Problem<Adapter>
50 {
51 public:
52 
53  typedef typename Adapter::scalar_t scalar_t;
54  typedef typename Adapter::gno_t gno_t;
55  typedef typename Adapter::lno_t lno_t;
56  typedef typename Adapter::user_t user_t;
57  typedef typename Adapter::part_t part_t;
59 
62 
65  virtual ~MappingProblem() {};
66 
69  MappingProblem(Adapter *A_, Teuchos::ParameterList *p_,
70  const Teuchos::RCP<const Teuchos::Comm<int> > &ucomm_,
71  partsoln_t *partition_ = NULL,
72  MachineRep *machine_ = NULL) :
73  Problem<Adapter>(A_, p_, ucomm_)
74  {
75  HELLO;
76  createMappingProblem(partition_, machine_);
77  };
78 
79 #ifdef HAVE_ZOLTAN2_MPI
80 
82  MappingProblem(Adapter *A_, Teuchos::ParameterList *p_,
83  MPI_Comm mpicomm_,
84  partsoln_t *partition_ = NULL,
85  MachineRep *machine_ = NULL) :
86  MappingProblem(A_, p_,
87  rcp<const Comm<int> >(
88  new Teuchos::MpiComm<int>(
89  Teuchos::opaqueWrapper(mpicomm_))),
90  partition_, machine_)
91  {}
92 #endif
93 
95  //
96  // \param updateInputData If true this indicates that either
97  // this is the first attempt at solution, or that we
98  // are computing a new solution and the input data has
99  // changed since the previous solution was computed.
100  // If false, this indicates that we are computing a
101  // new solution using the same input data was used for
102  // the previous solution, even though the parameters
103  // may have been changed.
104  //
105  // For the sake of performance, we ask the caller to set
106  // \c updateInputData
107  // to false if he/she is computing a new solution using the same
108  // input data, but different problem parameters, than that which was
109  // used to compute the most recent solution.
110 
111  void solve(bool updateInputData=true);
112 
115  static void getValidParameters(ParameterList & pl)
116  {
117  MachineRepresentation <typename Adapter::scalar_t,
119  RCP<Teuchos::StringValidator> mapping_algorithm_Validator =
120  Teuchos::rcp( new Teuchos::StringValidator(
121  Teuchos::tuple<std::string>( "geometric", "default", "block" )));
122  pl.set("mapping_algorithm", "default", "mapping algorithm",
123  mapping_algorithm_Validator);
124 
125 
126  // bool parameter
127  pl.set("distributed_input_adapter", true,
128  "Whether the input adapter for mapping is distributed over processes or not",
130 
131  // bool parameter
132  pl.set("divide_prime_first", false,
133  "When partitioning into-non power of two, whether to partition for "
134  "nonpowers of two at the beginning, or at the end",
136 
137  //TODO: This should be positive integer validator.
138  pl.set("ranks_per_node", 1,
139  "The number of MPI ranks per node",
141  pl.set("reduce_best_mapping", true,
142  "If true, nodes will calculate different mappings with rotations, and best "
143  "one will be reduced. If not, the result will be the one with longest "
144  "dimension partitioning.",
146  }
147 
149  //
150  // \return the solution to the most recent solve().
151 
152  mapsoln_t *getSolution() { return soln.getRawPtr(); };
153  Teuchos::RCP<MachineRep> getMachine(){return machine; }
154 private:
155  void createMappingProblem(partsoln_t *partition_, MachineRep *machine_);
156 
157  Teuchos::RCP<mapsoln_t> soln;
158 
159  Teuchos::RCP<partsoln_t> partition;
160  Teuchos::RCP<MachineRep> machine;
161 };
162 
164 // createMappingProblem
165 // Method with common functionality for creating a MappingProblem.
166 // Individual constructors do appropriate conversions of input, etc.
167 // This method does everything that all constructors must do.
168 
169 template <typename Adapter, typename MachineRep>
170 void MappingProblem<Adapter, MachineRep>::createMappingProblem(
171  partsoln_t *partition_,
172  MachineRep *machine_)
173 {
174  HELLO;
175 
176  // Save pointer to user's partitioning solution. If not provided, create one.
177 
178  if (partition_) {
179  // User provided a partitioning solution; use it.
180  partition = Teuchos::rcp(partition_, false);
181  }
182  else {
183  // User did not provide a partitioning solution;
184  // Use input adapter to create a "fake" solution with the input partition.
185 
186  partition = rcp(new partsoln_t(this->env_, this->comm_,
187  this->inputAdapter_->getNumWeightsPerID()));
188  size_t nLocal = this->inputAdapter_->getLocalNumIDs();
189 
190  const part_t *inputPartsView = NULL;
191  this->inputAdapter_->getPartsView(inputPartsView);
192  if (nLocal && inputPartsView == NULL) {
193  // User has not provided input parts in input adapter
194  int me = this->comm_->getRank();
195  ArrayRCP<part_t> inputParts = arcp(new part_t[nLocal], 0, nLocal, true);
196  for (size_t i = 0; i < nLocal; i++) inputParts[i] = me;
197  partition->setParts(inputParts);
198  }
199  else {
200  // User has provided input parts; use those.
201  ArrayRCP<part_t> inputParts = arcp(const_cast<part_t *>(inputPartsView),
202  0, nLocal, false);
203  partition->setParts(inputParts);
204  }
205  }
206 
207  // Save pointer to user's machine. If not provided, create one.
208  if (machine_)
209  machine = Teuchos::rcp(machine_, false);
210  else {
211  try {
212  Teuchos::ParameterList pl = this->env_->getParameters();
213 
214  machine = Teuchos::rcp(new MachineRep(*(this->comm_), pl));
215  }
217  }
218 }
219 
221 template <typename Adapter, typename MachineRep>
223 {
224  HELLO;
225 
226 
227  // Determine which algorithm to use based on defaults and parameters.
228  std::string algName("block");
229 
230  Teuchos::ParameterList pl = this->env_->getParametersNonConst();
231  const Teuchos::ParameterEntry *pe = pl.getEntryPtr("mapping_algorithm");
232  if (pe) algName = pe->getValue<std::string>(&algName);
233 
234  try {
235  if (algName == "default") {
236  throw(NotImplemented(__FILE__, __LINE__, __func__zoltan2__));
237 #ifdef KDDKDD_NOT_READH
238  this->algorithm_ = rcp(new AlgDefaultMapping<Adapter,MachineRep>(
239  this->comm_, machine,
240  this->inputAdapter_,
241  partition, this->envConst_));
242  this->soln = rcp(new mapsoln_t(this->env_, this->comm_, this->algorithm_));
243  this->algorithm_->map(this->soln);
244 #endif
245  }
246  else if (algName == "block") {
247  this->algorithm_ = rcp(new AlgBlockMapping<Adapter,MachineRep>(
248  this->comm_, machine,
249  this->inputAdapter_,
250  partition, this->envConst_));
251  this->soln = rcp(new mapsoln_t(this->env_, this->comm_, this->algorithm_));
252  this->algorithm_->map(this->soln);
253  }
254  else if (algName == "geometric") {
255 
256  bool is_input_distributed = true;
257  const Teuchos::ParameterEntry *pe_input_adapter =
258  pl.getEntryPtr("distributed_input_adapter");
259  if (pe_input_adapter)
260  is_input_distributed = pe_input_adapter->getValue<bool>(&is_input_distributed);
261 
262 
263  int ranks_per_node = 1;
264  pe_input_adapter = pl.getEntryPtr("ranks_per_node");
265  if (pe_input_adapter)
266  ranks_per_node = pe_input_adapter->getValue<int>(&ranks_per_node);
267 
268  bool divide_prime_first = false;
269  pe_input_adapter = pl.getEntryPtr("divide_prime_first");
270  if (pe_input_adapter)
271  divide_prime_first = pe_input_adapter->getValue<bool>(&divide_prime_first);
272 
273  bool reduce_best_mapping = true;
274  pe_input_adapter = pl.getEntryPtr("reduce_best_mapping");
275  if (pe_input_adapter)
276  reduce_best_mapping = pe_input_adapter->getValue<bool>(&reduce_best_mapping);
277 
278  this->algorithm_ =
279  rcp(new CoordinateTaskMapper<Adapter,part_t>(this->comm_,
280  machine,
281  this->inputAdapter_,
282  partition,
283  this->envConst_,
284  is_input_distributed,
285  ranks_per_node,
286  divide_prime_first,
287  reduce_best_mapping));
288 
289  this->soln = rcp(new mapsoln_t(this->env_, this->comm_, this->algorithm_));
290 
291  this->algorithm_->map(this->soln);
292  }
293  else {
294  // Add other mapping methods here
295  throw std::logic_error("specified mapping_algorithm not supported");
296  }
297  }
299 }
300 
301 } //namespace Zoltan2
302 
303 #endif
304 
305 #ifdef KDDKDD
306 Case 1
307 MappingProblem(
308  InputAdapter
309  partitioningSolution
310  MachineRepresentation=NULL
311 // KDD Don't know how to properly template MachineRepresentation. Proper types
312 // KDD probably depend on how it is to be used. I imagine MJ needs
313 // KDD pcoord_t to be scalar_t, right? But how does user know that at the
314 // KDD time he calls this constructor?
315 )
316 {
317  // Create MachineRepresentation if not provided
318  // User would have called partitioning problem and provides a solution
319  // Mapping vertices are the parts from the partitioning solution
320  // Create MappingSolution that can return getRankForPart(part)
321 }
322 
323 
324 Case 2
325 MappingProblem(
326  InputAdapter
327  MachineRepresentation=NULL
328 )
329 {
330  // Create MachineRepresentation if not provided
331  // Compute mapping vertices based on InputAdapter's partition
332  // Assuming input adapter's partition should be used.
333  // KDD would use with Exodus/Nemesis input files or PamGen meshes
334 
335 }
336 
337 
338 Case 3
339 MappingProblem(
340  InputAdapter
341  MachineRepresentation=NULL
342 )
343 {
344  // Create MachineRepresentation if not provided
345  // Call a partitioning algorithm to get mapping vertices that are the parts
346  // Mapping vertices are computed from this internal partitioning solution
347  // Maybe relevant models can be shared.
348  // Similar to what's in PartitioningProblem now and to what LibTopoMap does
349 
350 }
351 
352 
353 Case 4
354 MappingProblem(
355  InputAdapter
356  MachineRepresentation=NULL
357 )
358 {
359  // Create MachineRepresentation if not provided
360  // Call mapping with mapping vertices == IDs from the input adapter.
361  // Similar in spirit to previous case, but runs more slowly since current
362  // task mapping is done in serial.
363  // Mehmet has done experiments with Scotch, comparing case 3 with 4.
364  // Case 3 is faster; case 4 has higher quality.
365 
366 
367 }
368 
369 
370 // In general, the applyPartitioningSolution method should take an
371 // optional MappingSolution.
372 
373 // Should MappingSolution provide a re-numbered communicator reflecting the new mapping?
374 
375 #endif
#define HELLO
Zoltan2::BaseAdapter< userTypes_t > base_adapter_t
#define Z2_FORWARD_EXCEPTIONS
Forward an exception back through call stack.
PartitionMapping maps a solution or an input distribution to ranks.
static RCP< Teuchos::BoolParameterEntryValidator > getBoolValidator()
Exists to make setting up validators less cluttered.
Adapter::base_adapter_t base_adapter_t
map_t::global_ordinal_type gno_t
Definition: mapRemotes.cpp:27
void solve(bool updateInputData=true)
Direct the problem to create a solution.
Defines the PartitioningSolution class.
Define a simple mapping of parts to processors assuming parts.
mapsoln_t * getSolution()
Get the solution to the problem.
SparseMatrixAdapter_t::part_t part_t
MappingProblem(Adapter *A_, Teuchos::ParameterList *p_, const Teuchos::RCP< const Teuchos::Comm< int > > &ucomm_, partsoln_t *partition_=NULL, MachineRep *machine_=NULL)
Constructor that takes an Teuchos communicator.
A PartitioningSolution is a solution to a partitioning problem.
Exception thrown when a called base-class method is not implemented.
static void getValidParameters(ParameterList &pl)
Set up validators specific to this Problem.
Problem base class from which other classes (PartitioningProblem, ColoringProblem, OrderingProblem, MatchingProblem, etc.) derive.
Defines the Problem base class.
map_t::local_ordinal_type lno_t
Definition: mapRemotes.cpp:26
static RCP< Teuchos::AnyNumberParameterEntryValidator > getAnyIntValidator()
Exists to make setting up validators less cluttered.
MachineRepresentation Class Base class for representing machine coordinates, networks, etc.
MappingSolution< Adapter > mapsoln_t
Defines the MappingSolution class.
Gathering definitions used in software development.
PartitioningSolution< Adapter > partsoln_t
MappingProblem enables mapping of a partition (either computed or input) to MPI ranks.
Teuchos::RCP< MachineRep > getMachine()
virtual ~MappingProblem()
Destructor.
#define __func__zoltan2__
Zoltan2::BasicUserTypes< zscalar_t, zlno_t, zgno_t > user_t
Definition: Metric.cpp:39