OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
parmetis_dist_util.hpp
1 /*
2  * parmetis_util.hpp
3  *
4  * Created on: Oct 07, 2015
5  * Author: Antonio Leo
6  */
7 
8 #ifndef DISTPARMETIS_UTIL_HPP
9 #define DISTPARMETIS_UTIL_HPP
10 
11 #include <iostream>
12 #include "parmetis.h"
13 #include "VTKWriter/VTKWriter.hpp"
14 #include "VCluster/VCluster.hpp"
15 
22 {
24  idx_t * nvtxs;
25 
30  idx_t * ncon;
31 
33  idx_t * xadj;
34 
36  idx_t * adjncy;
37 
39  idx_t * vwgt;
40 
42  idx_t * vsize;
43 
45  idx_t * adjwgt;
46 
48  idx_t * nparts;
49 
51  real_t * tpwgts;
52 
54  real_t * ubvec;
55 
57  idx_t * options;
58 
60  idx_t * objval;
61 
63  idx_t * part;
64 
66  idx_t * edgecut;
67 
69  real_t * itr;
70 
72  idx_t * numflag;
73 
79  idx_t * wgtflag;
80 };
81 
83 #define BALANCE_CC 1
84 #define BALANCE_CCM 2
86 #define BALANCE_CC_O(c) c+1
88 
96 template<typename Graph>
98 {
101 
103  MPI_Comm comm = (MPI_Comm)NULL;
104 
107 
109  int p_id = 0;
110 
112  size_t nc = 0;
113 
119  void constructAdjList(Graph & sub_g)
120  {
121 
122  // init basic graph informations and part vector
123  Mg.nvtxs[0] = sub_g.getNVertex();
124  Mg.part = new idx_t[sub_g.getNVertex()];
125  for (size_t i = 0; i < sub_g.getNVertex(); i++)
126  Mg.part[i] = p_id;
127 
128  // create xadj, adjlist, vwgt, adjwgt and vsize
129  Mg.xadj = new idx_t[sub_g.getNVertex() + 1];
130  Mg.adjncy = new idx_t[sub_g.getNEdge()];
131  Mg.vwgt = new idx_t[sub_g.getNVertex()];
132  Mg.adjwgt = new idx_t[sub_g.getNEdge()];
133  Mg.vsize = new idx_t[sub_g.getNVertex()];
134 
136  size_t prev = 0;
137 
138  // actual position
139  size_t id = 0;
140 
141  for (size_t i = 0, j = sub_g.firstId(); i < sub_g.getNVertex() && j <= sub_g.lastId(); i++, j++)
142  {
143  size_t idx = sub_g.nodeById(j);
144 
145  // Add weight to vertex and migration cost
146  Mg.vwgt[i] = sub_g.vertex(idx).template get<nm_v::computation>();
147  Mg.vsize[i] = sub_g.vertex(idx).template get<nm_v::migration>();
148 
149  // Calculate the starting point in the adjacency list
150  Mg.xadj[id] = prev;
151 
152  // Create the adjacency list and the weights for edges
153  for (size_t s = 0; s < sub_g.getNChilds(idx); s++)
154  {
155  Mg.adjncy[prev + s] = sub_g.getChild(idx, s);
156 
157  Mg.adjwgt[prev + s] = sub_g.getChildEdge(idx, s).template get<nm_e::communication>();
158  }
159 
160  // update the position for the next vertex
161  prev += sub_g.getNChilds(idx);
162 
163  id++;
164  }
165 
166  // Fill the last point
167  Mg.xadj[id] = prev;
168 
169  }
170 
171 public:
172 
182  v_cl(v_cl), nc(nc)
183  {
184  // TODO Move into VCluster
185  MPI_Comm_dup(MPI_COMM_WORLD, &comm);
186 
187  // Nullify Mg
188  Mg.nvtxs = NULL;
189  Mg.ncon = NULL;
190  Mg.xadj = NULL;
191  Mg.adjncy = NULL;
192  Mg.vwgt = NULL;
193  Mg.vsize = NULL;
194  Mg.adjwgt = NULL;
195  Mg.nparts = NULL;
196  Mg.tpwgts = NULL;
197  Mg.ubvec = NULL;
198  Mg.options = NULL;
199  Mg.objval = NULL;
200  Mg.part = NULL;
201  Mg.edgecut = NULL;
202  Mg.itr = NULL;
203  Mg.numflag = NULL;
204  Mg.wgtflag = NULL;
205  }
206 
207  //TODO deconstruct new variables
214  {
215  // Deallocate the Mg structure
216  if (Mg.nvtxs != NULL)
217  {
218  delete[] Mg.nvtxs;
219  }
220 
221  if (Mg.ncon != NULL)
222  {
223  delete[] Mg.ncon;
224  }
225 
226  if (Mg.xadj != NULL)
227  {
228  delete[] Mg.xadj;
229  }
230 
231  if (Mg.adjncy != NULL)
232  {
233  delete[] Mg.adjncy;
234  }
235 
236  if (Mg.vwgt != NULL)
237  {
238  delete[] Mg.vwgt;
239  }
240 
241  if (Mg.adjwgt != NULL)
242  {
243  delete[] Mg.adjwgt;
244  }
245 
246  if (Mg.nparts != NULL)
247  {
248  delete[] Mg.nparts;
249  }
250 
251  if (Mg.tpwgts != NULL)
252  {
253  delete[] Mg.tpwgts;
254  }
255 
256  if (Mg.ubvec != NULL)
257  {
258  delete[] Mg.ubvec;
259  }
260 
261  if (Mg.options != NULL)
262  {
263  delete[] Mg.options;
264  }
265 
266  if (Mg.part != NULL)
267  {
268  delete[] Mg.part;
269  }
270 
271  if (Mg.edgecut != NULL)
272  {
273  delete[] Mg.edgecut;
274  }
275 
276  if (Mg.numflag != NULL)
277  {
278  delete[] Mg.numflag;
279  }
280 
281  if (Mg.wgtflag != NULL)
282  {
283  delete[] Mg.wgtflag;
284  }
285  }
286 
292  void initSubGraph(Graph & sub_g)
293  {
295 
296  // Get the number of vertex
297 
298  Mg.nvtxs = new idx_t[1];
299  Mg.nvtxs[0] = sub_g.getNVertex();
300 
301  // Set the number of constrains
302 
303  Mg.ncon = new idx_t[1];
304  Mg.ncon[0] = 1;
305 
306  // Set to null the weight of the vertex (init after in constructAdjList) (can be removed)
307 
308  Mg.vwgt = NULL;
309 
310  // Set to null the weight of the edge (init after in constructAdjList) (can be removed)
311 
312  Mg.adjwgt = NULL;
313 
314  // construct the adjacency list
315 
316  constructAdjList(sub_g);
317 
318  // Set the total number of partitions
319 
320  Mg.nparts = new idx_t[1];
321  Mg.nparts[0] = nc;
322 
324 
325  Mg.options = new idx_t[4];
326  Mg.options[0] = 0;
327  Mg.options[1] = 0;
328  Mg.options[2] = 0;
329  Mg.options[3] = 0;
330 
332  Mg.itr = new real_t[1];
333  Mg.itr[0] = 1000.0;
334 
336 
337  Mg.tpwgts = new real_t[Mg.nparts[0]];
338  Mg.ubvec = new real_t[Mg.nparts[0]];
339 
340  for (int s = 0; s < Mg.nparts[0]; s++)
341  {
342  Mg.tpwgts[s] = 1.0 / Mg.nparts[0];
343  Mg.ubvec[s] = 1.05;
344  }
345 
346  Mg.edgecut = new idx_t[1];
347  Mg.edgecut[0] = 0;
348 
350  Mg.numflag = new idx_t[1];
351  Mg.numflag[0] = 0;
352 
354  Mg.wgtflag = new idx_t[1];
355  Mg.wgtflag[0] = 3;
356  }
357 
365  template<unsigned int i>
366  void decompose(Graph & sub_g)
367  {
368 
369  // Decompose
370 
371  ParMETIS_V3_PartKway((idx_t *) sub_g.getVtxdist()->getPointer(), Mg.xadj, Mg.adjncy, Mg.vwgt, Mg.adjwgt, Mg.wgtflag, Mg.numflag, Mg.ncon, Mg.nparts, Mg.tpwgts, Mg.ubvec, Mg.options, Mg.edgecut, Mg.part, &comm);
372  /*
373  ParMETIS_V3_AdaptiveRepart( (idx_t *) vtxdist.getPointer(), Mg.xadj,Mg.adjncy,Mg.vwgt,Mg.vsize,Mg.adjwgt, Mg.wgtflag, Mg.numflag,
374  Mg.ncon, Mg.nparts, Mg.tpwgts, Mg.ubvec, Mg.itr, Mg.options, Mg.edgecut,
375  Mg.part, &comm );
376  */
377 
378  // For each vertex store the processor that contain the data
379  for (size_t id = 0, j = sub_g.firstId(); id < sub_g.getNVertex() && j <= sub_g.lastId(); id++, j++)
380  {
381  sub_g.vertex(sub_g.nodeById(j)).template get<i>() = Mg.part[id];
382  }
383  }
384 
393  template<unsigned int i>
394  void refine(Graph & sub_g)
395  {
396  // Refine
397  //ParMETIS_V3_PartKway((idx_t *) sub_g.getVtxdist()->getPointer(), Mg.xadj, Mg.adjncy, Mg.vwgt, Mg.adjwgt, Mg.wgtflag, Mg.numflag, Mg.ncon, Mg.nparts, Mg.tpwgts, Mg.ubvec, Mg.options, Mg.edgecut, Mg.part, &comm);
398  ParMETIS_V3_AdaptiveRepart((idx_t *) sub_g.getVtxdist()->getPointer(), Mg.xadj, Mg.adjncy, Mg.vwgt, Mg.vsize, Mg.adjwgt, Mg.wgtflag, Mg.numflag, Mg.ncon, Mg.nparts, Mg.tpwgts, Mg.ubvec, Mg.itr, Mg.options, Mg.edgecut, Mg.part, &comm);
399 
400  // For each vertex store the processor that contain the data
401  for (size_t id = 0, j = sub_g.firstId(); id < sub_g.getNVertex() && j <= sub_g.lastId(); id++, j++)
402  {
403  sub_g.vertex(sub_g.nodeById(j)).template get<i>() = Mg.part[id];
404  }
405  }
406 
412  idx_t * getPartition()
413  {
414  return Mg.part;
415  }
416 
422  void reset(Graph & sub_g)
423  {
424  // Deallocate the graph structures
425 
426  if (Mg.xadj != NULL)
427  {
428  delete[] Mg.xadj;
429  }
430 
431  if (Mg.adjncy != NULL)
432  {
433  delete[] Mg.adjncy;
434  }
435 
436  if (Mg.vwgt != NULL)
437  {
438  delete[] Mg.vwgt;
439  }
440 
441  if (Mg.adjwgt != NULL)
442  {
443  delete[] Mg.adjwgt;
444  }
445 
446  if (Mg.part != NULL)
447  {
448  delete[] Mg.part;
449  }
450 
451  if (Mg.vsize != NULL)
452  {
453  delete[] Mg.vsize;
454  }
455 
456  sub_g.deleteGhosts();
457 
458  constructAdjList(sub_g);
459  }
460 }
461 ;
462 
463 #endif
void constructAdjList(Graph &sub_g)
Construct Adjacency list.
idx_t * nparts
number of part to partition the graph
real_t * tpwgts
Desired weight for each partition (one for each constrain)
idx_t * vsize
Array of the vertex size, basically is the total communication amount.
real_t * ubvec
For each partition load imbalance tollerated.
Metis graph structure.
Vcluster & v_cl
VCluster.
size_t getProcessUnitID()
Get the process unit id.
idx_t * nvtxs
The number of vertices in the graph.
DistParmetis(Vcluster &v_cl, size_t nc)
Constructor.
int p_id
Process rank information.
MPI_Comm comm
Communticator for OpenMPI.
idx_t * edgecut
Upon successful completion, the number of edges that are cut by the partitioning is written to this p...
~DistParmetis()
destructor
idx_t * options
Additional option for the graph partitioning.
void decompose(Graph &sub_g)
Decompose the graph.
Helper class to define Metis graph.
void reset(Graph &sub_g)
Reset graph and reconstruct it.
real_t * itr
This parameter describes the ratio of inter-processor communication time compared to data redistri- b...
Implementation of VCluster class.
Definition: VCluster.hpp:36
size_t nc
nc Number of partition
idx_t * vwgt
Array that store the weight for each vertex.
idx_t * objval
return the total comunication cost for each partition
idx_t * adjwgt
The weight of the edge.
idx_t * adjncy
For each vertex it store a list of all neighborhood vertex.
idx_t * getPartition()
Get graph partition vector.
idx_t * numflag
This is used to indicate the numbering scheme that is used for the vtxdist, xadj, adjncy...
idx_t * xadj
For each vertex it store the adjacency lost start for the vertex i.
void initSubGraph(Graph &sub_g)
Set the Sub-graph.
void refine(Graph &sub_g)
Refine the graph.
idx_t * part
Is a output vector containing the partition for each vertex.
Parmetis_dist_graph Mg
Graph in parmetis reppresentation.