OpenFPM_pdata  1.1.0
Project that contain the implementation of distributed structures
 All Data Structures Namespaces Functions Variables Typedefs Enumerations Friends Pages
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 
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 
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, nm_e>, DIST_GRAPH> gv2(g);
342  gv2.write(std::to_string(file + ".vtk"));
343  }
344 
353  {
354  v_cl = dist.v_cl;
355  gr = dist.gr;
356  domain = dist.domain;
357  g = dist.g;
358  vtxdist = dist.vtxdist;
359  partitions = dist.partitions;
360  v_per_proc = dist.v_per_proc;
362 
363  return *this;
364  }
365 
374  {
375  v_cl = dist.v_cl;
376  gr = dist.gr;
377  domain = dist.domain;
378  g.swap(dist.g);
379  vtxdist.swap(dist.vtxdist);
380  partitions.swap(dist.partitions);
381  v_per_proc.swap(dist.v_per_proc);
382  verticesGotWeights = dist.verticesGotWeights;
383 
384  return *this;
385  }
386 }
387 ;
388 
389 #endif /* SRC_DECOMPOSITION_PARMETISDISTRIBUTION_HPP_ */
void sum(T &num)
Sum the numbers across all processors and get the result.
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 getTotalMovedV()
return number of moved vertices in all iterations so far
void setCommunicationCost(size_t v_id, size_t e, size_t communication)
Set communication cost of the edge id.
DistGraph_CSR< nm_v, nm_e > & getGraph()
Get the current graph (main)
size_t getProcessUnitID()
Get the process unit id.
size_t nodeById(size_t id) const
operator to access the vertex position index by id property
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.
size_t getProcessorLoad()
Compute the processor load counting the total weights of its vertices.
void execute()
Execute all the requests.
size_t getNSubSubDomainNeighbors(size_t id)
Returns total number of neighbors of the sub-sub-domain id.
void getDecompositionVector(openfpm::vector< idx_t > &v)
Operator to access the decomposition vector.
void swap(DistGraph_CSR< V, E > &g)
Swap the memory of g with this graph.
size_t g_moved
Number of moved vertices in all iterations.
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 getVertexWeight(size_t id)
function that get the weight of the vertex
void write(const std::string &file)
Print current graph and save it to file.
auto getChildEdge(size_t v, size_t v_e) -> decltype(e.get(0))
Get the vertex edge.
size_t firstId() const
void max(T &num)
Get the maximum number across all processors (or reduction with infinity norm)
void decompose(Graph &sub_g)
Decompose the graph.
size_t getMaxMovedV()
return number of moved vertices in all iterations so far
Helper class to define Metis graph.
void reset(Graph &sub_g)
Reset graph and reconstruct it.
size_t getNVertex() const
Return the number of the vertices in this subgraph.
Implementation of VCluster class.
Definition: VCluster.hpp:36
size_t lastId() const
grid_sm< dim, void > gr
Structure that store the cartesian grid information.
void getSubSubDomainPosition(size_t id, T(&pos)[dim])
function that return the position of the vertex in the space
void setComputationCost(size_t id, size_t weight)
Function that set the weight of the vertex.
size_t getNSubSubDomains()
Returns total number of sub-sub-domains in the distribution graph.
DistGraph_CSR< nm_v, nm_e > g
Processor sub-sub-domain graph.
const size_t(& getSize() const)[N]
Return the size of the grid as an array.
Definition: grid_sm.hpp:677
Box< dim, T > domain
rectangular domain to decompose
openfpm::vector< openfpm::vector< idx_t > > partitions
partitions
void redistribute()
Redistribute function that wraps different stages of the redistribution.
const DistParMetisDistribution< dim, T > & operator=(const DistParMetisDistribution< dim, T > &dist)
copy operator
size_t m_moved
Max number of moved vertices in all iterations.
This class represent an N-dimensional box.
Definition: Box.hpp:56
idx_t * getPartition()
Get graph partition vector.
DistParmetis< DistGraph_CSR< nm_v, nm_e > > parmetis_graph
Convert the graph to parmetis format.
void refine()
Refine current decomposition.
size_t getNChilds(size_t c) const
Return the number of children of a vertex.
void initSubGraph(Graph &sub_g)
Set the Sub-graph.
This class construct a cartesian graph.
void refine(Graph &sub_g)
Refine the graph.
void setMigrationCost(size_t id, size_t migration)
Set migration cost of the vertex id.
void decompose()
Create first decomposition, it divides the graph in slices and give each slice to a processor...
void min(T &num)
Get the minimum number across all processors (or reduction with insinity norm)
void createCartGraph(grid_sm< dim, void > &grid, Box< dim, T > dom)
Initialize the distribution graph.
It model an expression expr1 + ... exprn.
Definition: sum.hpp:92
openfpm::vector< idx_t > vtxdist
Init vtxdist needed for Parmetis.
static const unsigned int proc_id
proc_id property id in boost::fusion::vector
size_t getProcessingUnits()
Get the total number of processors.
bool weightsAreUsed()
Checks if weights are used on the vertices.
float getUnbalance()
Compute the unbalance value.
const DistParMetisDistribution< dim, T > & operator=(DistParMetisDistribution< dim, T > &&dist)
copy operator
auto vertex(size_t id) -> decltype(v.get(id))
Function to access the vertexes.
bool verticesGotWeights
Flag to check if weights are used on vertices.