Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LC_CSR_Graph.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_GRAPH_H
21 #define GALOIS_GRAPHS_LC_CSR_GRAPH_H
22 
23 #include <fstream>
24 #include <type_traits>
25 
26 #include <boost/archive/binary_oarchive.hpp>
27 #include <boost/archive/binary_iarchive.hpp>
28 #include <boost/serialization/split_member.hpp>
29 #include <boost/serialization/binary_object.hpp>
30 #include <boost/serialization/serialization.hpp>
31 
32 #include "galois/config.h"
33 #include "galois/Galois.h"
34 #include "galois/graphs/Details.h"
38 
39 namespace galois::graphs {
58 template <typename NodeTy, typename EdgeTy, bool HasNoLockable = false,
60  bool UseNumaAlloc = false, bool HasOutOfLineLockable = false,
61  typename FileEdgeTy = EdgeTy>
62 class LC_CSR_Graph :
64  private boost::noncopyable,
65  private internal::LocalIteratorFeature<UseNumaAlloc>,
66  private internal::OutOfLineLockableFeature<HasOutOfLineLockable &&
67  !HasNoLockable> {
68  template <typename Graph>
69  friend class LC_InOut_Graph;
70 
71 public:
72  template <bool _has_id>
73  struct with_id {
74  typedef LC_CSR_Graph type;
75  };
76 
77  template <typename _node_data>
78  struct with_node_data {
79  typedef LC_CSR_Graph<_node_data, EdgeTy, HasNoLockable, UseNumaAlloc,
80  HasOutOfLineLockable, FileEdgeTy>
82  };
83 
84  template <typename _edge_data>
85  struct with_edge_data {
86  typedef LC_CSR_Graph<NodeTy, _edge_data, HasNoLockable, UseNumaAlloc,
87  HasOutOfLineLockable, FileEdgeTy>
89  };
90 
91  template <typename _file_edge_data>
93  typedef LC_CSR_Graph<NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc,
94  HasOutOfLineLockable, _file_edge_data>
96  };
97 
99  template <bool _has_no_lockable>
101  typedef LC_CSR_Graph<NodeTy, EdgeTy, _has_no_lockable, UseNumaAlloc,
102  HasOutOfLineLockable, FileEdgeTy>
104  };
105  template <bool _has_no_lockable>
106  using _with_no_lockable =
107  LC_CSR_Graph<NodeTy, EdgeTy, _has_no_lockable, UseNumaAlloc,
108  HasOutOfLineLockable, FileEdgeTy>;
109 
112  template <bool _use_numa_alloc>
114  typedef LC_CSR_Graph<NodeTy, EdgeTy, HasNoLockable, _use_numa_alloc,
115  HasOutOfLineLockable, FileEdgeTy>
117  };
118  template <bool _use_numa_alloc>
119  using _with_numa_alloc =
120  LC_CSR_Graph<NodeTy, EdgeTy, HasNoLockable, _use_numa_alloc,
121  HasOutOfLineLockable, FileEdgeTy>;
122 
124  template <bool _has_out_of_line_lockable>
126  typedef LC_CSR_Graph<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 
159 protected:
164 
165  uint64_t numNodes;
166  uint64_t numEdges;
167 
168  typedef internal::EdgeSortIterator<
171 
173  return edge_iterator((N == 0) ? 0 : edgeIndData[N - 1]);
174  }
175 
177  return edge_iterator(edgeIndData[N]);
178  }
179 
182  }
183 
185  return edge_sort_iterator(*raw_end(N), &edgeDst, &edgeData);
186  }
187 
188  template <bool _A1 = HasNoLockable, bool _A2 = HasOutOfLineLockable>
190  typename std::enable_if<!_A1 && !_A2>::type* = 0) {
192  }
193 
194  template <bool _A1 = HasOutOfLineLockable, bool _A2 = HasNoLockable>
196  typename std::enable_if<_A1 && !_A2>::type* = 0) {
197  this->outOfLineAcquire(getId(N), mflag);
198  }
199 
200  template <bool _A1 = HasOutOfLineLockable, bool _A2 = HasNoLockable>
202  typename std::enable_if<_A2>::type* = 0) {}
203 
204  template <bool _A1 = EdgeData::has_value,
207  typename FileGraph::edge_iterator nn,
208  typename std::enable_if<!_A1 || _A2>::type* = 0) {
209  typedef LargeArray<FileEdgeTy> FED;
211  edgeData.set(*nn, graph.getEdgeData<typename FED::value_type>(nn));
212  }
213 
214  template <bool _A1 = EdgeData::has_value,
217  typename std::enable_if<_A1 && !_A2>::type* = 0) {
218  edgeData.set(*nn, {});
219  }
220 
221  size_t getId(GraphNode N) { return N; }
222 
223  GraphNode getNode(size_t n) { return n; }
224 
225 private:
226  friend class boost::serialization::access;
227 
228  template <typename Archive>
229  void save(Archive& ar, const unsigned int) const {
230  ar << numNodes;
231  ar << numEdges;
232 
233  // Large Arrays
234  ar << edgeIndData;
235  ar << edgeDst;
236  ar << edgeData;
237  }
238 
239  template <typename Archive>
240  void load(Archive& ar, const unsigned int) {
241  ar >> numNodes;
242  ar >> numEdges;
243 
244  // Large Arrays
245  ar >> edgeIndData;
246  ar >> edgeDst;
247  ar >> edgeData;
248 
249  if (!nodeData.data()) {
250  if (UseNumaAlloc) {
251  nodeData.allocateBlocked(numNodes);
252  this->outOfLineAllocateBlocked(numNodes);
253  } else {
254  nodeData.allocateInterleaved(numNodes);
255  this->outOfLineAllocateInterleaved(numNodes);
256  }
257 
258  // Construct nodeData largeArray
259  for (size_t n = 0; n < numNodes; ++n) {
261  }
262  }
263  }
264 
265  // The macro BOOST_SERIALIZATION_SPLIT_MEMBER() generates code which invokes
266  // the save or load depending on whether the archive is used for saving or
267  // loading
268  BOOST_SERIALIZATION_SPLIT_MEMBER()
269 
270 public:
271  LC_CSR_Graph(LC_CSR_Graph&& rhs) = default;
272 
273  LC_CSR_Graph() = default;
274 
275  LC_CSR_Graph& operator=(LC_CSR_Graph&&) = default;
276 
282  void serializeNodeData(boost::archive::binary_oarchive& ar) const {
283  ar << nodeData;
284  }
285 
292  void deSerializeNodeData(boost::archive::binary_iarchive& ar) {
293  ar >> nodeData;
294  }
295 
301  void serializeGraph(boost::archive::binary_oarchive& ar) const {
302  ar << numNodes;
303  ar << numEdges;
304 
305  // Large Arrays
306  ar << nodeData;
307  ar << edgeIndData;
308  ar << edgeDst;
309  ar << edgeData;
310  }
311 
317  void deSerializeGraph(boost::archive::binary_iarchive& ar) {
318  ar >> numNodes;
319  ar >> numEdges;
320 
321  // Large Arrays
322  ar >> nodeData;
323  ar >> edgeIndData;
324  ar >> edgeDst;
325  ar >> edgeData;
326  }
327 
339  uint64_t operator[](uint64_t n) { return *(edge_end(n)); }
340 
341  template <typename EdgeNumFnTy, typename EdgeDstFnTy, typename EdgeDataFnTy>
342  LC_CSR_Graph(uint32_t _numNodes, uint64_t _numEdges, EdgeNumFnTy edgeNum,
343  EdgeDstFnTy _edgeDst, EdgeDataFnTy _edgeData)
344  : numNodes(_numNodes), numEdges(_numEdges) {
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  for (size_t n = 0; n < numNodes; ++n) {
362  }
363  uint64_t cur = 0;
364  for (size_t n = 0; n < numNodes; ++n) {
365  cur += edgeNum(n);
366  edgeIndData[n] = cur;
367  }
368  cur = 0;
369  for (size_t n = 0; n < numNodes; ++n) {
370  for (uint64_t e = 0, ee = edgeNum(n); e < ee; ++e) {
372  edgeData.set(cur, _edgeData(n, e));
373  edgeDst[cur] = _edgeDst(n, e);
374  ++cur;
375  }
376  }
377  }
378 
379  friend void swap(LC_CSR_Graph& lhs, LC_CSR_Graph& rhs) {
380  swap(lhs.nodeData, rhs.nodeData);
381  swap(lhs.edgeIndData, rhs.edgeIndData);
382  swap(lhs.edgeDst, rhs.edgeDst);
383  swap(lhs.edgeData, rhs.edgeData);
384  std::swap(lhs.numNodes, rhs.numNodes);
385  std::swap(lhs.numEdges, rhs.numEdges);
386  }
387 
389  MethodFlag mflag = MethodFlag::WRITE) {
390  // galois::runtime::checkWrite(mflag, false);
391  NodeInfo& NI = nodeData[N];
392  acquireNode(N, mflag);
393  return NI.getData();
394  }
395 
398  MethodFlag GALOIS_UNUSED(mflag) = MethodFlag::UNPROTECTED) {
399  // galois::runtime::checkWrite(mflag, false);
400  return edgeData[*ni];
401  }
402 
403  GraphNode getEdgeDst(edge_iterator ni) { return edgeDst[*ni]; }
404 
405  size_t size() const { return numNodes; }
406  size_t sizeEdges() const { return numEdges; }
407 
408  iterator begin() const { return iterator(0); }
409  iterator end() const { return iterator(numNodes); }
410 
412  return const_local_iterator(this->localBegin(numNodes));
413  }
414 
416  return const_local_iterator(this->localEnd(numNodes));
417  }
418 
420  return local_iterator(this->localBegin(numNodes));
421  }
422 
424  return local_iterator(this->localEnd(numNodes));
425  }
426 
428  acquireNode(N, mflag);
429  if (!HasNoLockable && galois::runtime::shouldLock(mflag)) {
430  for (edge_iterator ii = raw_begin(N), ee = raw_end(N); ii != ee; ++ii) {
431  acquireNode(edgeDst[*ii], mflag);
432  }
433  }
434  return raw_begin(N);
435  }
436 
438  acquireNode(N, mflag);
439  return raw_end(N);
440  }
441 
443  return std::find_if(edge_begin(N1), edge_end(N1),
444  [=](edge_iterator e) { return getEdgeDst(e) == N2; });
445  }
446 
448  auto e = std::lower_bound(
449  edge_begin(N1), edge_end(N1), N2,
450  [=](edge_iterator e, GraphNode N) { return getEdgeDst(e) < N; });
451  return (getEdgeDst(e) == N2) ? e : edge_end(N1);
452  }
453 
456  return internal::make_no_deref_range(edge_begin(N, mflag),
457  edge_end(N, mflag));
458  }
459 
462  return edges(N, mflag);
463  }
464 
468  template <typename CompTy>
470  const CompTy& comp = std::less<EdgeTy>(),
471  MethodFlag mflag = MethodFlag::WRITE) {
472  acquireNode(N, mflag);
473  std::sort(
475  internal::EdgeSortCompWrapper<EdgeSortValue<GraphNode, EdgeTy>, CompTy>(
476  comp));
477  }
478 
483  template <typename CompTy>
484  void sortEdges(GraphNode N, const CompTy& comp,
485  MethodFlag mflag = MethodFlag::WRITE) {
486  acquireNode(N, mflag);
488  }
489 
494  acquireNode(N, mflag);
495  typedef EdgeSortValue<GraphNode, EdgeTy> EdgeSortVal;
497  [=](const EdgeSortVal& e1, const EdgeSortVal& e2) {
498  return e1.dst < e2.dst;
499  });
500  }
501 
508  galois::iterate(size_t{0}, this->size()),
509  [=](GraphNode N) { this->sortEdgesByDst(N, mflag); },
511  }
512 
513  void allocateFrom(const FileGraph& graph) {
514  numNodes = graph.size();
515  numEdges = graph.sizeEdges();
516  if (UseNumaAlloc) {
517  nodeData.allocateBlocked(numNodes);
518  edgeIndData.allocateBlocked(numNodes);
519  edgeDst.allocateBlocked(numEdges);
520  edgeData.allocateBlocked(numEdges);
521  this->outOfLineAllocateBlocked(numNodes);
522  } else {
523  nodeData.allocateInterleaved(numNodes);
524  edgeIndData.allocateInterleaved(numNodes);
525  edgeDst.allocateInterleaved(numEdges);
526  edgeData.allocateInterleaved(numEdges);
527  this->outOfLineAllocateInterleaved(numNodes);
528  }
529  }
530 
531  void allocateFrom(uint32_t nNodes, uint64_t nEdges) {
532  numNodes = nNodes;
533  numEdges = nEdges;
534 
535  if (UseNumaAlloc) {
536  nodeData.allocateBlocked(numNodes);
537  edgeIndData.allocateBlocked(numNodes);
538  edgeDst.allocateBlocked(numEdges);
539  edgeData.allocateBlocked(numEdges);
540  this->outOfLineAllocateBlocked(numNodes);
541  } else {
542  nodeData.allocateInterleaved(numNodes);
543  edgeIndData.allocateInterleaved(numNodes);
544  edgeDst.allocateInterleaved(numEdges);
545  edgeData.allocateInterleaved(numEdges);
546  this->outOfLineAllocateInterleaved(numNodes);
547  }
548  }
549 
550  void destroyAndAllocateFrom(uint32_t nNodes, uint64_t nEdges) {
551  numNodes = nNodes;
552  numEdges = nEdges;
553 
554  deallocate();
555  if (UseNumaAlloc) {
556  nodeData.allocateBlocked(numNodes);
557  edgeIndData.allocateBlocked(numNodes);
558  edgeDst.allocateBlocked(numEdges);
559  edgeData.allocateBlocked(numEdges);
560  this->outOfLineAllocateBlocked(numNodes);
561  } else {
562  nodeData.allocateInterleaved(numNodes);
563  edgeIndData.allocateInterleaved(numNodes);
564  edgeDst.allocateInterleaved(numEdges);
565  edgeData.allocateInterleaved(numEdges);
566  this->outOfLineAllocateInterleaved(numNodes);
567  }
568  }
569 
570  void constructNodes() {
571 #ifndef GALOIS_GRAPH_CONSTRUCT_SERIAL
572  for (uint32_t x = 0; x < numNodes; ++x) {
574  this->outOfLineConstructAt(x);
575  }
576 #else
578  galois::iterate(UINT64_C(0), numNodes),
579  [&](uint64_t x) {
581  this->outOfLineConstructAt(x);
582  },
583  galois::no_stats(), galois::loopname("CONSTRUCT_NODES"));
584 #endif
585  }
586 
587  void deallocate() {
588  nodeData.destroy();
590 
591  edgeIndData.deallocate();
592  edgeIndData.destroy();
593 
594  edgeDst.deallocate();
595  edgeDst.destroy();
596 
597  edgeData.deallocate();
598  edgeData.destroy();
599  }
600 
601  void constructEdge(uint64_t e, uint32_t dst,
602  const typename EdgeData::value_type& val) {
603  edgeData.set(e, val);
604  edgeDst[e] = dst;
605  }
606 
607  void constructEdge(uint64_t e, uint32_t dst) { edgeDst[e] = dst; }
608 
609  void fixEndEdge(uint32_t n, uint64_t e) { edgeIndData[n] = e; }
610 
615  void transpose(const char* regionName = NULL) {
616  galois::StatTimer timer("TIMER_GRAPH_TRANSPOSE", regionName);
617  timer.start();
618 
619  EdgeDst edgeDst_old;
620  EdgeData edgeData_new;
621  EdgeIndData edgeIndData_old;
622  EdgeIndData edgeIndData_temp;
623 
624  if (UseNumaAlloc) {
625  edgeIndData_old.allocateBlocked(numNodes);
626  edgeIndData_temp.allocateBlocked(numNodes);
627  edgeDst_old.allocateBlocked(numEdges);
628  edgeData_new.allocateBlocked(numEdges);
629  } else {
630  edgeIndData_old.allocateInterleaved(numNodes);
631  edgeIndData_temp.allocateInterleaved(numNodes);
632  edgeDst_old.allocateInterleaved(numEdges);
633  edgeData_new.allocateInterleaved(numEdges);
634  }
635 
636  // Copy old node->index location + initialize the temp array
638  galois::iterate(UINT64_C(0), numNodes),
639  [&](uint64_t n) {
640  edgeIndData_old[n] = edgeIndData[n];
641  edgeIndData_temp[n] = 0;
642  },
643  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_COPY"));
644 
645  // get destination of edge, copy to array, and
647  galois::iterate(UINT64_C(0), numEdges),
648  [&](uint64_t e) {
649  auto dst = edgeDst[e];
650  edgeDst_old[e] = dst;
651  // counting outgoing edges in the tranpose graph by
652  // counting incoming edges in the original graph
653  __sync_add_and_fetch(&edgeIndData_temp[dst], 1);
654  },
655  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_INC"));
656 
657  // TODO is it worth doing parallel prefix sum?
658  // prefix sum calculation of the edge index array
659  for (uint32_t n = 1; n < numNodes; ++n) {
660  edgeIndData_temp[n] += edgeIndData_temp[n - 1];
661  }
662 
663  // copy over the new tranposed edge index data
665  galois::iterate(UINT64_C(0), numNodes),
666  [&](uint64_t n) { edgeIndData[n] = edgeIndData_temp[n]; },
667  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_SET"));
668 
669  // edgeIndData_temp[i] will now hold number of edges that all nodes
670  // before the ith node have
671  if (numNodes >= 1) {
672  edgeIndData_temp[0] = 0;
674  galois::iterate(UINT64_C(1), numNodes),
675  [&](uint64_t n) { edgeIndData_temp[n] = edgeIndData[n - 1]; },
676  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEINTDATA_TEMP"));
677  }
678 
680  galois::iterate(UINT64_C(0), numNodes),
681  [&](uint64_t src) {
682  // e = start index into edge array for a particular node
683  uint64_t e = (src == 0) ? 0 : edgeIndData_old[src - 1];
684 
685  // get all outgoing edges of a particular node in the
686  // non-transpose and convert to incoming
687  while (e < edgeIndData_old[src]) {
688  // destination nodde
689  auto dst = edgeDst_old[e];
690  // location to save edge
691  auto e_new = __sync_fetch_and_add(&(edgeIndData_temp[dst]), 1);
692  // save src as destination
693  edgeDst[e_new] = src;
694  // copy edge data to "new" array
695  edgeDataCopy(edgeData_new, edgeData, e_new, e);
696  e++;
697  }
698  },
699  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEDST"));
700 
701  // if edge weights, then overwrite edgeData with new edge data
702  if (EdgeData::has_value) {
704  galois::iterate(UINT64_C(0), numEdges),
705  [&](uint64_t e) { edgeDataCopy(edgeData, edgeData_new, e, e); },
706  galois::no_stats(), galois::loopname("TRANSPOSE_EDGEDATA_SET"));
707  }
708 
709  timer.stop();
710  }
711 
712  template <bool is_non_void = EdgeData::has_value>
713  void edgeDataCopy(EdgeData& edgeData_new, EdgeData& edgeData, uint64_t e_new,
714  uint64_t e,
715  typename std::enable_if<is_non_void>::type* = 0) {
716  edgeData_new[e_new] = edgeData[e];
717  }
718 
719  template <bool is_non_void = EdgeData::has_value>
720  void edgeDataCopy(EdgeData&, EdgeData&, uint64_t, uint64_t,
721  typename std::enable_if<!is_non_void>::type* = 0) {
722  // does nothing
723  }
724 
725  template <typename E = EdgeTy,
726  std::enable_if_t<!std::is_same<E, void>::value, int>* = nullptr>
727  void constructFrom(FileGraph& graph, unsigned tid, unsigned total,
728  const bool readUnweighted = false) {
729  // at this point memory should already be allocated
730  auto r =
731  graph
732  .divideByNode(
733  NodeData::size_of::value + EdgeIndData::size_of::value +
734  LC_CSR_Graph::size_of_out_of_line::value,
735  EdgeDst::size_of::value + EdgeData::size_of::value, tid, total)
736  .first;
737 
738  this->setLocalRange(*r.first, *r.second);
739 
740  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
741  nodeData.constructAt(*ii);
742  edgeIndData[*ii] = *graph.edge_end(*ii);
743 
744  this->outOfLineConstructAt(*ii);
745 
746  for (FileGraph::edge_iterator nn = graph.edge_begin(*ii),
747  en = graph.edge_end(*ii);
748  nn != en; ++nn) {
749  if (readUnweighted) {
750  edgeData.set(*nn, {});
751  } else {
752  constructEdgeValue(graph, nn);
753  }
754  edgeDst[*nn] = graph.getEdgeDst(nn);
755  }
756  }
757  }
758 
759  template <typename E = EdgeTy,
760  std::enable_if_t<std::is_same<E, void>::value, int>* = nullptr>
761  void constructFrom(FileGraph& graph, unsigned tid, unsigned total,
762  const bool GALOIS_UNUSED(readUnweighted) = false) {
763  // at this point memory should already be allocated
764  auto r =
765  graph
766  .divideByNode(
767  NodeData::size_of::value + EdgeIndData::size_of::value +
768  LC_CSR_Graph::size_of_out_of_line::value,
769  EdgeDst::size_of::value + EdgeData::size_of::value, tid, total)
770  .first;
771 
772  this->setLocalRange(*r.first, *r.second);
773 
774  for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
775  nodeData.constructAt(*ii);
776  edgeIndData[*ii] = *graph.edge_end(*ii);
777 
778  this->outOfLineConstructAt(*ii);
779 
780  for (FileGraph::edge_iterator nn = graph.edge_begin(*ii),
781  en = graph.edge_end(*ii);
782  nn != en; ++nn) {
783  constructEdgeValue(graph, nn);
784  edgeDst[*nn] = graph.getEdgeDst(nn);
785  }
786  }
787  }
788 
795  const EdgeIndData& getEdgePrefixSum() const { return edgeIndData; }
796 
797  auto divideByNode(size_t nodeSize, size_t edgeSize, size_t id, size_t total) {
799  numNodes, numEdges, nodeSize, edgeSize, id, total, edgeIndData);
800  }
807  void constructFrom(uint32_t numNodes, uint64_t numEdges,
808  std::vector<uint64_t>& prefix_sum,
809  std::vector<std::vector<uint32_t>>& edges_id,
810  std::vector<std::vector<EdgeTy>>& edges_data) {
811  // allocateFrom(numNodes, numEdges);
812  /*
813  * Deallocate if reusing the graph
814  */
815  destroyAndAllocateFrom(numNodes, numEdges);
816  constructNodes();
817 
818  galois::do_all(galois::iterate((uint32_t)0, numNodes),
819  [&](uint32_t n) { edgeIndData[n] = prefix_sum[n]; });
820 
821  galois::do_all(galois::iterate((uint32_t)0, numNodes), [&](uint32_t n) {
822  if (n == 0) {
823  if (edgeIndData[n] > 0) {
824  std::copy(edges_id[n].begin(), edges_id[n].end(), edgeDst.begin());
825  std::copy(edges_data[n].begin(), edges_data[n].end(),
826  edgeData.begin());
827  }
828  } else {
829  if (edgeIndData[n] - edgeIndData[n - 1] > 0) {
830  std::copy(edges_id[n].begin(), edges_id[n].end(),
831  edgeDst.begin() + edgeIndData[n - 1]);
832  std::copy(edges_data[n].begin(), edges_data[n].end(),
833  edgeData.begin() + edgeIndData[n - 1]);
834  }
835  }
836  });
837 
839  }
841  uint32_t numNodes, uint64_t numEdges, std::vector<uint64_t>& prefix_sum,
843  std::vector<std::vector<EdgeTy>>& edges_data) {
844  allocateFrom(numNodes, numEdges);
845  constructNodes();
846 
847  galois::do_all(galois::iterate((uint32_t)0, numNodes),
848  [&](uint32_t n) { edgeIndData[n] = prefix_sum[n]; });
849 
850  galois::do_all(galois::iterate((uint32_t)0, numNodes), [&](uint32_t n) {
851  if (n == 0) {
852  if (edgeIndData[n] > 0) {
853  std::copy(edges_id[n].begin(), edges_id[n].end(), edgeDst.begin());
854  std::copy(edges_data[n].begin(), edges_data[n].end(),
855  edgeData.begin());
856  }
857  } else {
858  if (edgeIndData[n] - edgeIndData[n - 1] > 0) {
859  std::copy(edges_id[n].begin(), edges_id[n].end(),
860  edgeDst.begin() + edgeIndData[n - 1]);
861  std::copy(edges_data[n].begin(), edges_data[n].end(),
862  edgeData.begin() + edgeIndData[n - 1]);
863  }
864  }
865  });
866 
868  }
869 
877  template <
878  typename U = void,
879  typename std::enable_if<!std::is_void<EdgeTy>::value, U>::type* = nullptr>
880  void readGraphFromGRFile(const std::string& filename) {
881  std::ifstream graphFile(filename.c_str());
882  if (!graphFile.is_open()) {
883  GALOIS_DIE("failed to open file");
884  }
885  uint64_t header[4];
886  graphFile.read(reinterpret_cast<char*>(header), sizeof(uint64_t) * 4);
887  uint64_t version = header[0];
888  numNodes = header[2];
889  numEdges = header[3];
890  galois::gPrint("Number of Nodes: ", numNodes,
891  ", Number of Edges: ", numEdges, "\n");
892  allocateFrom(numNodes, numEdges);
893  constructNodes();
897  assert(edgeIndData.data());
898  if (!edgeIndData.data()) {
899  GALOIS_DIE("out of memory");
900  }
901 
902  // start position to read index data
903  uint64_t readPosition = (4 * sizeof(uint64_t));
904  graphFile.seekg(readPosition);
905  graphFile.read(reinterpret_cast<char*>(edgeIndData.data()),
906  sizeof(uint64_t) * numNodes);
910  assert(edgeDst.data());
911  if (!edgeDst.data()) {
912  GALOIS_DIE("out of memory");
913  }
914 
915  readPosition = ((4 + numNodes) * sizeof(uint64_t));
916  graphFile.seekg(readPosition);
917  if (version == 1) {
918  graphFile.read(reinterpret_cast<char*>(edgeDst.data()),
919  sizeof(uint32_t) * numEdges);
920  readPosition =
921  ((4 + numNodes) * sizeof(uint64_t) + numEdges * sizeof(uint32_t));
922  // version 1 padding TODO make version agnostic
923  if (numEdges % 2) {
924  readPosition += sizeof(uint32_t);
925  }
926  } else if (version == 2) {
927  graphFile.read(reinterpret_cast<char*>(edgeDst.data()),
928  sizeof(uint64_t) * numEdges);
929  readPosition =
930  ((4 + numNodes) * sizeof(uint64_t) + numEdges * sizeof(uint64_t));
931  if (numEdges % 2) {
932  readPosition += sizeof(uint64_t);
933  }
934  } else {
935  GALOIS_DIE("unknown file version: ", version);
936  }
940  assert(edgeData.data());
941  if (!edgeData.data()) {
942  GALOIS_DIE("out of memory");
943  }
944  graphFile.seekg(readPosition);
945  graphFile.read(reinterpret_cast<char*>(edgeData.data()),
946  sizeof(EdgeTy) * numEdges);
947 
949  graphFile.close();
950  }
951 
959  template <
960  typename U = void,
961  typename std::enable_if<std::is_void<EdgeTy>::value, U>::type* = nullptr>
962  void readGraphFromGRFile(const std::string& filename) {
963  std::ifstream graphFile(filename.c_str());
964  if (!graphFile.is_open()) {
965  GALOIS_DIE("failed to open file");
966  }
967  uint64_t header[4];
968  graphFile.read(reinterpret_cast<char*>(header), sizeof(uint64_t) * 4);
969  uint64_t version = header[0];
970  numNodes = header[2];
971  numEdges = header[3];
972  galois::gPrint("Number of Nodes: ", numNodes,
973  ", Number of Edges: ", numEdges, "\n");
974  allocateFrom(numNodes, numEdges);
975  constructNodes();
979  assert(edgeIndData.data());
980  if (!edgeIndData.data()) {
981  GALOIS_DIE("out of memory");
982  }
983  // start position to read index data
984  uint64_t readPosition = (4 * sizeof(uint64_t));
985  graphFile.seekg(readPosition);
986  graphFile.read(reinterpret_cast<char*>(edgeIndData.data()),
987  sizeof(uint64_t) * numNodes);
991  assert(edgeDst.data());
992  if (!edgeDst.data()) {
993  GALOIS_DIE("out of memory");
994  }
995  readPosition = ((4 + numNodes) * sizeof(uint64_t));
996  graphFile.seekg(readPosition);
997  if (version == 1) {
998  graphFile.read(reinterpret_cast<char*>(edgeDst.data()),
999  sizeof(uint32_t) * numEdges);
1000  } else if (version == 2) {
1001  graphFile.read(reinterpret_cast<char*>(edgeDst.data()),
1002  sizeof(uint64_t) * numEdges);
1003  } else {
1004  GALOIS_DIE("unknown file version: ", version);
1005  }
1006 
1008  graphFile.close();
1009  }
1010 
1016  galois::on_each([&](unsigned tid, unsigned total) {
1017  auto r = divideByNode(0, 1, tid, total).first;
1018  this->setLocalRange(*r.first, *r.second);
1019  });
1020  }
1021 };
1022 
1023 } // namespace galois::graphs
1024 
1025 #endif
void destroyAndAllocateFrom(uint32_t nNodes, uint64_t nEdges)
Definition: LC_CSR_Graph.h:550
void set(difference_type x, const_reference v)
Definition: LargeArray.h:197
Definition: Traits.h:247
const_local_iterator local_end() const
Definition: LC_CSR_Graph.h:415
void constructFrom(FileGraph &graph, unsigned tid, unsigned total, const bool GALOIS_UNUSED(readUnweighted)=false)
Definition: LC_CSR_Graph.h:761
runtime::iterable< NoDerefIterator< edge_iterator > > out_edges(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Graph.h:461
void acquireNode(GraphNode, MethodFlag, typename std::enable_if< _A2 >::type *=0)
Definition: LC_CSR_Graph.h:201
void destroy()
Definition: LargeArray.h:277
EdgeIndData edgeIndData
Definition: LC_CSR_Graph.h:161
size_t size() const
Definition: LC_CSR_Graph.h:405
LC_CSR_Graph< NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc, HasOutOfLineLockable, _file_edge_data > type
Definition: LC_CSR_Graph.h:95
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
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_Graph.h:713
Contains FileGraph and FileGraphWriter class declarations.
iterator const_local_iterator
Definition: LC_CSR_Graph.h:157
LargeArray< EdgeTy > EdgeData
Definition: LC_CSR_Graph.h:134
NodeInfoTypes::reference node_data_reference
Definition: LC_CSR_Graph.h:151
size_t size() const
Returns the number of nodes in the (sub)graph.
Definition: FileGraph.h:545
edge_data_reference getEdgeData(edge_iterator ni, MethodFlag GALOIS_UNUSED(mflag)=MethodFlag::UNPROTECTED)
Definition: LC_CSR_Graph.h:397
NodeTy node_data_type
Definition: LC_CSR_Graph.h:149
void edgeDataCopy(EdgeData &, EdgeData &, uint64_t, uint64_t, typename std::enable_if<!is_non_void >::type *=0)
Definition: LC_CSR_Graph.h:720
edge_sort_iterator edge_sort_begin(GraphNode N)
Definition: LC_CSR_Graph.h:180
Local computation graph (i.e., graph structure does not change).
Definition: LC_CSR_Graph.h:62
void constructEdgeValue(FileGraph &, typename FileGraph::edge_iterator nn, typename std::enable_if< _A1 &&!_A2 >::type *=0)
Definition: LC_CSR_Graph.h:216
void sortEdges(GraphNode N, const CompTy &comp, MethodFlag mflag=MethodFlag::WRITE)
Sorts outgoing edges of a node.
Definition: LC_CSR_Graph.h:484
LC_CSR_Graph< NodeTy, _edge_data, HasNoLockable, UseNumaAlloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Graph.h:88
uint64_t value_type
Definition: LargeArray.h:60
boost::counting_iterator< uint64_t > iterator
uint64 boost counting iterator
Definition: FileGraph.h:408
uint64_t numNodes
Definition: LC_CSR_Graph.h:165
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
read_default_graph_tag read_tag
Definition: LC_CSR_Graph.h:131
LC_CSR_Graph type
Definition: LC_CSR_Graph.h:74
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
Definition: Iterable.h:36
internal::EdgeSortIterator< GraphNode, typename EdgeIndData::value_type, EdgeDst, EdgeData > edge_sort_iterator
Definition: LC_CSR_Graph.h:170
void fixEndEdge(uint32_t n, uint64_t e)
Definition: LC_CSR_Graph.h:609
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_Graph.h:339
iterator end() const
Definition: LC_CSR_Graph.h:409
void deSerializeNodeData(boost::archive::binary_iarchive &ar)
Deserializes a Boost archive containing node data to the local node data variable.
Definition: LC_CSR_Graph.h:292
size_t sizeEdges() const
Definition: LC_CSR_Graph.h:406
void transpose(const char *regionName=NULL)
Perform an in-memory transpose of the graph, replacing the original CSR to CSC.
Definition: LC_CSR_Graph.h:615
const char * loopname
Definition: Executor_ParaMeter.h:145
#define GALOIS_DIE(...)
Definition: gIO.h:96
edge_iterator raw_end(GraphNode N) const
Definition: LC_CSR_Graph.h:176
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
void allocateFrom(uint32_t nNodes, uint64_t nEdges)
Definition: LC_CSR_Graph.h:531
node_data_reference getData(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Graph.h:388
friend void swap(LC_CSR_Graph &lhs, LC_CSR_Graph &rhs)
Definition: LC_CSR_Graph.h:379
iterator const_iterator
Definition: LC_CSR_Graph.h:155
EdgeData edgeData
Definition: LC_CSR_Graph.h:163
EdgeDst edgeDst
Definition: LC_CSR_Graph.h:162
local_iterator local_begin()
Definition: LC_CSR_Graph.h:419
LC_CSR_Graph(uint32_t _numNodes, uint64_t _numEdges, EdgeNumFnTy edgeNum, EdgeDstFnTy _edgeDst, EdgeDataFnTy _edgeData)
Definition: LC_CSR_Graph.h:342
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
Definition: ParallelSTL.h:247
Modify a LC_Graph to have in and out edges.
Definition: LC_InOut_Graph.h:39
NodeData nodeData
Definition: LC_CSR_Graph.h:160
void deSerializeGraph(boost::archive::binary_iarchive &ar)
Deserializes a Boost archive to the local graph.
Definition: LC_CSR_Graph.h:317
const_local_iterator local_begin() const
Definition: LC_CSR_Graph.h:411
LC_CSR_Graph< _node_data, EdgeTy, HasNoLockable, UseNumaAlloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Graph.h:81
void serializeNodeData(boost::archive::binary_oarchive &ar) const
Serializes node data using Boost.
Definition: LC_CSR_Graph.h:282
edge_iterator findEdgeSortedByDst(GraphNode N1, GraphNode N2)
Definition: LC_CSR_Graph.h:447
void sortEdgesByDst(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Sorts outgoing edges of a node.
Definition: LC_CSR_Graph.h:493
void constructEdgeValue(FileGraph &graph, typename FileGraph::edge_iterator nn, typename std::enable_if<!_A1||_A2 >::type *=0)
Definition: LC_CSR_Graph.h:206
void allocateInterleaved(size_type n)
[allocatefunctions] Allocates interleaved across NUMA (memory) nodes.
Definition: LargeArray.h:206
iterator local_iterator
Definition: LC_CSR_Graph.h:156
std::vector< T, Pow2Alloc< T >> Vector
[STL vector using Pow_2_VarSizeAlloc]
Definition: gstl.h:52
value_type & reference
Definition: LargeArray.h:63
GraphNode getEdgeDst(edge_iterator ni)
Definition: LC_CSR_Graph.h:403
edge_iterator edge_begin(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Graph.h:427
LargeArray< NodeInfo > NodeData
Definition: LC_CSR_Graph.h:143
const EdgeIndData & getEdgePrefixSum() const
Returns the reference to the edgeIndData LargeArray (a prefix sum of edges)
Definition: LC_CSR_Graph.h:795
void constructNodes()
Definition: LC_CSR_Graph.h:570
edge_iterator raw_begin(GraphNode N) const
Definition: LC_CSR_Graph.h:172
void gPrint(Args &&...args)
Prints a sequence of things.
Definition: gIO.h:47
Proxy object for internal EdgeSortReference.
Definition: Details.h:56
Definition: Traits.h:206
runtime::iterable< NoDerefIterator< edge_iterator > > edges(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Graph.h:455
If true, use NUMA-aware graph allocation; otherwise, use NUMA interleaved allocation.
Definition: LC_CSR_Graph.h:113
local_iterator local_end()
Definition: LC_CSR_Graph.h:423
LargeArray< uint64_t > EdgeIndData
Definition: LC_CSR_Graph.h:142
void constructEdge(uint64_t e, uint32_t dst, const typename EdgeData::value_type &val)
Definition: LC_CSR_Graph.h:601
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
void sortAllEdgesByDst(MethodFlag mflag=MethodFlag::WRITE)
Sorts all outgoing edges of all nodes in parallel.
Definition: LC_CSR_Graph.h:506
If true, store abstract locks separate from nodes.
Definition: LC_CSR_Graph.h:125
void constructFrom(uint32_t numNodes, uint64_t numEdges, std::vector< uint64_t > &prefix_sum, galois::gstl::Vector< galois::PODResizeableArray< uint32_t >> &edges_id, std::vector< std::vector< EdgeTy >> &edges_data)
Definition: LC_CSR_Graph.h:840
MethodFlag
What should the runtime do when executing a method.
Definition: MethodFlags.h:34
boost::counting_iterator< typename EdgeIndData::value_type > edge_iterator
Definition: LC_CSR_Graph.h:153
void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if<!_A1 &&!_A2 >::type *=0)
Definition: LC_CSR_Graph.h:189
GraphNode getNode(size_t n)
Definition: LC_CSR_Graph.h:223
uint64_t numEdges
Definition: LC_CSR_Graph.h:166
iterator begin() const
Definition: LC_CSR_Graph.h:408
void do_all(const RangeFunc &rangeMaker, FunctionTy &&fn, const Args &...args)
Standard do-all loop.
Definition: Loops.h:71
void serializeGraph(boost::archive::binary_oarchive &ar) const
Serializes graph using Boost.
Definition: LC_CSR_Graph.h:301
void initializeLocalRanges()
Given a manually created graph, initialize the local ranges on this graph so that threads can iterate...
Definition: LC_CSR_Graph.h:1015
void start()
Definition: Timer.cpp:82
void on_each(FunctionTy &&fn, const Args &...args)
Low-level parallel loop.
Definition: Loops.h:86
void constructFrom(uint32_t numNodes, uint64_t numEdges, std::vector< uint64_t > &prefix_sum, std::vector< std::vector< uint32_t >> &edges_id, std::vector< std::vector< EdgeTy >> &edges_data)
custom allocator for vector&lt;vector&lt;&gt;&gt; Adding for Louvain clustering TODO: Find better way to do this ...
Definition: LC_CSR_Graph.h:807
LargeArray< uint32_t > EdgeDst
Definition: LC_CSR_Graph.h:135
void constructFrom(FileGraph &graph, unsigned tid, unsigned total, const bool readUnweighted=false)
Definition: LC_CSR_Graph.h:727
EdgeData::reference edge_data_reference
Definition: LC_CSR_Graph.h:150
size_t getId(GraphNode N)
Definition: LC_CSR_Graph.h:221
EdgeTy & getEdgeData(GraphNode src, GraphNode dst)
Get edge data of an edge between 2 nodes.
Definition: FileGraph.h:241
LC_CSR_Graph< NodeTy, EdgeTy, _has_no_lockable, UseNumaAlloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Graph.h:103
edge_iterator findEdge(GraphNode N1, GraphNode N2)
Definition: LC_CSR_Graph.h:442
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
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
size_t sizeEdges() const
Returns the number of edges in the (sub)graph.
Definition: FileGraph.h:548
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
Definition: LC_CSR_Graph.h:73
Graph that mmaps Galois gr files for access.
Definition: FileGraph.h:57
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
void constructEdge(uint64_t e, uint32_t dst)
Definition: LC_CSR_Graph.h:607
internal::NodeInfoBase< NodeTy,!HasNoLockable &&!HasOutOfLineLockable > NodeInfo
Definition: LC_CSR_Graph.h:141
internal::NodeInfoBaseTypes< NodeTy,!HasNoLockable &&!HasOutOfLineLockable > NodeInfoTypes
Definition: LC_CSR_Graph.h:138
InputIterator find_if(InputIterator first, InputIterator last, Predicate pred)
Definition: ParallelSTL.h:70
void sortEdgesByEdgeData(GraphNode N, const CompTy &comp=std::less< EdgeTy >(), MethodFlag mflag=MethodFlag::WRITE)
Sorts outgoing edges of a node.
Definition: LC_CSR_Graph.h:469
void allocateFrom(const FileGraph &graph)
Definition: LC_CSR_Graph.h:513
If true, do not use abstract locks in graph.
Definition: LC_CSR_Graph.h:100
T value_type
Definition: Executor_ParaMeter.h:111
edge_sort_iterator edge_sort_end(GraphNode N)
Definition: LC_CSR_Graph.h:184
EdgeTy edge_data_type
Definition: LC_CSR_Graph.h:147
LC_CSR_Graph< NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc, _has_out_of_line_lockable, FileEdgeTy > type
Definition: LC_CSR_Graph.h:128
auto divideByNode(size_t nodeSize, size_t edgeSize, size_t id, size_t total)
Definition: LC_CSR_Graph.h:797
void deallocate()
Definition: LC_CSR_Graph.h:587
void deallocate()
Definition: LargeArray.h:271
uint32_t GraphNode
Definition: LC_CSR_Graph.h:146
LC_CSR_Graph< NodeTy, EdgeTy, HasNoLockable, _use_numa_alloc, HasOutOfLineLockable, FileEdgeTy > type
Definition: LC_CSR_Graph.h:116
void stop()
Definition: Timer.cpp:87
edge_iterator edge_end(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_Graph.h:437
void readGraphFromGRFile(const std::string &filename)
Reads the GR files directly into in-memory data-structures of LC_CSR graphs using freads...
Definition: LC_CSR_Graph.h:880
Galois Timer that automatically reports stats upon destruction Provides statistic interface around ti...
Definition: Timer.h:63
FileEdgeTy file_edge_data_type
Definition: LC_CSR_Graph.h:148
void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if< _A1 &&!_A2 >::type *=0)
Definition: LC_CSR_Graph.h:195
boost::counting_iterator< typename EdgeDst::value_type > iterator
Definition: LC_CSR_Graph.h:154