OpenFPM  5.2.0
Project that contain the implementation of distributed structures
DistParMetisDistribution.hpp
1 /*
2  * DistParMetisDistribution.hpp
3  *
4  * Created on: Nov 19, 2015
5  * Author: Antonio Leo
6  */
7 
8 #ifndef SRC_DECOMPOSITION_DISTPARMETISDISTRIBUTION_HPP_
9 #define SRC_DECOMPOSITION_DISTPARMETISDISTRIBUTION_HPP_
10 
11 #include "SubdomainGraphNodes.hpp"
12 #include "parmetis_dist_util.hpp"
13 #include "Graph/dist_map_graph.hpp"
14 #include "Graph/DistGraphFactory.hpp"
15 
16 template<unsigned int dim, typename T>
18 {
21 
24 
27 
30 
33 
36 
39 
42 
44  size_t g_moved = 0;
45 
47  size_t m_moved = 0;
48 
50  bool verticesGotWeights = false;
51 
61  static void * message_receive(size_t msg_i, size_t total_msg, size_t total_p, size_t i, size_t ri, void * ptr)
62  {
64 
65  v->get(i).resize(msg_i / sizeof(idx_t));
66 
67  return &(v->get(i).get(0));
68  }
69 
70 public:
71 
77  v_cl(v_cl), parmetis_graph(v_cl, v_cl.getProcessingUnits()), vtxdist(v_cl.getProcessingUnits() + 1), partitions(v_cl.getProcessingUnits()), v_per_proc(v_cl.getProcessingUnits())
78 
79  {
80  }
81 
88  {
90  gr = grid;
91  domain = dom;
92 
95  g = dist_g_factory.template construct<NO_EDGE, T, dim - 1, 0>(gr.getSize(), domain);
97 
98  if (dim == 2)
99  for (size_t i = 0; i < g.getNVertex(); i++)
100  g.vertex(i).template get<nm_v_x>()[2] = 0;
101 
102  }
103 
108  {
109  return g;
110  }
111 
115  void decompose()
116  {
119 
121  parmetis_graph.template decompose<nm_v_proc_id>(g);
122 
124  idx_t *partition = parmetis_graph.getPartition();
125 
126  for (size_t i = 0, j = g.firstId(); i < g.getNVertex() && j <= g.lastId(); i++, j++)
127  {
128  if ((size_t)partition[i] != v_cl.getProcessUnitID())
129  g.q_move(g.nodeById(j), partition[i]);
130  }
131  g.redistribute();
132  }
133 
140  void refine()
141  {
144 
146  parmetis_graph.template refine<nm_v_proc_id>(g);
147 
149  idx_t *partition = parmetis_graph.getPartition();
150 
151  for (size_t i = 0, j = g.firstId(); i < g.getNVertex() && j <= g.lastId(); i++, j++)
152  {
153  if ((size_t)partition[i] != v_cl.getProcessUnitID())
154  g.q_move(g.nodeById(j), partition[i]);
155  }
156  g.redistribute();
157  }
158 
163  float getUnbalance()
164  {
165  long t_cost = getProcessorLoad();
166 
167  long min, max, sum;
168  float unbalance;
169 
170  min = t_cost;
171  max = t_cost;
172  sum = t_cost;
173 
174  v_cl.min(min);
175  v_cl.max(max);
176  v_cl.sum(sum);
177  v_cl.execute();
178 
179  unbalance = ((float) (max - min)) / (float) (sum / v_cl.getProcessingUnits());
180 
181  return unbalance * 100;
182  }
183 
190  void getSubSubDomainPosition(size_t id, T (&pos)[dim])
191  {
192 #ifdef SE_CLASS1
193  if (id >= g.getNVertex())
194  std::cerr << __FILE__ << ":" << __LINE__ << " Position - Such vertex doesn't exist (id = " << id << ", " << "total size = " << g.getNVertex() << ")\n";
195 #endif
196 
197  pos[0] = g.vertex(id).template get<nm_v_x>()[0];
198  pos[1] = g.vertex(id).template get<nm_v_x>()[1];
199  if (dim == 3)
200  pos[2] = g.vertex(id).template get<nm_v_x>()[2];
201  }
202 
209  inline void setComputationCost(size_t id, size_t weight)
210  {
211  verticesGotWeights = true;
212 #ifdef SE_CLASS1
213  if (id >= g.getNVertex())
214  std::cerr << __FILE__ << ":" << __LINE__ << "Weight - Such vertex doesn't exist (id = " << id << ", " << "total size = " << g.getNVertex() << ")\n";
215 #endif
216 
217  // If the vertex is inside this processor update the value
218  g.vertex(id).template get<nm_v_computation>() = weight;
219 
220  }
221 
227  {
228  return verticesGotWeights;
229  }
230 
238  size_t getVertexWeight(size_t id)
239  {
240 #ifdef SE_CLASS1
241  if (id >= g.getNVertex())
242  std::cerr << __FILE__ << ":" << __LINE__ << "Such vertex doesn't exist (id = " << id << ", " << "total size = " << g.getTotNVertex() << ")\n";
243 #endif
244 
245  return g.vertex(id).template get<nm_v_computation>();
246  }
247 
253  {
254  size_t load = 0;
255 
256  for (size_t i = 0; i < g.getNVertex(); i++)
257  {
258  load += g.vertex(i).template get<nm_v_computation>();
259  }
260  return load;
261  }
262 
268  size_t getTotalMovedV()
269  {
270  return g_moved;
271  }
272 
278  size_t getMaxMovedV()
279  {
280  return m_moved;
281  }
282 
288  void setMigrationCost(size_t id, size_t migration)
289  {
290 #ifdef SE_CLASS1
291  if (id >= g.getNVertex())
292  std::cerr << __FILE__ << ":" << __LINE__ << "Migration - Such vertex doesn't exist (id = " << id << ", " << "total size = " << g.getNVertex() << ")\n";
293 #endif
294 
295  g.vertex(id).template get<nm_v_migration>() = migration;
296  }
297 
304  void setCommunicationCost(size_t v_id, size_t e, size_t communication)
305  {
306  g.getChildEdge(v_id, e).template get<nm_e::communication>() = communication;
307  }
308 
315  {
316  return g.getNVertex();
317  }
318 
326  size_t getNSubSubDomainNeighbors(size_t id)
327  {
328  if (id >= g.getNVertex())
329  std::cerr << "Neighbors - Such vertex doesn't exist (id = " << id << ", " << "total size = " << g.getNVertex() << ")\n";
330 
331  return g.getNChilds(id);
332  }
333 
339  void write(const std::string & file)
340  {
341  VTKWriter<DistGraph_CSR<nm_v<dim>, nm_e>, DIST_GRAPH> gv2(g);
342  gv2.write(std::to_string(file + ".vtk"));
343  }
344 
353  {
354  gr = dist.gr;
355  domain = dist.domain;
356  g = dist.g;
357  vtxdist = dist.vtxdist;
358  partitions = dist.partitions;
359  v_per_proc = dist.v_per_proc;
360  verticesGotWeights = dist.verticesGotWeights;
361 
362  return *this;
363  }
364 
373  {
374  gr = dist.gr;
375  domain = dist.domain;
376  g.swap(dist.g);
377  vtxdist.swap(dist.vtxdist);
378  partitions.swap(dist.partitions);
379  v_per_proc.swap(dist.v_per_proc);
380  verticesGotWeights = dist.verticesGotWeights;
381 
382  return *this;
383  }
384 }
385 ;
386 
387 #endif /* SRC_DECOMPOSITION_PARMETISDISTRIBUTION_HPP_ */
This class represent an N-dimensional box.
Definition: Box.hpp:60
This class construct a cartesian graph.
Structure that store a graph in CSR format or basically in compressed adjacency matrix format.
size_t getNVertex() const
Return the number of the vertices in this subgraph.
void swap(DistGraph_CSR< V, E > &g)
Swap the memory of g with this graph.
size_t getTotNVertex() const
Return the total number of the vertices.
void q_move(size_t i, size_t t)
Prepare to send vertex i from the local processor to the target processor.
size_t nodeById(size_t id) const
operator to access the vertex position index by id property
void redistribute()
Redistribute function that wraps different stages of the redistribution.
void getDecompositionVector(openfpm::vector< idx_t > &v)
Operator to access the decomposition vector.
size_t getNChilds(size_t c) const
Return the number of children of a vertex.
size_t firstId() const
size_t lastId() const
auto vertex(size_t id) -> decltype(v.get(id))
Function to access the vertexes.
auto getChildEdge(size_t v, size_t v_e) -> decltype(e.get(0))
Get the vertex edge.
void getSubSubDomainPosition(size_t id, T(&pos)[dim])
function that return the position of the vertex in the space
size_t getProcessorLoad()
Compute the processor load counting the total weights of its vertices.
DistGraph_CSR< nm_v< dim >, nm_e > & getGraph()
Get the current graph (main)
Box< dim, T > domain
rectangular domain to decompose
void write(const std::string &file)
Print current graph and save it to file.
void refine()
Refine current decomposition.
size_t getTotalMovedV()
return number of moved vertices in all iterations so far
bool verticesGotWeights
Flag to check if weights are used on vertices.
void decompose()
Create first decomposition, it divides the graph in slices and give each slice to a processor.
bool weightsAreUsed()
Checks if weights are used on the vertices.
DistParMetisDistribution(Vcluster<> &v_cl)
openfpm::vector< openfpm::vector< idx_t > > partitions
partitions
void createCartGraph(grid_sm< dim, void > &grid, Box< dim, T > dom)
Initialize the distribution graph.
float getUnbalance()
Compute the unbalance value.
DistGraph_CSR< nm_v< dim >, nm_e > g
Processor sub-sub-domain graph.
void setMigrationCost(size_t id, size_t migration)
Set migration cost of the vertex id.
const DistParMetisDistribution< dim, T > & operator=(DistParMetisDistribution< dim, T > &&dist)
copy operator
size_t getVertexWeight(size_t id)
function that get the weight of the vertex
void setComputationCost(size_t id, size_t weight)
Function that set the weight of the vertex.
openfpm::vector< idx_t > vtxdist
Init vtxdist needed for Parmetis.
size_t getMaxMovedV()
return number of moved vertices in all iterations so far
const DistParMetisDistribution< dim, T > & operator=(const DistParMetisDistribution< dim, T > &dist)
copy operator
openfpm::vector< openfpm::vector< size_t > > v_per_proc
Init data structure to keep trace of new vertices distribution in processors (needed to update main g...
size_t getNSubSubDomainNeighbors(size_t id)
Returns total number of neighbors of the sub-sub-domain id.
size_t g_moved
Number of moved vertices in all iterations.
void setCommunicationCost(size_t v_id, size_t e, size_t communication)
Set communication cost of the edge id.
size_t getNSubSubDomains()
Returns total number of sub-sub-domains in the distribution graph.
grid_sm< dim, void > gr
Structure that store the cartesian grid information.
size_t m_moved
Max number of moved vertices in all iterations.
static void * message_receive(size_t msg_i, size_t total_msg, size_t total_p, size_t i, size_t ri, void *ptr)
Callback of the sendrecv to set the size of the array received.
DistParmetis< DistGraph_CSR< nm_v< dim >, nm_e > > parmetis_graph
Convert the graph to parmetis format.
Helper class to define Metis graph.
idx_t * getPartition()
Get graph partition vector.
void initSubGraph(Graph &sub_g)
Set the Sub-graph.
void reset(Graph &sub_g)
Reset graph and reconstruct it.
void execute()
Execute all the requests.
void sum(T &num)
Sum the numbers across all processors and get the result.
size_t getProcessUnitID()
Get the process unit id.
void min(T &num)
Get the minimum number across all processors (or reduction with insinity norm)
size_t getProcessingUnits()
Get the total number of processors.
void max(T &num)
Get the maximum number across all processors (or reduction with infinity norm)
Implementation of VCluster class.
Definition: VCluster.hpp:59
__device__ __host__ const size_t(& getSize() const)[N]
Return the size of the grid as an array.
Definition: grid_sm.hpp:760
sub-domain edge graph node
It model an expression expr1 + ... exprn.
Definition: sum.hpp:93