Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
GenericPartitioners.h
Go to the documentation of this file.
1 #ifndef _GALOIS_DIST_GENERICPARTS_H
2 #define _GALOIS_DIST_GENERICPARTS_H
3 
4 #include "DistributedGraph.h"
5 #include "BasePolicies.h"
6 #include <utility>
7 #include <cmath>
8 #include <limits>
9 
11 public:
12  NoCommunication(uint32_t, uint32_t numHosts, uint64_t, uint64_t)
13  : galois::graphs::ReadMasterAssignment(0, numHosts, 0, 0) {}
14 
15  uint32_t getEdgeOwner(uint32_t src, uint32_t, uint64_t) const {
16  return retrieveMaster(src);
17  }
18 
19  bool noCommunication() { return true; }
20  bool isVertexCut() const { return false; }
21  void serializePartition(boost::archive::binary_oarchive&) {}
22  void deserializePartition(boost::archive::binary_iarchive&) {}
23  std::pair<unsigned, unsigned> cartesianGrid() {
24  return std::make_pair(0u, 0u);
25  }
26 };
27 
31 public:
32  MiningPolicyNaive(uint32_t, uint32_t numHosts, uint64_t, uint64_t,
33  std::vector<uint64_t>&)
34  : galois::graphs::ReadMasterAssignment(0, numHosts, 0, 0) {}
35 
36  static bool needNodeDegrees() { return false; }
37 
38  bool keepEdge(uint32_t src, uint32_t dst) const { return src < dst; }
39 };
40 
42  std::vector<uint64_t>& ndegrees;
43 
44 public:
45  MiningPolicyDegrees(uint32_t, uint32_t numHosts, uint64_t, uint64_t,
46  std::vector<uint64_t>& _ndeg)
47  : galois::graphs::ReadMasterAssignment(0, numHosts, 0, 0),
48  ndegrees(_ndeg) {}
49 
50  static bool needNodeDegrees() { return true; }
51 
52  bool keepEdge(uint32_t src, uint32_t dst) const {
53  uint64_t sourceDegree = ndegrees[src];
54  uint64_t destDegree = ndegrees[dst];
55  if ((destDegree > sourceDegree) ||
56  ((destDegree == sourceDegree) && (src < dst))) {
57  return true;
58  } else {
59  return false;
60  }
61  }
62 };
63 
65 
67  unsigned numRowHosts;
68  unsigned numColumnHosts;
69  unsigned _h_offset;
70 
71  void factorizeHosts() {
72  numColumnHosts = sqrt(_numHosts);
73 
74  while ((_numHosts % numColumnHosts) != 0)
75  numColumnHosts--;
76 
77  numRowHosts = _numHosts / numColumnHosts;
78  assert(numRowHosts >= numColumnHosts);
79 
80  // if (moreColumnHosts) {
81  // std::swap(numRowHosts, numColumnHosts);
82  //}
83 
84  if (_hostID == 0) {
85  galois::gPrint("Cartesian grid: ", numRowHosts, " x ", numColumnHosts,
86  "\n");
87  }
88  }
89 
91  unsigned gridRowID() const { return (_hostID / numColumnHosts); }
93  unsigned gridRowID(unsigned id) const { return (id / numColumnHosts); }
95  unsigned gridColumnID() const { return (_hostID % numColumnHosts); }
97  unsigned gridColumnID(unsigned id) const { return (id % numColumnHosts); }
98 
100  unsigned getColumnOfNode(uint64_t gid) const {
101  return gridColumnID(retrieveMaster(gid));
102  }
103 
104 public:
105  GenericCVC(uint32_t hostID, uint32_t numHosts, uint64_t numNodes,
106  uint64_t numEdges)
107  : galois::graphs::ReadMasterAssignment(hostID, numHosts, numNodes,
108  numEdges) {
109  factorizeHosts();
110  _h_offset = gridRowID() * numColumnHosts;
111  }
112 
113  uint32_t getEdgeOwner(uint32_t, uint32_t dst, uint64_t) const {
114  int i = getColumnOfNode(dst);
115  return _h_offset + i;
116  }
117 
118  bool noCommunication() { return false; }
119  bool isVertexCut() const {
120  if ((numRowHosts == 1) || (numColumnHosts == 1))
121  return false;
122  return true;
123  }
124  void serializePartition(boost::archive::binary_oarchive& ar) {
125  ar << numRowHosts;
126  ar << numColumnHosts;
127  }
128  void deserializePartition(boost::archive::binary_iarchive& ar) {
129  ar >> numRowHosts;
130  ar >> numColumnHosts;
131  }
132 
133  std::pair<unsigned, unsigned> cartesianGrid() {
134  return std::make_pair(numRowHosts, numColumnHosts);
135  }
136 };
137 
139 
140 // same as above, except columns are flipped (changes behavior of vertex cut
141 // call as well)
143  unsigned numRowHosts;
144  unsigned numColumnHosts;
145  unsigned _h_offset;
146 
147  void factorizeHosts() {
148  numColumnHosts = sqrt(_numHosts);
149 
150  while ((_numHosts % numColumnHosts) != 0)
151  numColumnHosts--;
152 
153  numRowHosts = _numHosts / numColumnHosts;
154  assert(numRowHosts >= numColumnHosts);
155 
156  // column flip
157  std::swap(numRowHosts, numColumnHosts);
158 
159  if (_hostID == 0) {
160  galois::gPrint("Cartesian grid: ", numRowHosts, " x ", numColumnHosts,
161  "\n");
162  }
163  }
164 
166  unsigned gridRowID() const { return (_hostID / numColumnHosts); }
168  unsigned gridRowID(unsigned id) const { return (id / numColumnHosts); }
170  unsigned gridColumnID() const { return (_hostID % numColumnHosts); }
172  unsigned gridColumnID(unsigned id) const { return (id % numColumnHosts); }
173 
175  unsigned getColumnOfNode(uint64_t gid) const {
176  return gridColumnID(retrieveMaster(gid));
177  }
178 
179 public:
180  GenericCVCColumnFlip(uint32_t hostID, uint32_t numHosts, uint64_t numNodes,
181  uint64_t numEdges)
182  : galois::graphs::ReadMasterAssignment(hostID, numHosts, numNodes,
183  numEdges) {
184  factorizeHosts();
185  _h_offset = gridRowID() * numColumnHosts;
186  }
187 
188  uint32_t getEdgeOwner(uint32_t, uint32_t dst, uint64_t) const {
189  int i = getColumnOfNode(dst);
190  return _h_offset + i;
191  }
192 
193  bool noCommunication() { return false; }
194  bool isVertexCut() const {
195  if ((numRowHosts == 1) && (numColumnHosts == 1))
196  return false;
197  return true;
198  }
199 
200  void serializePartition(boost::archive::binary_oarchive& ar) {
201  ar << numRowHosts;
202  ar << numColumnHosts;
203  }
204 
205  void deserializePartition(boost::archive::binary_iarchive& ar) {
206  ar >> numRowHosts;
207  ar >> numColumnHosts;
208  }
209 
210  std::pair<unsigned, unsigned> cartesianGrid() {
211  return std::make_pair(numRowHosts, numColumnHosts);
212  }
213 };
216  uint32_t _vCutThreshold;
217 
218 public:
219  GenericHVC(uint32_t hostID, uint32_t numHosts, uint64_t numNodes,
220  uint64_t numEdges)
221  : galois::graphs::ReadMasterAssignment(hostID, numHosts, numNodes,
222  numEdges) {
223  _vCutThreshold = 1000; // can be changed, but default seems to be 1000
224  }
225 
226  uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t numEdges) const {
227  if (numEdges > _vCutThreshold) {
228  return retrieveMaster(dst);
229  } else {
230  return retrieveMaster(src);
231  }
232  }
233 
234  bool noCommunication() { return false; }
235  // TODO I should be able to make this runtime detectable
236  bool isVertexCut() const { return true; }
237  void serializePartition(boost::archive::binary_oarchive&) {}
238  void deserializePartition(boost::archive::binary_iarchive&) {}
239  std::pair<unsigned, unsigned> cartesianGrid() {
240  return std::make_pair(0u, 0u);
241  }
242 };
243 
245 
247  // used in hybrid cut
248  uint32_t _vCutThreshold;
249  // ginger scoring constants
250  double _gamma;
251  double _alpha;
252  // ginger node/edge ratio
253  double _neRatio;
254 
258  double getCompositeBalanceParam(
259  unsigned host, const std::vector<uint64_t>& nodeLoads,
260  const std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
261  const std::vector<uint64_t>& edgeLoads,
262  const std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
263  // get node/edge loads
264  uint64_t hostNodeLoad = nodeLoads[host] + nodeAccum[host].load();
265  uint64_t hostEdgeLoad = edgeLoads[host] + edgeAccum[host].load();
266 
267  return (hostNodeLoad + (_neRatio * hostEdgeLoad)) / 2;
268  }
269 
274  double getFennelBalanceScore(double param) {
275  return _alpha * _gamma * pow(param, _gamma - 1);
276  }
277 
278 public:
279  GingerP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes,
280  uint64_t numEdges)
281  : galois::graphs::CustomMasterAssignment(hostID, numHosts, numNodes,
282  numEdges) {
283  _vCutThreshold = 1000;
284  _gamma = 1.5;
285  _alpha = numEdges * pow(numHosts, _gamma - 1.0) / pow(numNodes, _gamma);
286  _neRatio = (double)numNodes / (double)numEdges;
287  }
288 
289  template <typename EdgeTy>
290  uint32_t getMaster(uint32_t src,
292  const std::vector<uint32_t>& localNodeToMaster,
293  std::unordered_map<uint64_t, uint32_t>& gid2offsets,
294  const std::vector<uint64_t>& nodeLoads,
295  std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
296  const std::vector<uint64_t>& edgeLoads,
297  std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
298  auto ii = bufGraph.edgeBegin(src);
299  auto ee = bufGraph.edgeEnd(src);
300  // number of edges
301  uint64_t ne = std::distance(ii, ee);
302 
303  // high in-degree nodes masters stay the same
304  if (ne > _vCutThreshold) {
305  return _hostID;
306  } else {
307  // low in degree masters move based on augmented FENNEL scoring metric
308  // initialize array to hold scores
310  scores.resize(_numHosts);
311  for (unsigned i = 0; i < _numHosts; i++) {
312  scores[i] = 0.0;
313  }
314 
315  for (; ii < ee; ++ii) {
316  uint64_t dst = bufGraph.edgeDestination(*ii);
317  size_t offsetIntoMap = (unsigned)-1;
318 
319  auto it = gid2offsets.find(dst);
320  if (it != gid2offsets.end()) {
321  offsetIntoMap = it->second;
322  } else {
323  // determine offset
324  offsetIntoMap = dst - bufGraph.getNodeOffset();
325  }
326 
327  assert(offsetIntoMap != (unsigned)-1);
328  assert(offsetIntoMap < localNodeToMaster.size());
329 
330  unsigned currentAssignment = localNodeToMaster[offsetIntoMap];
331 
332  if (currentAssignment != (unsigned)-1) {
333  scores[currentAssignment] += 1.0;
334  } else {
335  galois::gDebug("[", _hostID, "] ", dst, " unassigned");
336  }
337  }
338 
339  // subtraction of the composite balance term
340  for (unsigned i = 0; i < _numHosts; i++) {
341  scores[i] -= getFennelBalanceScore(getCompositeBalanceParam(
342  i, nodeLoads, nodeAccum, edgeLoads, edgeAccum));
343  }
344 
345  unsigned bestHost = -1;
346  double bestScore = std::numeric_limits<double>::lowest();
347  // find max score
348  for (unsigned i = 0; i < _numHosts; i++) {
349  if (scores[i] >= bestScore) {
350  // galois::gDebug("best score ", bestScore, " beaten by ", scores[i]);
351  bestScore = scores[i];
352  bestHost = i;
353  }
354  }
355 
356  galois::gDebug("[", _hostID, "] ", src, " assigned to ", bestHost,
357  " with num edge ", ne);
358 
359  // update metadata; TODO make this a nicer interface
360  galois::atomicAdd(nodeAccum[bestHost], (uint64_t)1);
361  galois::atomicAdd(edgeAccum[bestHost], ne);
362 
363  return bestHost;
364  }
365  }
366 
367  uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t numEdges) const {
368  // if high indegree, then move to source (which is dst), else stay on
369  // dst (which is src)
370  // note "dst" here is actually the source on the actual graph
371  // since we're reading transpose
372  if (numEdges > _vCutThreshold) {
373  return retrieveMaster(dst);
374  } else {
375  return retrieveMaster(src);
376  }
377  }
378 
379  bool noCommunication() { return false; }
380  // TODO I should be able to make this runtime detectable
381  bool isVertexCut() const { return true; }
382  void serializePartition(boost::archive::binary_oarchive&) {}
383  void deserializePartition(boost::archive::binary_iarchive&) {}
384  std::pair<unsigned, unsigned> cartesianGrid() {
385  return std::make_pair(0u, 0u);
386  }
387 };
388 
390  // used in hybrid cut
391  uint32_t _vCutThreshold;
392  // ginger scoring constants
393  double _gamma;
394  double _alpha;
395  // ginger node/edge ratio
396  double _neRatio;
397 
401  double getCompositeBalanceParam(
402  unsigned host, const std::vector<uint64_t>& nodeLoads,
403  const std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
404  const std::vector<uint64_t>& edgeLoads,
405  const std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
406  // get node/edge loads
407  uint64_t hostNodeLoad = nodeLoads[host] + nodeAccum[host].load();
408  uint64_t hostEdgeLoad = edgeLoads[host] + edgeAccum[host].load();
409 
410  return (hostNodeLoad + (_neRatio * hostEdgeLoad)) / 2;
411  }
412 
417  double getFennelBalanceScore(double param) {
418  return _alpha * _gamma * pow(param, _gamma - 1);
419  }
420 
421 public:
422  FennelP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes,
423  uint64_t numEdges)
424  : galois::graphs::CustomMasterAssignment(hostID, numHosts, numNodes,
425  numEdges) {
426  _vCutThreshold = 1000;
427  _gamma = 1.5;
428  _alpha = numEdges * pow(numHosts, _gamma - 1.0) / pow(numNodes, _gamma);
429  _neRatio = (double)numNodes / (double)numEdges;
430  }
431 
432  template <typename EdgeTy>
433  uint32_t getMaster(uint32_t src,
435  const std::vector<uint32_t>& localNodeToMaster,
436  std::unordered_map<uint64_t, uint32_t>& gid2offsets,
437  const std::vector<uint64_t>& nodeLoads,
438  std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
439  const std::vector<uint64_t>& edgeLoads,
440  std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
441  auto ii = bufGraph.edgeBegin(src);
442  auto ee = bufGraph.edgeEnd(src);
443  // number of edges
444  uint64_t ne = std::distance(ii, ee);
445 
446  // high degree nodes masters stay the same
447  if (ne > _vCutThreshold) {
448  return _hostID;
449  } else {
450  // low degree masters move based on augmented FENNEL scoring metric
451  // initialize array to hold scores
453  scores.resize(_numHosts);
454  for (unsigned i = 0; i < _numHosts; i++) {
455  scores[i] = 0.0;
456  }
457 
458  for (; ii < ee; ++ii) {
459  uint64_t dst = bufGraph.edgeDestination(*ii);
460  size_t offsetIntoMap = (unsigned)-1;
461 
462  auto it = gid2offsets.find(dst);
463  if (it != gid2offsets.end()) {
464  offsetIntoMap = it->second;
465  } else {
466  // determine offset
467  offsetIntoMap = dst - bufGraph.getNodeOffset();
468  }
469 
470  assert(offsetIntoMap != (unsigned)-1);
471  assert(offsetIntoMap < localNodeToMaster.size());
472 
473  unsigned currentAssignment = localNodeToMaster[offsetIntoMap];
474 
475  if (currentAssignment != (unsigned)-1) {
476  scores[currentAssignment] += 1.0;
477  } else {
478  galois::gDebug("[", _hostID, "] ", dst, " unassigned");
479  }
480  }
481 
482  // subtraction of the composite balance term
483  for (unsigned i = 0; i < _numHosts; i++) {
484  scores[i] -= getFennelBalanceScore(getCompositeBalanceParam(
485  i, nodeLoads, nodeAccum, edgeLoads, edgeAccum));
486  }
487 
488  unsigned bestHost = -1;
489  double bestScore = std::numeric_limits<double>::lowest();
490  // find max score
491  for (unsigned i = 0; i < _numHosts; i++) {
492  if (scores[i] >= bestScore) {
493  // galois::gDebug("best score ", bestScore, " beaten by ", scores[i]);
494  bestScore = scores[i];
495  bestHost = i;
496  }
497  }
498 
499  galois::gDebug("[", _hostID, "] ", src, " assigned to ", bestHost,
500  " with num edge ", ne);
501 
502  // update metadata; TODO make this a nicer interface
503  galois::atomicAdd(nodeAccum[bestHost], (uint64_t)1);
504  galois::atomicAdd(edgeAccum[bestHost], ne);
505 
506  return bestHost;
507  }
508  }
509 
510  // Fennel is an edge cut: all edges on source
511  uint32_t getEdgeOwner(uint32_t src, uint32_t, uint64_t) const {
512  return retrieveMaster(src);
513  }
514 
515  bool noCommunication() { return false; }
516  // TODO I should be able to make this runtime detectable
517  bool isVertexCut() const { return false; }
518  void serializePartition(boost::archive::binary_oarchive&) {}
519  void deserializePartition(boost::archive::binary_iarchive&) {}
520  std::pair<unsigned, unsigned> cartesianGrid() {
521  return std::make_pair(0u, 0u);
522  }
523 };
524 
526  // used in hybrid cut
527  uint32_t _vCutThreshold;
528  // ginger scoring constants
529  double _gamma;
530  double _alpha;
531  // ginger node/edge ratio
532  double _neRatio;
533 
534  unsigned numRowHosts;
535  unsigned numColumnHosts;
536 
537  void factorizeHosts() {
538  numColumnHosts = sqrt(_numHosts);
539 
540  while ((_numHosts % numColumnHosts) != 0)
541  numColumnHosts--;
542 
543  numRowHosts = _numHosts / numColumnHosts;
544  assert(numRowHosts >= numColumnHosts);
545 
546  if (_hostID == 0) {
547  galois::gPrint("Cartesian grid: ", numRowHosts, " x ", numColumnHosts,
548  "\n");
549  }
550  }
551 
553  unsigned gridRowID() const { return (_hostID / numColumnHosts); }
555  unsigned gridRowID(unsigned id) const { return (id / numColumnHosts); }
557  unsigned gridColumnID() const { return (_hostID % numColumnHosts); }
559  unsigned gridColumnID(unsigned id) const { return (id % numColumnHosts); }
560 
562  unsigned getRowOfNode(uint64_t gid) const {
563  return gridRowID(retrieveMaster(gid));
564  }
565 
567  unsigned getColumnOfNode(uint64_t gid) const {
568  return gridColumnID(retrieveMaster(gid));
569  }
570 
574  double getCompositeBalanceParam(
575  unsigned host, const std::vector<uint64_t>& nodeLoads,
576  const std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
577  const std::vector<uint64_t>& edgeLoads,
578  const std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
579  // get node/edge loads
580  uint64_t hostNodeLoad = nodeLoads[host] + nodeAccum[host].load();
581  uint64_t hostEdgeLoad = edgeLoads[host] + edgeAccum[host].load();
582 
583  return (hostNodeLoad + (_neRatio * hostEdgeLoad)) / 2;
584  }
585 
590  double getFennelBalanceScore(double param) {
591  return _alpha * _gamma * pow(param, _gamma - 1);
592  }
593 
594 public:
595  SugarP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes,
596  uint64_t numEdges)
597  : galois::graphs::CustomMasterAssignment(hostID, numHosts, numNodes,
598  numEdges) {
599  _vCutThreshold = 1000;
600  _gamma = 1.5;
601  _alpha = numEdges * pow(numHosts, _gamma - 1.0) / pow(numNodes, _gamma);
602  _neRatio = (double)numNodes / (double)numEdges;
603  // CVC things
604  factorizeHosts();
605  }
606 
607  template <typename EdgeTy>
608  uint32_t getMaster(uint32_t src,
610  const std::vector<uint32_t>& localNodeToMaster,
611  std::unordered_map<uint64_t, uint32_t>& gid2offsets,
612  const std::vector<uint64_t>& nodeLoads,
613  std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
614  const std::vector<uint64_t>& edgeLoads,
615  std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
616  auto ii = bufGraph.edgeBegin(src);
617  auto ee = bufGraph.edgeEnd(src);
618  // number of edges
619  uint64_t ne = std::distance(ii, ee);
620 
621  // high degree nodes masters stay the same
622  if (ne > _vCutThreshold) {
623  return _hostID;
624  } else {
625  // low degree masters move based on augmented FENNEL scoring metric
626  // initialize array to hold scores
628  scores.resize(_numHosts);
629  for (unsigned i = 0; i < _numHosts; i++) {
630  scores[i] = 0.0;
631  }
632 
633  for (; ii < ee; ++ii) {
634  uint64_t dst = bufGraph.edgeDestination(*ii);
635  size_t offsetIntoMap = (unsigned)-1;
636 
637  auto it = gid2offsets.find(dst);
638  if (it != gid2offsets.end()) {
639  offsetIntoMap = it->second;
640  } else {
641  // determine offset
642  offsetIntoMap = dst - bufGraph.getNodeOffset();
643  }
644 
645  assert(offsetIntoMap != (unsigned)-1);
646  assert(offsetIntoMap < localNodeToMaster.size());
647 
648  unsigned currentAssignment = localNodeToMaster[offsetIntoMap];
649 
650  if (currentAssignment != (unsigned)-1) {
651  scores[currentAssignment] += 1.0;
652  } else {
653  // galois::gDebug("[", _hostID, "] ", dst, " unassigned");
654  }
655  }
656 
657  // subtraction of the composite balance term
658  for (unsigned i = 0; i < _numHosts; i++) {
659  scores[i] -= getFennelBalanceScore(getCompositeBalanceParam(
660  i, nodeLoads, nodeAccum, edgeLoads, edgeAccum));
661  }
662 
663  unsigned bestHost = -1;
664  double bestScore = std::numeric_limits<double>::lowest();
665  // find max score
666  for (unsigned i = 0; i < _numHosts; i++) {
667  if (scores[i] >= bestScore) {
668  // galois::gDebug("best score ", bestScore, " beaten by ", scores[i]);
669  bestScore = scores[i];
670  bestHost = i;
671  }
672  }
673 
674  galois::gDebug("[", _hostID, "] ", src, " assigned to ", bestHost,
675  " with num edge ", ne);
676 
677  // update metadata; TODO make this a nicer interface
678  galois::atomicAdd(nodeAccum[bestHost], (uint64_t)1);
679  galois::atomicAdd(edgeAccum[bestHost], ne);
680 
681  return bestHost;
682  }
683  }
684 
688  uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t) const {
689  unsigned blockedRowOffset = getRowOfNode(src) * numColumnHosts;
690  unsigned cyclicColumnOffset = getColumnOfNode(dst);
691  return blockedRowOffset + cyclicColumnOffset;
692  }
693 
694  bool noCommunication() { return false; }
695  bool isVertexCut() const {
696  if ((numRowHosts == 1) || (numColumnHosts == 1))
697  return false;
698  return true;
699  }
700 
701  void serializePartition(boost::archive::binary_oarchive& ar) {
702  ar << numRowHosts;
703  ar << numColumnHosts;
704  }
705 
706  void deserializePartition(boost::archive::binary_iarchive& ar) {
707  ar >> numRowHosts;
708  ar >> numColumnHosts;
709  }
710 
711  std::pair<unsigned, unsigned> cartesianGrid() {
712  return std::make_pair(numRowHosts, numColumnHosts);
713  }
714 };
715 
717  // used in hybrid cut
718  uint32_t _vCutThreshold;
719  // ginger scoring constants
720  double _gamma;
721  double _alpha;
722  // ginger node/edge ratio
723  double _neRatio;
724 
725  unsigned numRowHosts;
726  unsigned numColumnHosts;
727 
728  void factorizeHosts() {
729  numColumnHosts = sqrt(_numHosts);
730 
731  while ((_numHosts % numColumnHosts) != 0)
732  numColumnHosts--;
733 
734  numRowHosts = _numHosts / numColumnHosts;
735  assert(numRowHosts >= numColumnHosts);
736 
737  // column flip
738  std::swap(numRowHosts, numColumnHosts);
739 
740  if (_hostID == 0) {
741  galois::gPrint("Cartesian grid: ", numRowHosts, " x ", numColumnHosts,
742  "\n");
743  }
744  }
745 
747  unsigned gridRowID() const { return (_hostID / numColumnHosts); }
749  unsigned gridRowID(unsigned id) const { return (id / numColumnHosts); }
751  unsigned gridColumnID() const { return (_hostID % numColumnHosts); }
753  unsigned gridColumnID(unsigned id) const { return (id % numColumnHosts); }
754 
756  unsigned getRowOfNode(uint64_t gid) const {
757  return gridRowID(retrieveMaster(gid));
758  }
759 
761  unsigned getColumnOfNode(uint64_t gid) const {
762  return gridColumnID(retrieveMaster(gid));
763  }
764 
768  double getCompositeBalanceParam(
769  unsigned host, const std::vector<uint64_t>& nodeLoads,
770  const std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
771  const std::vector<uint64_t>& edgeLoads,
772  const std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
773  // get node/edge loads
774  uint64_t hostNodeLoad = nodeLoads[host] + nodeAccum[host].load();
775  uint64_t hostEdgeLoad = edgeLoads[host] + edgeAccum[host].load();
776 
777  return (hostNodeLoad + (_neRatio * hostEdgeLoad)) / 2;
778  }
779 
784  double getFennelBalanceScore(double param) {
785  return _alpha * _gamma * pow(param, _gamma - 1);
786  }
787 
788 public:
789  SugarColumnFlipP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes,
790  uint64_t numEdges)
791  : galois::graphs::CustomMasterAssignment(hostID, numHosts, numNodes,
792  numEdges) {
793  _vCutThreshold = 1000;
794  _gamma = 1.5;
795  _alpha = numEdges * pow(numHosts, _gamma - 1.0) / pow(numNodes, _gamma);
796  _neRatio = (double)numNodes / (double)numEdges;
797  // CVC things
798  factorizeHosts();
799  }
800 
801  template <typename EdgeTy>
802  uint32_t getMaster(uint32_t src,
804  const std::vector<uint32_t>& localNodeToMaster,
805  std::unordered_map<uint64_t, uint32_t>& gid2offsets,
806  const std::vector<uint64_t>& nodeLoads,
807  std::vector<galois::CopyableAtomic<uint64_t>>& nodeAccum,
808  const std::vector<uint64_t>& edgeLoads,
809  std::vector<galois::CopyableAtomic<uint64_t>>& edgeAccum) {
810  auto ii = bufGraph.edgeBegin(src);
811  auto ee = bufGraph.edgeEnd(src);
812  // number of edges
813  uint64_t ne = std::distance(ii, ee);
814 
815  // high degree nodes masters stay the same
816  if (ne > _vCutThreshold) {
817  return _hostID;
818  } else {
819  // low degree masters move based on augmented FENNEL scoring metric
820  // initialize array to hold scores
822  scores.resize(_numHosts);
823  for (unsigned i = 0; i < _numHosts; i++) {
824  scores[i] = 0.0;
825  }
826 
827  for (; ii < ee; ++ii) {
828  uint64_t dst = bufGraph.edgeDestination(*ii);
829  size_t offsetIntoMap = (unsigned)-1;
830 
831  auto it = gid2offsets.find(dst);
832  if (it != gid2offsets.end()) {
833  offsetIntoMap = it->second;
834  } else {
835  // determine offset
836  offsetIntoMap = dst - bufGraph.getNodeOffset();
837  }
838 
839  assert(offsetIntoMap != (unsigned)-1);
840  assert(offsetIntoMap < localNodeToMaster.size());
841 
842  unsigned currentAssignment = localNodeToMaster[offsetIntoMap];
843 
844  if (currentAssignment != (unsigned)-1) {
845  scores[currentAssignment] += 1.0;
846  } else {
847  galois::gDebug("[", _hostID, "] ", dst, " unassigned");
848  }
849  }
850 
851  // subtraction of the composite balance term
852  for (unsigned i = 0; i < _numHosts; i++) {
853  scores[i] -= getFennelBalanceScore(getCompositeBalanceParam(
854  i, nodeLoads, nodeAccum, edgeLoads, edgeAccum));
855  }
856 
857  unsigned bestHost = -1;
858  double bestScore = std::numeric_limits<double>::lowest();
859  // find max score
860  for (unsigned i = 0; i < _numHosts; i++) {
861  if (scores[i] >= bestScore) {
862  // galois::gDebug("best score ", bestScore, " beaten by ", scores[i]);
863  bestScore = scores[i];
864  bestHost = i;
865  }
866  }
867 
868  galois::gDebug("[", _hostID, "] ", src, " assigned to ", bestHost,
869  " with num edge ", ne);
870 
871  // update metadata; TODO make this a nicer interface
872  galois::atomicAdd(nodeAccum[bestHost], (uint64_t)1);
873  galois::atomicAdd(edgeAccum[bestHost], ne);
874 
875  return bestHost;
876  }
877  }
878 
882  uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t) const {
883  unsigned blockedRowOffset = getRowOfNode(src) * numColumnHosts;
884  unsigned cyclicColumnOffset = getColumnOfNode(dst);
885  return blockedRowOffset + cyclicColumnOffset;
886  }
887 
888  bool noCommunication() { return false; }
889  bool isVertexCut() const {
890  if ((numRowHosts == 1) && (numColumnHosts == 1))
891  return false;
892  return true;
893  }
894  void serializePartition(boost::archive::binary_oarchive& ar) {
895  ar << numRowHosts;
896  ar << numColumnHosts;
897  }
898  void deserializePartition(boost::archive::binary_iarchive& ar) {
899  ar >> numRowHosts;
900  ar >> numColumnHosts;
901  }
902 
903  std::pair<unsigned, unsigned> cartesianGrid() {
904  return std::make_pair(numRowHosts, numColumnHosts);
905  }
906 };
907 
908 #endif
bool isVertexCut() const
Definition: GenericPartitioners.h:381
EdgeIterator edgeEnd(uint64_t globalNodeID)
Get the index to the first edge of the node after the provided node.
Definition: BufferedGraph.h:414
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:384
bool noCommunication()
Definition: GenericPartitioners.h:118
bool noCommunication()
Definition: GenericPartitioners.h:888
uint32_t getMaster(uint32_t src, galois::graphs::BufferedGraph< EdgeTy > &bufGraph, const std::vector< uint32_t > &localNodeToMaster, std::unordered_map< uint64_t, uint32_t > &gid2offsets, const std::vector< uint64_t > &nodeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &nodeAccum, const std::vector< uint64_t > &edgeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &edgeAccum)
Definition: GenericPartitioners.h:802
uint32_t getEdgeOwner(uint32_t, uint32_t dst, uint64_t) const
Definition: GenericPartitioners.h:113
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:239
uint32_t getMaster(uint32_t src, galois::graphs::BufferedGraph< EdgeTy > &bufGraph, const std::vector< uint32_t > &localNodeToMaster, std::unordered_map< uint64_t, uint32_t > &gid2offsets, const std::vector< uint64_t > &nodeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &nodeAccum, const std::vector< uint64_t > &edgeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &edgeAccum)
Definition: GenericPartitioners.h:290
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:711
uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t) const
return owner of edge using cartesian edge owner determination
Definition: GenericPartitioners.h:882
void deserializePartition(boost::archive::binary_iarchive &)
Definition: GenericPartitioners.h:519
uint32_t _numHosts
total number of hosts
Definition: BasePolicies.h:40
Definition: GenericPartitioners.h:389
Class that loads a portion of a Galois graph from disk directly into memory buffers for access...
Definition: BufferedGraph.h:49
const Ty atomicAdd(std::atomic< Ty > &val, Ty delta)
galois::atomicAdd
Definition: AtomicHelpers.h:89
Policies that use the read assignment of nodes as the masters.
Definition: BasePolicies.h:74
bool noCommunication()
Definition: GenericPartitioners.h:19
void deserializePartition(boost::archive::binary_iarchive &)
Definition: GenericPartitioners.h:383
EdgeIterator edgeBegin(uint64_t globalNodeID)
Get the index to the first edge of the provided node THAT THIS GRAPH HAS LOADED (not necessary the fi...
Definition: BufferedGraph.h:386
bool isVertexCut() const
Definition: GenericPartitioners.h:695
GingerP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Definition: GenericPartitioners.h:279
bool isVertexCut() const
Definition: GenericPartitioners.h:517
void resize(size_t n)
Definition: PODResizeableArray.h:142
void deserializePartition(boost::archive::binary_iarchive &ar)
Definition: GenericPartitioners.h:706
static bool needNodeDegrees()
Definition: GenericPartitioners.h:36
void gDebug(Args &&...GALOIS_USED_ONLY_IN_DEBUG(args))
Prints a debug string from a sequence of things; prints nothing if NDEBUG is defined.
Definition: gIO.h:72
bool keepEdge(uint32_t src, uint32_t dst) const
Definition: GenericPartitioners.h:38
void deserializePartition(boost::archive::binary_iarchive &ar)
Definition: GenericPartitioners.h:898
uint32_t getMaster(uint32_t src, galois::graphs::BufferedGraph< EdgeTy > &bufGraph, const std::vector< uint32_t > &localNodeToMaster, std::unordered_map< uint64_t, uint32_t > &gid2offsets, const std::vector< uint64_t > &nodeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &nodeAccum, const std::vector< uint64_t > &edgeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &edgeAccum)
Definition: GenericPartitioners.h:608
SugarColumnFlipP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Definition: GenericPartitioners.h:789
void serializePartition(boost::archive::binary_oarchive &)
Definition: GenericPartitioners.h:382
uint32_t retrieveMaster(uint32_t gid) const
Retrieves a saved master mapping: does not fail if a GID mapping is not found but instead returns -1 ...
Definition: BasePolicies.h:189
uint32_t getMaster(uint32_t src, galois::graphs::BufferedGraph< EdgeTy > &bufGraph, const std::vector< uint32_t > &localNodeToMaster, std::unordered_map< uint64_t, uint32_t > &gid2offsets, const std::vector< uint64_t > &nodeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &nodeAccum, const std::vector< uint64_t > &edgeLoads, std::vector< galois::CopyableAtomic< uint64_t >> &edgeAccum)
Definition: GenericPartitioners.h:433
uint32_t getEdgeOwner(uint32_t, uint32_t dst, uint64_t) const
Definition: GenericPartitioners.h:188
Class that inherits from std::atomic to make it copyable by defining a copy constructor.
Definition: AtomicWrapper.h:40
bool isVertexCut() const
Definition: GenericPartitioners.h:236
void serializePartition(boost::archive::binary_oarchive &ar)
Definition: GenericPartitioners.h:124
bool keepEdge(uint32_t src, uint32_t dst) const
Definition: GenericPartitioners.h:52
uint32_t _hostID
host ID of owner of this object
Definition: BasePolicies.h:39
uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t numEdges) const
Definition: GenericPartitioners.h:226
NoCommunication(uint32_t, uint32_t numHosts, uint64_t, uint64_t)
Definition: GenericPartitioners.h:12
void deserializePartition(boost::archive::binary_iarchive &)
Definition: GenericPartitioners.h:238
Definition: GenericPartitioners.h:10
uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t numEdges) const
Definition: GenericPartitioners.h:367
Definition: GenericPartitioners.h:246
Definition: GenericPartitioners.h:142
bool noCommunication()
Definition: GenericPartitioners.h:234
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:210
bool noCommunication()
Definition: GenericPartitioners.h:515
uint32_t retrieveMaster(uint32_t gid) const
Returns the host ID of the host that read a particular node and its edges from disk.
Definition: BasePolicies.h:90
void gPrint(Args &&...args)
Prints a sequence of things.
Definition: gIO.h:47
Definition: GenericPartitioners.h:30
void serializePartition(boost::archive::binary_oarchive &ar)
Definition: GenericPartitioners.h:894
uint64_t getNodeOffset() const
Definition: BufferedGraph.h:304
MiningPolicyNaive(uint32_t, uint32_t numHosts, uint64_t, uint64_t, std::vector< uint64_t > &)
Definition: GenericPartitioners.h:32
MiningPolicyDegrees(uint32_t, uint32_t numHosts, uint64_t, uint64_t, std::vector< uint64_t > &_ndeg)
Definition: GenericPartitioners.h:45
void serializePartition(boost::archive::binary_oarchive &ar)
Definition: GenericPartitioners.h:200
CustomMasterAssignment(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Calls parent constructor to initialize common data.
Definition: BasePolicies.h:176
bool isVertexCut() const
Definition: GenericPartitioners.h:20
void serializePartition(boost::archive::binary_oarchive &)
Definition: GenericPartitioners.h:237
Header file that includes the base classes for defining CuSP partitioning policies.
void serializePartition(boost::archive::binary_oarchive &ar)
Definition: GenericPartitioners.h:701
Policies that use a custom assignment of masters (from the user).
Definition: BasePolicies.h:147
SugarP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Definition: GenericPartitioners.h:595
uint32_t getEdgeOwner(uint32_t src, uint32_t, uint64_t) const
Definition: GenericPartitioners.h:15
Contains the implementation for DistGraph.
Definition: GenericPartitioners.h:66
Definition: GenericPartitioners.h:215
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:23
FennelP(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Definition: GenericPartitioners.h:422
uint32_t getEdgeOwner(uint32_t src, uint32_t dst, uint64_t) const
return owner of edge using cartesian edge owner determination
Definition: GenericPartitioners.h:688
Definition: GenericPartitioners.h:716
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:133
void serializePartition(boost::archive::binary_oarchive &)
Definition: GenericPartitioners.h:518
GenericCVC(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Definition: GenericPartitioners.h:105
bool noCommunication()
Definition: GenericPartitioners.h:694
uint32_t getEdgeOwner(uint32_t src, uint32_t, uint64_t) const
Definition: GenericPartitioners.h:511
void deserializePartition(boost::archive::binary_iarchive &)
Definition: GenericPartitioners.h:22
GenericCVCColumnFlip(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Definition: GenericPartitioners.h:180
This is a container that encapsulates a resizeable array of plain-old-datatype (POD) elements...
Definition: PODResizeableArray.h:40
bool isVertexCut() const
Definition: GenericPartitioners.h:194
void deserializePartition(boost::archive::binary_iarchive &ar)
Definition: GenericPartitioners.h:128
bool isVertexCut() const
Definition: GenericPartitioners.h:889
void serializePartition(boost::archive::binary_oarchive &)
Definition: GenericPartitioners.h:21
bool noCommunication()
Definition: GenericPartitioners.h:379
uint64_t edgeDestination(uint64_t globalEdgeID)
Get the global node id of the destination of the provided edge.
Definition: BufferedGraph.h:437
GenericHVC(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Definition: GenericPartitioners.h:219
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:520
void deserializePartition(boost::archive::binary_iarchive &ar)
Definition: GenericPartitioners.h:205
static bool needNodeDegrees()
Definition: GenericPartitioners.h:50
Definition: GenericPartitioners.h:525
Definition: GenericPartitioners.h:41
ReadMasterAssignment(uint32_t hostID, uint32_t numHosts, uint64_t numNodes, uint64_t numEdges)
Constructor simply calls parent constructor.
Definition: BasePolicies.h:79
bool isVertexCut() const
Definition: GenericPartitioners.h:119
std::pair< unsigned, unsigned > cartesianGrid()
Definition: GenericPartitioners.h:903
bool noCommunication()
Definition: GenericPartitioners.h:193