Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LC_CSR_Hypergraph.h
Go to the documentation of this file.
1 /*
2  * This file belongs to the Galois project, a C++ library for exploiting
3  * parallelism. The code is being released under the terms of the 3-Clause BSD
4  * License (a copy is located in LICENSE.txt at the top-level directory).
5  *
6  * Copyright (C) 2018, The University of Texas at Austin. All rights reserved.
7  * UNIVERSITY EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES CONCERNING THIS
8  * SOFTWARE AND DOCUMENTATION, INCLUDING ANY WARRANTIES OF MERCHANTABILITY,
9  * FITNESS FOR ANY PARTICULAR PURPOSE, NON-INFRINGEMENT AND WARRANTIES OF
10  * PERFORMANCE, AND ANY WARRANTY THAT MIGHT OTHERWISE ARISE FROM COURSE OF
11  * DEALING OR USAGE OF TRADE. NO WARRANTY IS EITHER EXPRESS OR IMPLIED WITH
12  * RESPECT TO THE USE OF THE SOFTWARE OR DOCUMENTATION. Under no circumstances
13  * shall University be liable for incidental, special, indirect, direct or
14  * consequential damages or loss of profits, interruption of business, or
15  * related expenses which may arise from use of Software or Documentation,
16  * including but not limited to those resulting from defects in Software and/or
17  * Documentation, or loss or inaccuracy of data of any kind.
18  */
19 
20 #ifndef GALOIS_GRAPHS_LC_CSR_HYPERGRAPH_H
21 #define GALOIS_GRAPHS_LC_CSR_HYPERGRAPH_H
22 
23 #include <type_traits>
24 
25 #include <boost/archive/binary_oarchive.hpp>
26 #include <boost/archive/binary_iarchive.hpp>
27 #include <boost/serialization/split_member.hpp>
28 #include <boost/serialization/binary_object.hpp>
29 #include <boost/serialization/serialization.hpp>
30 
31 #include "galois/config.h"
32 #include "galois/Galois.h"
33 #include "galois/graphs/Details.h"
37 
38 namespace galois {
39 namespace graphs {
58 template <typename NodeTy, typename EdgeTy, bool HasNoLockable = false,
60  bool UseNumaAlloc =
61  false, // true => numa-blocked, false => numa-interleaved
62  bool HasOutOfLineLockable = false, typename FileEdgeTy = EdgeTy>
65  private boost::noncopyable,
66  private internal::LocalIteratorFeature<UseNumaAlloc>,
67  private internal::OutOfLineLockableFeature<HasOutOfLineLockable &&
68  !HasNoLockable> {
69  template <typename Graph>
70  friend class LC_InOut_Graph;
71 
72 public:
73  template <bool _has_id>
74  struct with_id {
76  };
77 
78  template <typename _node_data>
79  struct with_node_data {
80  typedef LC_CSR_Hypergraph<_node_data, EdgeTy, HasNoLockable, UseNumaAlloc,
81  HasOutOfLineLockable, FileEdgeTy>
83  };
84 
85  template <typename _edge_data>
86  struct with_edge_data {
87  typedef LC_CSR_Hypergraph<NodeTy, _edge_data, HasNoLockable, UseNumaAlloc,
88  HasOutOfLineLockable, FileEdgeTy>
90  };
91 
92  template <typename _file_edge_data>
94  typedef LC_CSR_Hypergraph<NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc,
95  HasOutOfLineLockable, _file_edge_data>
97  };
98 
100  template <bool _has_no_lockable>
102  typedef LC_CSR_Hypergraph<NodeTy, EdgeTy, _has_no_lockable, UseNumaAlloc,
103  HasOutOfLineLockable, FileEdgeTy>
105  };
106  template <bool _has_no_lockable>
107  using _with_no_lockable =
108  LC_CSR_Hypergraph<NodeTy, EdgeTy, _has_no_lockable, UseNumaAlloc,
109  HasOutOfLineLockable, FileEdgeTy>;
110 
112  template <bool _use_numa_alloc>
114  typedef LC_CSR_Hypergraph<NodeTy, EdgeTy, HasNoLockable, _use_numa_alloc,
115  HasOutOfLineLockable, FileEdgeTy>
117  };
118  template <bool _use_numa_alloc>
119  using _with_numa_alloc =
120  LC_CSR_Hypergraph<NodeTy, EdgeTy, HasNoLockable, _use_numa_alloc,
121  HasOutOfLineLockable, FileEdgeTy>;
122 
124  template <bool _has_out_of_line_lockable>
126  typedef LC_CSR_Hypergraph<NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc,
127  _has_out_of_line_lockable, FileEdgeTy>
129  };
130 
132 
133 protected:
136  typedef internal::NodeInfoBaseTypes<NodeTy,
137  !HasNoLockable && !HasOutOfLineLockable>
139  typedef internal::NodeInfoBase<NodeTy,
140  !HasNoLockable && !HasOutOfLineLockable>
144 
145 public:
146  typedef uint32_t GraphNode;
147  typedef EdgeTy edge_data_type;
148  typedef FileEdgeTy file_edge_data_type;
149  typedef NodeTy node_data_type;
151  typedef typename NodeInfoTypes::reference node_data_reference;
152  using edge_iterator =
153  boost::counting_iterator<typename EdgeIndData::value_type>;
154  using iterator = boost::counting_iterator<typename EdgeDst::value_type>;
158  // for hypergraphs
159  size_t hedges;
160  size_t hnodes;
161 
162 protected:
167 
168  uint64_t numNodes;
169  uint64_t numEdges;
170 
171  typedef internal::EdgeSortIterator<
174 
176  return edge_iterator((N == 0) ? 0 : edgeIndData[N - 1]);
177  }
178 
180  return edge_iterator(edgeIndData[N]);
181  }
182 
185  }
186 
188  return edge_sort_iterator(*raw_end(N), &edgeDst, &edgeData);
189  }
190 
191  template <bool _A1 = HasNoLockable, bool _A2 = HasOutOfLineLockable>
193  typename std::enable_if<!_A1 && !_A2>::type* = 0) {
195  }
196 
197  template <bool _A1 = HasOutOfLineLockable, bool _A2 = HasNoLockable>
199  typename std::enable_if<_A1 && !_A2>::type* = 0) {
200  this->outOfLineAcquire(getId(N), mflag);
201  }
202 
203  template <bool _A1 = HasOutOfLineLockable, bool _A2 = HasNoLockable>
205  typename std::enable_if<_A2>::type* = 0) {}
206 
207  template <bool _A1 = EdgeData::has_value,
210  typename FileGraph::edge_iterator nn,
211  typename std::enable_if<!_A1 || _A2>::type* = 0) {
212  typedef LargeArray<FileEdgeTy> FED;
214  edgeData.set(*nn, graph.getEdgeData<typename FED::value_type>(nn));
215  }
216 
217  template <bool _A1 = EdgeData::has_value,
220  typename std::enable_if<_A1 && !_A2>::type* = 0) {
221  edgeData.set(*nn, {});
222  }
223 
224  size_t getId(GraphNode N) { return N; }
225 
226  GraphNode getNode(size_t n) { return n; }
227 
228 private:
230  template <typename Archive>
231  void save(Archive& ar, const unsigned int) const {
232  ar << numNodes;
233  ar << numEdges;
234 
235  // Large Arrays
236  ar << edgeIndData;
237  ar << edgeDst;
238  ar << edgeData;
239  }
240 
241  template <typename Archive>
242  void load(Archive& ar, const unsigned int) {
243  ar >> numNodes;
244  ar >> numEdges;
245 
246  // Large Arrays
247  ar >> edgeIndData;
248  ar >> edgeDst;
249  ar >> edgeData;
250 
251  if (!nodeData.data()) {
252  if (UseNumaAlloc) {
253  nodeData.allocateBlocked(numNodes);
254  this->outOfLineAllocateBlocked(numNodes);
255  } else {
256  nodeData.allocateInterleaved(numNodes);
257  this->outOfLineAllocateInterleaved(numNodes);
258  }
259 
260  // Construct nodeData largeArray
261  for (size_t n = 0; n < numNodes; ++n) {
263  }
264  }
265  }
266  // The macro BOOST_SERIALIZATION_SPLIT_MEMBER() generates code which invokes
267  // the save or load depending on whether the archive is used for saving or
268  // loading
269  BOOST_SERIALIZATION_SPLIT_MEMBER()
270 
271 public:
272  LC_CSR_Hypergraph(LC_CSR_Hypergraph&& rhs) = default;
273  LC_CSR_Hypergraph() = default;
274  LC_CSR_Hypergraph& operator=(LC_CSR_Hypergraph&&) = default;
275 
281  void serializeNodeData(boost::archive::binary_oarchive& ar) const {
282  ar << nodeData;
283  }
284 
291  void deSerializeNodeData(boost::archive::binary_iarchive& ar) {
292  ar >> nodeData;
293  }
294 
300  void serializeGraph(boost::archive::binary_oarchive& ar) const {
301  ar << numNodes;
302  ar << numEdges;
303 
304  // Large Arrays
305  ar << nodeData;
306  ar << edgeIndData;
307  ar << edgeDst;
308  ar << edgeData;
309  }
310 
316  void deSerializeGraph(boost::archive::binary_iarchive& ar) {
317  ar >> numNodes;
318  ar >> numEdges;
319 
320  // Large Arrays
321  ar >> nodeData;
322  ar >> edgeIndData;
323  ar >> edgeDst;
324  ar >> edgeData;
325  }
326 
338  uint64_t operator[](uint64_t n) { return *(edge_end(n)); }
339 
340  template <typename EdgeNumFnTy, typename EdgeDstFnTy, typename EdgeDataFnTy>
341  LC_CSR_Hypergraph(uint32_t _numNodes, uint64_t _numEdges, EdgeNumFnTy edgeNum,
342  EdgeDstFnTy _edgeDst, EdgeDataFnTy _edgeData)
343  : numNodes(_numNodes), numEdges(_numEdges) {
344  // std::cerr << "\n**" << numNodes << " " << numEdges << "\n\n";
345  if (UseNumaAlloc) {
347  nodeData.allocateBlocked(numNodes);
348  edgeIndData.allocateBlocked(numNodes);
349  edgeDst.allocateBlocked(numEdges);
350  edgeData.allocateBlocked(numEdges);
352  this->outOfLineAllocateBlocked(numNodes, false);
353  } else {
354  nodeData.allocateInterleaved(numNodes);
355  edgeIndData.allocateInterleaved(numNodes);
356  edgeDst.allocateInterleaved(numEdges);
357  edgeData.allocateInterleaved(numEdges);
358  this->outOfLineAllocateInterleaved(numNodes);
359  }
360  // std::cerr << "Done Alloc\n";
361  for (size_t n = 0; n < numNodes; ++n) {
363  }
364  // std::cerr << "Done Node Construct\n";
365  uint64_t cur = 0;
366  for (size_t n = 0; n < numNodes; ++n) {
367  cur += edgeNum(n);
368  edgeIndData[n] = cur;
369  }
370  // std::cerr << "Done Edge Reserve\n";
371  cur = 0;
372  for (size_t n = 0; n < numNodes; ++n) {
373  // if (n % (1024*128) == 0)
374  // std::cout << n << " " << cur << "\n";
375  for (uint64_t e = 0, ee = edgeNum(n); e < ee; ++e) {
377  edgeData.set(cur, _edgeData(n, e));
378  edgeDst[cur] = _edgeDst(n, e);
379  ++cur;
380  }
381  }
382 
383  // std::cerr << "Done Construct\n";
384  }
385 
386  friend void swap(LC_CSR_Hypergraph& lhs, LC_CSR_Hypergraph& rhs) {
387  swap(lhs.nodeData, rhs.nodeData);
388  swap(lhs.edgeIndData, rhs.edgeIndData);
389  swap(lhs.edgeDst, rhs.edgeDst);
390  swap(lhs.edgeData, rhs.edgeData);
391  std::swap(lhs.numNodes, rhs.numNodes);
392  std::swap(lhs.numEdges, rhs.numEdges);
393  }
394 
396  MethodFlag mflag = MethodFlag::WRITE) {
397  // galois::runtime::checkWrite(mflag, false);
398  NodeInfo& NI = nodeData[N];
399  acquireNode(N, mflag);
400  return NI.getData();
401  }
402 
405  MethodFlag GALOIS_UNUSED(mflag) = MethodFlag::UNPROTECTED) {
406  // galois::runtime::checkWrite(mflag, false);
407  return edgeData[*ni];
408  }
409 
410  GraphNode getEdgeDst(edge_iterator ni) { return edgeDst[*ni]; }
411 
412  size_t size() const { return numNodes; }
413  size_t sizeEdges() const { return numEdges; }
414 
415  iterator begin() const { return iterator(0); }
416  iterator end() const { return iterator(numNodes); }
417 
419  return const_local_iterator(this->localBegin(numNodes));
420  }
421 
423  return const_local_iterator(this->localEnd(numNodes));
424  }
425 
427  return local_iterator(this->localBegin(numNodes));
428  }
429 
431  return local_iterator(this->localEnd(numNodes));
432  }
433 
435  acquireNode(N, mflag);
436  if (!HasNoLockable && galois::runtime::shouldLock(mflag)) {
437  for (edge_iterator ii = raw_begin(N), ee = raw_end(N); ii != ee; ++ii) {
438  acquireNode(edgeDst[*ii], mflag);
439  }
440  }
441  return raw_begin(N);
442  }
443 
445  acquireNode(N, mflag);
446  return raw_end(N);
447  }
448 
450  return std::find_if(edge_begin(N1), edge_end(N1),
451  [=](edge_iterator e) { return getEdgeDst(e) == N2; });
452  }
453 
455  auto e = std::lower_bound(
456  edge_begin(N1), edge_end(N1), N2,
457  [=](edge_iterator e, GraphNode N) { return getEdgeDst(e) < N; });
458  return (getEdgeDst(e) == N2) ? e : edge_end(N1);
459  }
460 
463  return internal::make_no_deref_range(edge_begin(N, mflag),
464  edge_end(N, mflag));
465  }
466 
469  return edges(N, mflag);
470  }
471 
475  template <typename CompTy>
477  const CompTy& comp = std::less<EdgeTy>(),
478  MethodFlag mflag = MethodFlag::WRITE) {
479  acquireNode(N, mflag);
480  std::sort(
482  internal::EdgeSortCompWrapper<EdgeSortValue<GraphNode, EdgeTy>, CompTy>(
483  comp));
484  }
485 
490  template <typename CompTy>
491  void sortEdges(GraphNode N, const CompTy& comp,
492  MethodFlag mflag = MethodFlag::WRITE) {
493  acquireNode(N, mflag);
495  }
496 
501  acquireNode(N, mflag);
502  typedef EdgeSortValue<GraphNode, EdgeTy> EdgeSortVal;
504  [=](const EdgeSortVal& e1, const EdgeSortVal& e2) {
505  return e1.dst < e2.dst;
506  });
507  }
508 
515  galois::iterate(size_t{0}, this->size()),
516  [=](GraphNode N) { this->sortEdgesByDst(N, mflag); },
518  }
519 
520  void allocateFrom(FileGraph& graph) {
521  numNodes = graph.size();
522  numEdges = graph.sizeEdges();
523  if (UseNumaAlloc) {
524  nodeData.allocateBlocked(numNodes);
525  edgeIndData.allocateBlocked(numNodes);
526  edgeDst.allocateBlocked(numEdges);
527  edgeData.allocateBlocked(numEdges);
528  this->outOfLineAllocateBlocked(numNodes);
529  } else {
530  nodeData.allocateInterleaved(numNodes);
531  edgeIndData.allocateInterleaved(numNodes);
532  edgeDst.allocateInterleaved(numEdges);
533  edgeData.allocateInterleaved(numEdges);
534  this->outOfLineAllocateInterleaved(numNodes);
535  }
536  }
537 
538  void allocateFrom(uint32_t nNodes, uint64_t nEdges) {
539  numNodes = nNodes;
540  numEdges = nEdges;
541 
542  if (UseNumaAlloc) {
543  nodeData.allocateBlocked(numNodes);
544  edgeIndData.allocateBlocked(numNodes);
545  edgeDst.allocateBlocked(numEdges);
546  edgeData.allocateBlocked(numEdges);
547  this->outOfLineAllocateBlocked(numNodes);
548  } else {
549  nodeData.allocateInterleaved(numNodes);
550  edgeIndData.allocateInterleaved(numNodes);
551  edgeDst.allocateInterleaved(numEdges);
552  edgeData.allocateInterleaved(numEdges);
553  this->outOfLineAllocateInterleaved(numNodes);
554  }
555  }
556 
557  void constructNodes() {
558 #ifndef GALOIS_GRAPH_CONSTRUCT_SERIAL
559  for (uint32_t x = 0; x < numNodes; ++x) {
561  this->outOfLineConstructAt(x);
562  }
563 #else
565  galois::iterate(UINT64_C(0), numNodes),
566  [&](uint64_t x) {
568  this->outOfLineConstructAt(x);
569  },
570  galois::no_stats(), galois::loopname("CONSTRUCT_NODES"));
571 #endif
572  }
573 
574  void deallocate() {
575  nodeData.destroy();
577 
578  edgeIndData.deallocate();
579  edgeIndData.destroy();
580 
581  edgeDst.deallocate();
582  edgeDst.destroy();
583 
584  edgeData.deallocate();
585  edgeData.destroy();
586  }
587 
588  void constructEdge(uint64_t e, uint32_t dst,
589  const typename EdgeData::value_type& val) {
590  edgeData.set(e, val);
591  edgeDst[e] = dst;
592  }
593 
594  void constructEdge(uint64_t e, uint32_t dst) { edgeDst[e] = dst; }
595 
596  void fixEndEdge(uint32_t n, uint64_t e) { edgeIndData[n] = e; }
597 
602  void transpose(const char* regionName = NULL) {
603  galois::StatTimer timer("TIMER_GRAPH_TRANSPOSE", regionName);
604  timer.start();
605 
606  EdgeDst edgeDst_old;
607  EdgeData edgeData_new;
608  EdgeIndData edgeIndData_old;
609  EdgeIndData edgeIndData_temp;
610 
611  if (UseNumaAlloc) {
612  edgeIndData_old.allocateBlocked(numNodes);
613  edgeIndData_temp.allocateBlocked(numNodes);
614  edgeDst_old.allocateBlocked(numEdges);
615  edgeData_new.allocateBlocked(numEdges);
616  } else {
617  edgeIndData_old.allocateInterleaved(numNodes);
618  edgeIndData_temp.allocateInterleaved(numNodes);
619  edgeDst_old.allocateInterleaved(numEdges);
620  edgeData_new.allocateInterleaved(numEdges);
621  }
622 
623  // Copy old node->index location + initialize the temp array
625  galois::iterate(UINT64_C(0), numNodes),
626  [&](uint64_t n) {
627  edgeIndData_old[n] = edgeIndData[n];
628  edgeIndData_temp[n] = 0;
629  },
630  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_COPY"));
631 
632  // get destination of edge, copy to array, and
634  galois::iterate(UINT64_C(0), numEdges),
635  [&](uint64_t e) {
636  auto dst = edgeDst[e];
637  edgeDst_old[e] = dst;
638  // counting outgoing edges in the tranpose graph by
639  // counting incoming edges in the original graph
640  __sync_add_and_fetch(&(edgeIndData_temp[dst]), 1);
641  },
642  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_INC"));
643 
644  // TODO is it worth doing parallel prefix sum?
645  // prefix sum calculation of the edge index array
646  for (uint32_t n = 1; n < numNodes; ++n) {
647  edgeIndData_temp[n] += edgeIndData_temp[n - 1];
648  }
649 
650  // copy over the new tranposed edge index data
652  galois::iterate(UINT64_C(0), numNodes),
653  [&](uint64_t n) { edgeIndData[n] = edgeIndData_temp[n]; },
654  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_SET"));
655 
656  // edgeIndData_temp[i] will now hold number of edges that all nodes
657  // before the ith node have
658  if (numNodes >= 1) {
659  edgeIndData_temp[0] = 0;
661  galois::iterate(UINT64_C(1), numNodes),
662  [&](uint64_t n) { edgeIndData_temp[n] = edgeIndData[n - 1]; },
663  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_TEMP"));
664  }
665 
667  galois::iterate(UINT64_C(0), numNodes),
668  [&](uint64_t src) {
669  // e = start index into edge array for a particular node
670  uint64_t e = (src == 0) ? 0 : edgeIndData_old[src - 1];
671 
672  // get all outgoing edges of a particular node in the
673  // non-transpose and convert to incoming
674  while (e < edgeIndData_old[src]) {
675  // destination nodde
676  auto dst = edgeDst_old[e];
677  // location to save edge
678  auto e_new = __sync_fetch_and_add(&(edgeIndData_temp[dst]), 1);
679  // save src as destination
680  edgeDst[e_new] = src;
681  // copy edge data to "new" array
682  edgeDataCopy(edgeData_new, edgeData, e_new, e);
683  e++;
684  }
685  },
686  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEDST"));
687 
688  // if edge weights, then overwrite edgeData with new edge data
689  if (EdgeData::has_value) {
691  galois::iterate(UINT64_C(0), numEdges),
692  [&](uint64_t e) { edgeDataCopy(edgeData, edgeData_new, e, e); },
693  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEDATA_SET"));
694  }
695 
696  timer.stop();
697  }
698 
699  template <bool is_non_void = EdgeData::has_value>
700  void edgeDataCopy(EdgeData& edgeData_new, EdgeData& edgeData, uint64_t e_new,
701  uint64_t e,
702  typename std::enable_if<is_non_void>::type* = 0) {
703  edgeData_new[e_new] = edgeData[e];
704  }
705 
706  template <bool is_non_void = EdgeData::has_value>
707  void edgeDataCopy(EdgeData&, EdgeData&, uint64_t, uint64_t,
708  typename std::enable_if<!is_non_void>::type* = 0) {
709  // does nothing
710  }
711 
712  void constructFrom(FileGraph& graph, unsigned tid, unsigned total) {
713  // at this point memory should already be allocated
714  auto r =
715  graph
716  .divideByNode(
717  NodeData::size_of::value + EdgeIndData::size_of::value +
718  LC_CSR_Hypergraph::size_of_out_of_line::value,
719  EdgeDst::size_of::value + EdgeData::size_of::value, tid, total)
720  .first;
721 
722  this->setLocalRange(*r.first, *r.second);
723 
724  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
725  nodeData.constructAt(*ii);
726  edgeIndData[*ii] = *graph.edge_end(*ii);
727 
728  this->outOfLineConstructAt(*ii);
729 
730  for (FileGraph::edge_iterator nn = graph.edge_begin(*ii),
731  en = graph.edge_end(*ii);
732  nn != en; ++nn) {
733  constructEdgeValue(graph, nn);
734  edgeDst[*nn] = graph.getEdgeDst(nn);
735  }
736  }
737  }
738 
745  const EdgeIndData& getEdgePrefixSum() const { return edgeIndData; }
746 
747  auto divideByNode(size_t nodeSize, size_t edgeSize, size_t id, size_t total) {
749  numNodes, numEdges, nodeSize, edgeSize, id, total, edgeIndData);
750  }
758  uint32_t numNodes, uint64_t numEdges, std::vector<uint64_t>& prefix_sum,
759  std::vector<std::vector<uint32_t>>&
760  edges_id) { //, std::vector<std::vector<EdgeTy>>& edges_data) {
761  allocateFrom(numNodes, numEdges);
762  constructNodes();
763 
764  galois::do_all(galois::iterate((uint32_t)0, numNodes),
765  [&](uint32_t n) { edgeIndData[n] = prefix_sum[n]; });
766 
767  galois::do_all(galois::iterate((uint32_t)0, numNodes), [&](uint32_t n) {
768  if (n == 0) {
769  if (edgeIndData[n] > 0) {
770  std::copy(edges_id[n].begin(), edges_id[n].end(), edgeDst.begin());
771  // std::copy(edges_data[n].begin(), edges_data[n].end(),
772  // edgeData.begin());
773  }
774  } else {
775  if (edgeIndData[n] - edgeIndData[n - 1] > 0) {
776  std::copy(edges_id[n].begin(), edges_id[n].end(),
777  edgeDst.begin() + edgeIndData[n - 1]);
778  // std::copy(edges_data[n].begin(), edges_data[n].end(),
779  // edgeData.begin() + edgeIndData[n-1]);
780  }
781  }
782  });
783 
784  galois::on_each([&](unsigned tid, unsigned total) {
785  std::vector<unsigned>
786  dummy_scale_factor; // dummy passed in to function call
787 
788  auto r = divideByNode(0, 1, tid, total).first;
789 
790  // galois::gPrint("[", tid, "] : Ranges : ", *r.first, ", ", *r.second,
791  // "\n");
792  this->setLocalRange(*r.first, *r.second);
793  });
794  }
796  uint32_t numNodes, uint64_t numEdges, std::vector<uint64_t>& prefix_sum,
798  edges_id) { //, std::vector<std::vector<EdgeTy>>& edges_data) {
799  allocateFrom(numNodes, numEdges);
800  constructNodes();
801 
802  galois::do_all(galois::iterate((uint32_t)0, numNodes),
803  [&](uint32_t n) { edgeIndData[n] = prefix_sum[n]; });
804 
805  galois::do_all(galois::iterate((uint32_t)0, numNodes), [&](uint32_t n) {
806  if (n == 0) {
807  if (edgeIndData[n] > 0) {
808  std::copy(edges_id[n].begin(), edges_id[n].end(), edgeDst.begin());
809  // std::copy(edges_data[n].begin(), edges_data[n].end(),
810  // edgeData.begin());
811  }
812  } else {
813  if (edgeIndData[n] - edgeIndData[n - 1] > 0) {
814  std::copy(edges_id[n].begin(), edges_id[n].end(),
815  edgeDst.begin() + edgeIndData[n - 1]);
816  // std::copy(edges_data[n].begin(), edges_data[n].end(),
817  // edgeData.begin() + edgeIndData[n-1]);
818  }
819  }
820  });
821 
822  galois::on_each([&](unsigned tid, unsigned total) {
823  std::vector<unsigned>
824  dummy_scale_factor; // dummy passed in to function call
825 
826  auto r = divideByNode(0, 1, tid, total).first;
827 
828  // galois::gPrint("[", tid, "] : Ranges : ", *r.first, ", ", *r.second,
829  // "\n");
830  this->setLocalRange(*r.first, *r.second);
831  });
832  }
833  // uint32_t edgeSize(uint32_t n) {
834  // return edgeDst[n].size();
835  //}
836 };
837 } // namespace graphs
838 } // namespace galois
839 
840 #endif
friend void swap(LC_CSR_Hypergraph &lhs, LC_CSR_Hypergraph &rhs)
Definition: LC_CSR_Hypergraph.h:386
void set(difference_type x, const_reference v)
Definition: LargeArray.h:197
If true, store abstract locks separate from nodes.
Definition: LC_CSR_Hypergraph.h:125
Definition: Traits.h:247
LargeArray< EdgeTy > EdgeData
Definition: LC_CSR_Hypergraph.h:134
LC_CSR_Hypergraph< NodeTy, EdgeTy, HasNoLockable, _use_numa_alloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Hypergraph.h:116
size_t size() const
Definition: LC_CSR_Hypergraph.h:412
size_t hnodes
Definition: LC_CSR_Hypergraph.h:160
boost::counting_iterator< typename EdgeDst::value_type > iterator
Definition: LC_CSR_Hypergraph.h:154
void constructNodes()
Definition: LC_CSR_Hypergraph.h:557
size_t getId(GraphNode N)
Definition: LC_CSR_Hypergraph.h:224
LC_CSR_Hypergraph< NodeTy, EdgeTy, _has_no_lockable, UseNumaAlloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Hypergraph.h:104
void destroy()
Definition: LargeArray.h:277
LargeArray< uint32_t > EdgeDst
Definition: LC_CSR_Hypergraph.h:135
void deSerializeGraph(boost::archive::binary_iarchive &ar)
Deserializes a Boost archive to the local graph.
Definition: LC_CSR_Hypergraph.h:316
void constructFrom(uint32_t numNodes, uint64_t numEdges, std::vector< uint64_t > &prefix_sum, galois::gstl::Vector< galois::PODResizeableArray< uint32_t >> &edges_id)
Definition: LC_CSR_Hypergraph.h:795
edge_iterator edge_begin(GraphNode N)
Returns the index to the beginning of global node N&#39;s outgoing edges in the outgoing edges array...
Definition: FileGraph.cpp:641
Contains FileGraph and FileGraphWriter class declarations.
Definition: LC_CSR_Hypergraph.h:86
size_t size() const
Returns the number of nodes in the (sub)graph.
Definition: FileGraph.h:545
LC_CSR_Hypergraph< NodeTy, _edge_data, HasNoLockable, UseNumaAlloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Hypergraph.h:89
void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if< _A1 &&!_A2 >::type *=0)
Definition: LC_CSR_Hypergraph.h:198
size_t hedges
Definition: LC_CSR_Hypergraph.h:159
uint64_t value_type
Definition: LargeArray.h:60
edge_iterator raw_end(GraphNode N) const
Definition: LC_CSR_Hypergraph.h:179
boost::counting_iterator< uint64_t > iterator
uint64 boost counting iterator
Definition: FileGraph.h:408
EdgeData edgeData
Definition: LC_CSR_Hypergraph.h:166
EdgeIndData edgeIndData
Definition: LC_CSR_Hypergraph.h:164
LargeArray< NodeInfo > NodeData
Definition: LC_CSR_Hypergraph.h:143
void deSerializeNodeData(boost::archive::binary_iarchive &ar)
Deserializes a Boost archive containing node data to the local node data variable.
Definition: LC_CSR_Hypergraph.h:291
void serializeGraph(boost::archive::binary_oarchive &ar) const
Serializes graph using Boost.
Definition: LC_CSR_Hypergraph.h:300
auto divideNodesBinarySearch(NodeType numNodes, uint64_t numEdges, size_t nodeWeight, size_t edgeWeight, size_t id, size_t total, PrefixSumType &edgePrefixSum, std::vector< unsigned > scaleFactor=std::vector< unsigned >(), uint64_t edgeOffset=0, uint64_t nodeOffset=0)
Returns 2 ranges (one for nodes, one for edges) for a particular division.
Definition: GraphHelpers.h:141
void serializeNodeData(boost::archive::binary_oarchive &ar) const
Serializes node data using Boost.
Definition: LC_CSR_Hypergraph.h:281
const_local_iterator local_end() const
Definition: LC_CSR_Hypergraph.h:422
read_default_graph_tag read_tag
Definition: LC_CSR_Hypergraph.h:131
size_t sizeEdges() const
Definition: LC_CSR_Hypergraph.h:413
LC_CSR_Hypergraph< _node_data, EdgeTy, HasNoLockable, UseNumaAlloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Hypergraph.h:82
void constructFrom(FileGraph &graph, unsigned tid, unsigned total)
Definition: LC_CSR_Hypergraph.h:712
void constructEdgeValue(FileGraph &graph, typename FileGraph::edge_iterator nn, typename std::enable_if<!_A1||_A2 >::type *=0)
Definition: LC_CSR_Hypergraph.h:209
GraphNode getEdgeDst(edge_iterator it)
Gets the destination of some edge.
Definition: FileGraph.cpp:669
boost::counting_iterator< uint64_t > edge_iterator
Edge iterators (boost iterator)
Definition: FileGraph.h:248
uint32_t GraphNode
Definition: LC_CSR_Hypergraph.h:146
Definition: Iterable.h:36
void constructFrom(uint32_t numNodes, uint64_t numEdges, std::vector< uint64_t > &prefix_sum, std::vector< std::vector< uint32_t >> &edges_id)
custom allocator for vector&lt;vector&lt;&gt;&gt; Adding for Louvain clustering TODO: Find better way to do this ...
Definition: LC_CSR_Hypergraph.h:757
const char * loopname
Definition: Executor_ParaMeter.h:145
Definition: LC_CSR_Hypergraph.h:79
bool shouldLock(const galois::MethodFlag g)
Helper function to decide if the conflict detection lock should be taken.
Definition: libgalois/include/galois/runtime/Context.h:189
Definition: LC_CSR_Hypergraph.h:74
friend class boost::serialization::access
Definition: LC_CSR_Hypergraph.h:229
NodeTy node_data_type
Definition: LC_CSR_Hypergraph.h:149
edge_sort_iterator edge_sort_end(GraphNode N)
Definition: LC_CSR_Hypergraph.h:187
edge_iterator edge_begin(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Hypergraph.h:434
iterator const_iterator
Definition: LC_CSR_Hypergraph.h:155
void constructEdge(uint64_t e, uint32_t dst)
Definition: LC_CSR_Hypergraph.h:594
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
Definition: ParallelSTL.h:247
edge_sort_iterator edge_sort_begin(GraphNode N)
Definition: LC_CSR_Hypergraph.h:183
Modify a LC_Graph to have in and out edges.
Definition: LC_InOut_Graph.h:39
iterator end() const
Definition: LC_CSR_Hypergraph.h:416
Local computation graph (i.e., graph structure does not change).
Definition: LC_CSR_Hypergraph.h:63
void deallocate()
Definition: LC_CSR_Hypergraph.h:574
If true, do not use abstract locks in graph.
Definition: LC_CSR_Hypergraph.h:101
NodeData nodeData
Definition: LC_CSR_Hypergraph.h:163
local_iterator local_begin()
Definition: LC_CSR_Hypergraph.h:426
void allocateInterleaved(size_type n)
[allocatefunctions] Allocates interleaved across NUMA (memory) nodes.
Definition: LargeArray.h:206
void edgeDataCopy(EdgeData &edgeData_new, EdgeData &edgeData, uint64_t e_new, uint64_t e, typename std::enable_if< is_non_void >::type *=0)
Definition: LC_CSR_Hypergraph.h:700
std::vector< T, Pow2Alloc< T >> Vector
[STL vector using Pow_2_VarSizeAlloc]
Definition: gstl.h:52
iterator local_iterator
Definition: LC_CSR_Hypergraph.h:156
value_type & reference
Definition: LargeArray.h:63
If true, use NUMA-aware graph allocation.
Definition: LC_CSR_Hypergraph.h:113
const EdgeIndData & getEdgePrefixSum() const
Returns the reference to the edgeIndData LargeArray (a prefix sum of edges)
Definition: LC_CSR_Hypergraph.h:745
iterator const_local_iterator
Definition: LC_CSR_Hypergraph.h:157
LC_CSR_Hypergraph type
Definition: LC_CSR_Hypergraph.h:75
node_data_reference getData(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Hypergraph.h:395
GraphNode getEdgeDst(edge_iterator ni)
Definition: LC_CSR_Hypergraph.h:410
void sortEdgesByDst(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Sorts outgoing edges of a node.
Definition: LC_CSR_Hypergraph.h:500
Proxy object for internal EdgeSortReference.
Definition: Details.h:56
NodeInfoTypes::reference node_data_reference
Definition: LC_CSR_Hypergraph.h:151
boost::counting_iterator< typename EdgeIndData::value_type > edge_iterator
Definition: LC_CSR_Hypergraph.h:153
Definition: Traits.h:206
internal::EdgeSortIterator< GraphNode, typename EdgeIndData::value_type, EdgeDst, EdgeData > edge_sort_iterator
Definition: LC_CSR_Hypergraph.h:173
edge_iterator raw_begin(GraphNode N) const
Definition: LC_CSR_Hypergraph.h:175
EdgeData::reference edge_data_reference
Definition: LC_CSR_Hypergraph.h:150
void acquire(Lockable *lockable, galois::MethodFlag m)
Master function which handles conflict detection used to acquire a lockable thing.
Definition: libgalois/include/galois/runtime/Context.h:218
MethodFlag
What should the runtime do when executing a method.
Definition: MethodFlags.h:34
void constructEdgeValue(FileGraph &, typename FileGraph::edge_iterator nn, typename std::enable_if< _A1 &&!_A2 >::type *=0)
Definition: LC_CSR_Hypergraph.h:219
void fixEndEdge(uint32_t n, uint64_t e)
Definition: LC_CSR_Hypergraph.h:596
void do_all(const RangeFunc &rangeMaker, FunctionTy &&fn, const Args &...args)
Standard do-all loop.
Definition: Loops.h:71
void transpose(const char *regionName=NULL)
Perform an in-memory transpose of the graph, replacing the original CSR to CSC.
Definition: LC_CSR_Hypergraph.h:602
uint64_t operator[](uint64_t n)
Accesses the &quot;prefix sum&quot; of this graph; takes advantage of the fact that edge_end(n) is basically pr...
Definition: LC_CSR_Hypergraph.h:338
LargeArray< uint64_t > EdgeIndData
Definition: LC_CSR_Hypergraph.h:142
LC_CSR_Hypergraph< NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc, HasOutOfLineLockable, _file_edge_data > type
Definition: LC_CSR_Hypergraph.h:96
runtime::iterable< NoDerefIterator< edge_iterator > > edges(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Hypergraph.h:462
const_local_iterator local_begin() const
Definition: LC_CSR_Hypergraph.h:418
uint64_t numEdges
Definition: LC_CSR_Hypergraph.h:169
void start()
Definition: Timer.cpp:82
EdgeDst edgeDst
Definition: LC_CSR_Hypergraph.h:165
void on_each(FunctionTy &&fn, const Args &...args)
Low-level parallel loop.
Definition: Loops.h:86
edge_iterator findEdgeSortedByDst(GraphNode N1, GraphNode N2)
Definition: LC_CSR_Hypergraph.h:454
void acquireNode(GraphNode, MethodFlag, typename std::enable_if< _A2 >::type *=0)
Definition: LC_CSR_Hypergraph.h:204
GraphNode getNode(size_t n)
Definition: LC_CSR_Hypergraph.h:226
EdgeTy & getEdgeData(GraphNode src, GraphNode dst)
Get edge data of an edge between 2 nodes.
Definition: FileGraph.h:241
runtime::iterable< NoDerefIterator< edge_iterator > > out_edges(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Hypergraph.h:468
void sortEdges(GraphNode N, const CompTy &comp, MethodFlag mflag=MethodFlag::WRITE)
Sorts outgoing edges of a node.
Definition: LC_CSR_Hypergraph.h:491
iterator begin() const
Definition: LC_CSR_Hypergraph.h:415
EdgeTy edge_data_type
Definition: LC_CSR_Hypergraph.h:147
void constructAt(size_type n, Args &&...args)
Definition: LargeArray.h:260
GraphRange divideByNode(size_t nodeSize, size_t edgeSize, size_t id, size_t total)
Given a division and a total number of divisions, return a range for that particular division to work...
Definition: FileGraph.cpp:480
LC_CSR_Hypergraph(uint32_t _numNodes, uint64_t _numEdges, EdgeNumFnTy edgeNum, EdgeDstFnTy _edgeDst, EdgeDataFnTy _edgeData)
Definition: LC_CSR_Hypergraph.h:341
edge_iterator edge_end(GraphNode N)
Returns the index to the end of global node N&#39;s outgoing edges in the outgoing edges array...
Definition: FileGraph.cpp:655
internal::NodeInfoBaseTypes< NodeTy,!HasNoLockable &&!HasOutOfLineLockable > NodeInfoTypes
Definition: LC_CSR_Hypergraph.h:138
size_t sizeEdges() const
Returns the number of edges in the (sub)graph.
Definition: FileGraph.h:548
void sortAllEdgesByDst(MethodFlag mflag=MethodFlag::WRITE)
Sorts all outgoing edges of all nodes in parallel.
Definition: LC_CSR_Hypergraph.h:513
const_pointer data() const
Definition: LargeArray.h:292
void allocateBlocked(size_type n)
Allocates using blocked memory policy.
Definition: LargeArray.h:213
static const bool has_value
Definition: LargeArray.h:69
internal::NodeInfoBase< NodeTy,!HasNoLockable &&!HasOutOfLineLockable > NodeInfo
Definition: LC_CSR_Hypergraph.h:141
void edgeDataCopy(EdgeData &, EdgeData &, uint64_t, uint64_t, typename std::enable_if<!is_non_void >::type *=0)
Definition: LC_CSR_Hypergraph.h:707
auto divideByNode(size_t nodeSize, size_t edgeSize, size_t id, size_t total)
Definition: LC_CSR_Hypergraph.h:747
Graph that mmaps Galois gr files for access.
Definition: FileGraph.h:57
local_iterator local_end()
Definition: LC_CSR_Hypergraph.h:430
auto iterate(C &cont)
Definition: Range.h:323
This is a container that encapsulates a resizeable array of plain-old-datatype (POD) elements...
Definition: PODResizeableArray.h:40
edge_iterator findEdge(GraphNode N1, GraphNode N2)
Definition: LC_CSR_Hypergraph.h:449
InputIterator find_if(InputIterator first, InputIterator last, Predicate pred)
Definition: ParallelSTL.h:70
edge_data_reference getEdgeData(edge_iterator ni, MethodFlag GALOIS_UNUSED(mflag)=MethodFlag::UNPROTECTED)
Definition: LC_CSR_Hypergraph.h:404
void constructEdge(uint64_t e, uint32_t dst, const typename EdgeData::value_type &val)
Definition: LC_CSR_Hypergraph.h:588
T value_type
Definition: Executor_ParaMeter.h:111
void allocateFrom(FileGraph &graph)
Definition: LC_CSR_Hypergraph.h:520
void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if<!_A1 &&!_A2 >::type *=0)
Definition: LC_CSR_Hypergraph.h:192
FileEdgeTy file_edge_data_type
Definition: LC_CSR_Hypergraph.h:148
void deallocate()
Definition: LargeArray.h:271
edge_iterator edge_end(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Hypergraph.h:444
void allocateFrom(uint32_t nNodes, uint64_t nEdges)
Definition: LC_CSR_Hypergraph.h:538
void stop()
Definition: Timer.cpp:87
uint64_t numNodes
Definition: LC_CSR_Hypergraph.h:168
Galois Timer that automatically reports stats upon destruction Provides statistic interface around ti...
Definition: Timer.h:63
void sortEdgesByEdgeData(GraphNode N, const CompTy &comp=std::less< EdgeTy >(), MethodFlag mflag=MethodFlag::WRITE)
Sorts outgoing edges of a node.
Definition: LC_CSR_Hypergraph.h:476
LC_CSR_Hypergraph< NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc, _has_out_of_line_lockable, FileEdgeTy > type
Definition: LC_CSR_Hypergraph.h:128