Zoltan2
Metric.cpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Zoltan2: A package of combinatorial algorithms for scientific computing
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Karen Devine (kddevin@sandia.gov)
39 // Erik Boman (egboman@sandia.gov)
40 // Siva Rajamanickam (srajama@sandia.gov)
41 //
42 // ***********************************************************************
43 //
44 // @HEADER
45 //
46 // Test the following:
47 // EvaluatePartition class
48 // MetricValues class
49 // Metric related namespace methods
50 
51 
53 #include <Zoltan2_TestHelpers.hpp>
55 #include <stdlib.h>
56 #include <vector>
57 
58 
59 using Teuchos::ArrayRCP;
60 using Teuchos::Array;
61 using Teuchos::RCP;
62 using Teuchos::rcp;
63 using Teuchos::arcp;
64 
65 using namespace std;
66 using std::endl;
67 using std::cout;
68 
69 
70 void doTest(RCP<const Comm<int> > comm, int numLocalObj,
71  int nWeights, int numLocalParts, bool givePartSizes);
72 
73 int main(int argc, char *argv[])
74 {
75  Teuchos::GlobalMPISession session(&argc, &argv);
76  RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm();
77  int rank = comm->getRank();
78 
79  doTest(comm, 10, 0, -1, false);
80  doTest(comm, 10, 0, 1, false);
81  doTest(comm, 10, 0, 1, true);
82  doTest(comm, 10, 1, 1, false);
83  doTest(comm, 10, 1, 1, true);
84  doTest(comm, 10, 2, 1, false);
85  doTest(comm, 10, 2, 1, true);
86  doTest(comm, 10, 1, 2, true);
87  doTest(comm, 10, 1, 2, false);
88  doTest(comm, 10, 1, -1, false);
89  doTest(comm, 10, 1, -1, true);
90  doTest(comm, 10, 2, -1, false);
91 
92  if (rank==0)
93  cout << "PASS" << endl;
94 }
95 
96 // Assumes numLocalObj is the same on every process.
97 
98 void doTest(RCP<const Comm<int> > comm, int numLocalObj,
99  int nWeights, int numLocalParts, bool givePartSizes)
100 {
103  typedef Zoltan2::EvaluatePartition<idInput_t> quality_t;
104  typedef idInput_t::part_t part_t;
105  typedef idInput_t::base_adapter_t base_adapter_t;
106 
107  int rank = comm->getRank();
108  int nprocs = comm->getSize();
109  int fail=0;
110  srand(rank+1);
111  bool testEmptyParts = (numLocalParts < 1);
112  int numGlobalParts = 0;
113 
114  if (testEmptyParts){
115  numGlobalParts = nprocs / 2;
116  if (numGlobalParts >= 1)
117  numLocalParts = (rank < numGlobalParts ? 1 : 0);
118  else{
119  numLocalParts = 1;
120  testEmptyParts = false;
121  }
122  }
123  else{
124  numGlobalParts = nprocs * numLocalParts;
125  }
126 
127  if (rank == 0){
128  cout << endl;
129  cout << "Test: number of weights " << nWeights;
130  cout << ", desired number of parts " << numGlobalParts;
131  if (givePartSizes)
132  cout << ", with differing part sizes." << endl;
133  else
134  cout << ", with uniform part sizes." << endl;
135  cout << "Number of procs " << nprocs;
136  cout << ", each with " << numLocalObj << " objects, part = rank." << endl;
137  }
138 
139  // An environment. This is usually created by the problem.
140 
141  Teuchos::ParameterList pl("test list");
142  pl.set("num_local_parts", double(numLocalParts));
143 
144  RCP<const Zoltan2::Environment> env =
145  rcp(new Zoltan2::Environment(pl, comm));
146 
147  // A simple identifier map. Usually created by the model.
148 
149  zgno_t *myGids = new zgno_t [numLocalObj];
150  for (int i=0, x=rank*numLocalObj; i < numLocalObj; i++, x++){
151  myGids[i] = x;
152  }
153 
154  // Part sizes. Usually supplied by the user to the Problem.
155  // Then the problem supplies them to the Solution.
156 
157  int partSizeDim = (givePartSizes ? (nWeights ? nWeights : 1) : 0);
158  ArrayRCP<ArrayRCP<part_t> > ids(partSizeDim);
159  ArrayRCP<ArrayRCP<zscalar_t> > sizes(partSizeDim);
160 
161  if (givePartSizes && numLocalParts > 0){
162  part_t *myParts = new part_t [numLocalParts];
163  myParts[0] = rank * numLocalParts;
164  for (int i=1; i < numLocalParts; i++)
165  myParts[i] = myParts[i-1] + 1;
166  ArrayRCP<part_t> partNums(myParts, 0, numLocalParts, true);
167 
168  zscalar_t sizeFactor = nprocs/2 - rank;
169  if (sizeFactor < 0) sizeFactor *= -1;
170  sizeFactor += 1;
171 
172  for (int dim=0; dim < partSizeDim; dim++){
173  zscalar_t *psizes = new zscalar_t [numLocalParts];
174  for (int i=0; i < numLocalParts; i++)
175  psizes[i] = sizeFactor;
176  sizes[dim] = arcp(psizes, 0, numLocalParts, true);
177 
178  ids[dim] = partNums;
179  }
180  }
181 
182  // An input adapter with random weights. Created by the user.
183 
184  std::vector<const zscalar_t *> weights;
185  std::vector<int> strides; // default to 1
186 
187  int len = numLocalObj*nWeights;
188  ArrayRCP<zscalar_t> wgtBuf;
189  zscalar_t *wgts = NULL;
190 
191  if (len > 0){
192  wgts = new zscalar_t [len];
193  wgtBuf = arcp(wgts, 0, len, true);
194  for (int i=0; i < len; i++)
195  wgts[i] = (zscalar_t(rand()) / zscalar_t(RAND_MAX)) + 1.0;
196  }
197 
198  for (int i=0; i < nWeights; i++, wgts+=numLocalObj)
199  weights.push_back(wgts);
200 
201  RCP<const idInput_t> ia;
202  RCP<const base_adapter_t> bia;
203 
204  try{
205  ia = rcp(new idInput_t(numLocalObj, myGids, weights, strides));
206  }
207  catch (std::exception &e){
208  fail=1;
209  }
210 
211  TEST_FAIL_AND_EXIT(*comm, fail==0, "create adapter", 1);
212 
213  bia = Teuchos::rcp_implicit_cast<const base_adapter_t>(ia);
214 
215  // A solution (usually created by a problem)
216 
217  RCP<Zoltan2::PartitioningSolution<idInput_t> > solution;
218 
219  try{
220  if (givePartSizes)
221  solution = rcp(new Zoltan2::PartitioningSolution<idInput_t>(
222  env, comm, nWeights,
223  ids.view(0,partSizeDim), sizes.view(0,partSizeDim)));
224  else
225  solution = rcp(new Zoltan2::PartitioningSolution<idInput_t>(
226  env, comm, nWeights));
227  }
228  catch (std::exception &e){
229  fail=1;
230  }
231 
232  TEST_FAIL_AND_EXIT(*comm, fail==0, "create solution", 1);
233 
234  // Part assignment for my objects: The algorithm usually calls this.
235 
236  part_t *partNum = new part_t [numLocalObj];
237  ArrayRCP<part_t> partAssignment(partNum, 0, numLocalObj, true);
238  for (int i=0; i < numLocalObj; i++)
239  partNum[i] = rank;
240 
241  solution->setParts(partAssignment);
242  RCP<const Zoltan2::PartitioningSolution<idInput_t> > solutionConst =
243  rcp_const_cast<const Zoltan2::PartitioningSolution<idInput_t> >(solution);
244 
245  // create metric object (also usually created by a problem)
246 
247  RCP<quality_t> metricObject;
248 
249  try{
250  metricObject = rcp(new quality_t(env, comm, bia, solutionConst, false));
251  }
252  catch (std::exception &e){
253  fail=1;
254  }
255 
256  TEST_FAIL_AND_EXIT(*comm, fail==0, "compute metrics", 1);
257 
258 
259  if (rank==0){
260  zscalar_t imb;
261  try{
262  metricObject->getObjectCountImbalance(imb);
263  cout << "Object imbalance: " << imb << endl;
264  }
265  catch (std::exception &e){
266  fail=1;
267  }
268  }
269 
270  TEST_FAIL_AND_EXIT(*comm, fail==0, "getObjectCountImbalance", 1);
271 
272  if (rank==0 && nWeights > 0){
273  zscalar_t imb;
274  try{
275  for (int i=0; i < nWeights; i++){
276  metricObject->getWeightImbalance(imb, i);
277  cout << "Weight " << i << " imbalance: " << imb << endl;
278  }
279  }
280  catch (std::exception &e){
281  fail=10;
282  }
283  if (!fail && nWeights > 1){
284  try{
285  metricObject->getNormedImbalance(imb);
286  cout << "Normed weight imbalance: " << imb << endl;
287  }
288  catch (std::exception &e){
289  fail=11;
290  }
291  }
292  }
293 
294  TEST_FAIL_AND_EXIT(*comm, fail==0, "get imbalances", 1);
295 
296  if (rank==0){
297  try{
298  metricObject->printMetrics(cout);
299  }
300  catch (std::exception &e){
301  fail=1;
302  }
303  }
304 
305  TEST_FAIL_AND_EXIT(*comm, fail==0, "print metrics", 1);
306 }
IdentifierAdapter defines the interface for identifiers.
void doTest(RCP< const Comm< int > > comm, int numLocalObj, int nWeights, int numLocalParts, bool givePartSizes)
Definition: Metric.cpp:98
double zscalar_t
A simple class that can be the User template argument for an InputAdapter.
#define TEST_FAIL_AND_EXIT(comm, ok, s, code)
static ArrayRCP< ArrayRCP< zscalar_t > > weights
common code used by tests
int main(int argc, char *argv[])
Definition: Metric.cpp:73
This class represents a collection of global Identifiers and their associated weights, if any.
A PartitioningSolution is a solution to a partitioning problem.
Defines the EvaluatePartition class.
The user parameters, debug, timing and memory profiling output objects, and error checking methods...
static const std::string fail
int zgno_t
Defines the BasicIdentifierAdapter class.
Zoltan2::BasicIdentifierAdapter< zzuser_t > idInput_t
A class that computes and returns quality metrics.