Galois
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
LC_CSR_CSC_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 
25 #ifndef GALOIS_GRAPHS_LC_CSR_CSC_GRAPH_H
26 #define GALOIS_GRAPHS_LC_CSR_CSC_GRAPH_H
27 
28 #include "galois/config.h"
29 
31 
32 namespace galois {
33 namespace graphs {
34 
51 template <typename NodeTy, typename EdgeTy, bool EdgeDataByValue = false,
52  bool HasNoLockable = false, bool UseNumaAlloc = false,
53  bool HasOutOfLineLockable = false, typename FileEdgeTy = EdgeTy>
55  : public LC_CSR_Graph<NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc,
56  HasOutOfLineLockable, FileEdgeTy> {
57  // typedef to make it easier to read
59  using BaseGraph = LC_CSR_Graph<NodeTy, EdgeTy, HasNoLockable, UseNumaAlloc,
60  HasOutOfLineLockable, FileEdgeTy>;
62  using ThisGraph =
63  LC_CSR_CSC_Graph<NodeTy, EdgeTy, EdgeDataByValue, HasNoLockable,
64  UseNumaAlloc, HasOutOfLineLockable, FileEdgeTy>;
65 
66 public:
68  using GraphNode = uint32_t;
69 
70 protected:
71  // retypedefs of base class
78 
79 public:
81  using edge_iterator =
82  boost::counting_iterator<typename EdgeIndData::value_type>;
85 
86 protected:
94  using EdgeDataRep =
95  typename std::conditional<EdgeDataByValue, EdgeData, EdgeIndData>::type;
98 
100  using edge_sort_iterator =
101  internal::EdgeSortIterator<GraphNode, typename EdgeIndData::value_type,
103 
107  }
108 
112  }
113 
120  template <bool A = EdgeDataByValue,
121  typename std::enable_if<A>::type* = nullptr>
122  void createEdgeData(const uint64_t e_new, const uint64_t e) {
124  }
125 
133  template <bool A = EdgeDataByValue,
134  typename std::enable_if<!A>::type* = nullptr>
135  void createEdgeData(const uint64_t e_new, const uint64_t e) {
136  if (!std::is_void<EdgeTy>::value) {
137  inEdgeData[e_new] = e;
138  }
139  }
140 
151  // counting outgoing edges in the tranpose graph by
152  // counting incoming edges in the original graph
154  [&](uint64_t e) {
155  auto dst = BaseGraph::edgeDst[e];
156  __sync_add_and_fetch(&(dataBuffer[dst]), 1);
157  });
158 
159  // prefix sum calculation of the edge index array
160  for (uint32_t n = 1; n < BaseGraph::numNodes; ++n) {
161  dataBuffer[n] += dataBuffer[n - 1];
162  }
163 
164  // copy over the new tranposed edge index data
165  inEdgeIndData.allocateInterleaved(BaseGraph::numNodes);
166  galois::do_all(galois::iterate(UINT64_C(0), BaseGraph::numNodes),
167  [&](uint64_t n) { inEdgeIndData[n] = dataBuffer[n]; });
168  }
169 
177  // after this block dataBuffer[i] will now hold number of edges that all
178  // nodes before the ith node have; used to determine where to start
179  // saving an edge for a node
180  if (BaseGraph::numNodes >= 1) {
181  dataBuffer[0] = 0;
183  [&](uint64_t n) { dataBuffer[n] = inEdgeIndData[n - 1]; });
184  }
185 
186  // allocate edge dests and data
188 
189  if (!std::is_void<EdgeTy>::value) {
190  inEdgeData.allocateInterleaved(BaseGraph::numEdges);
191  }
192 
194  galois::iterate(UINT64_C(0), BaseGraph::numNodes), [&](uint64_t src) {
195  // e = start index into edge array for a particular node
196  uint64_t e = (src == 0) ? 0 : BaseGraph::edgeIndData[src - 1];
197 
198  // get all outgoing edges of a particular node in the non-transpose
199  // and convert to incoming
200  while (e < BaseGraph::edgeIndData[src]) {
201  // destination nodde
202  auto dst = BaseGraph::edgeDst[e];
203  // location to save edge
204  auto e_new = __sync_fetch_and_add(&(dataBuffer[dst]), 1);
205  // save src as destination
206  inEdgeDst[e_new] = src;
207  // edge data to "new" array
208  createEdgeData(e_new, e);
209  e++;
210  }
211  });
212  }
213 
214 public:
216  LC_CSR_CSC_Graph() = default;
218  LC_CSR_CSC_Graph(LC_CSR_CSC_Graph&& rhs) = default;
221 
223  // Construction functions
225 
231  galois::StatTimer incomingEdgeConstructTimer("IncomingEdgeConstruct");
232  incomingEdgeConstructTimer.start();
233 
234  // initialize the temp array
235  EdgeIndData dataBuffer;
238  [&](uint64_t n) { dataBuffer[n] = 0; });
239 
240  determineInEdgeIndices(dataBuffer);
241  determineInEdgeDestAndData(dataBuffer);
242 
243  incomingEdgeConstructTimer.stop();
244  }
245 
247  // Access functions
249 
257  return edge_iterator((N == 0) ? 0 : inEdgeIndData[N - 1]);
258  }
259 
268  return edge_iterator(inEdgeIndData[N]);
269  }
270 
279  MethodFlag mflag = MethodFlag::WRITE) {
280  BaseGraph::acquireNode(N, mflag);
281  if (!HasNoLockable && galois::runtime::shouldLock(mflag)) {
282  for (edge_iterator ii = in_raw_begin(N), ee = in_raw_end(N); ii != ee;
283  ++ii) {
284  BaseGraph::acquireNode(inEdgeDst[*ii], mflag);
285  }
286  }
287  return in_raw_begin(N);
288  }
289 
298  BaseGraph::acquireNode(N, mflag);
299  return in_raw_end(N);
300  }
301 
309  return internal::make_no_deref_range(in_edge_begin(N, mflag),
310  in_edge_end(N, mflag));
311  }
312 
319  GraphNode getInEdgeDst(edge_iterator ni) const { return inEdgeDst[*ni]; }
320 
330  template <bool A = EdgeDataByValue,
331  typename std::enable_if<A>::type* = nullptr>
334  return inEdgeData[*ni];
335  }
336 
346  template <bool A = EdgeDataByValue,
347  typename std::enable_if<A>::type* = nullptr>
350  return inEdgeData[*ni];
351  }
352 
362  template <bool A = EdgeDataByValue,
363  typename std::enable_if<!A>::type* = nullptr>
366  return BaseGraph::edgeData[inEdgeData[*ni]];
367  }
368 
378  template <bool A = EdgeDataByValue,
379  typename std::enable_if<!A>::type* = nullptr>
382  return BaseGraph::edgeData[inEdgeData[*ni]];
383  }
384 
388  const EdgeIndData& getInEdgePrefixSum() const { return inEdgeIndData; }
389 
391  // Utility
393 
398  BaseGraph::acquireNode(N, mflag);
399  // depending on value/ref the type of EdgeSortValue changes
400  using EdgeSortVal = EdgeSortValue<
401  GraphNode,
402  typename std::conditional<EdgeDataByValue, EdgeTy, uint64_t>::type>;
403 
405  [=](const EdgeSortVal& e1, const EdgeSortVal& e2) {
406  return e1.dst < e2.dst;
407  });
408  }
409 
416  galois::iterate((size_t)0, this->size()),
417  [=](GraphNode N) { this->sortInEdgesByDst(N, mflag); },
419  }
420 
425  void readAndConstructBiGraphFromGRFile(const std::string& filename) {
426  this->readGraphFromGRFile(filename);
428  }
429 };
430 
431 } // namespace graphs
432 } // namespace galois
433 #endif
uint32_t GraphNode
Graph node typedef.
Definition: LC_CSR_CSC_Graph.h:68
Definition: Traits.h:247
LC_CSR_CSC_Graph & operator=(LC_CSR_CSC_Graph &&)=default
default = operator
edge_data_reference getInEdgeData(edge_iterator ni, MethodFlag=MethodFlag::UNPROTECTED)
Given an edge id for in edge, get the data associated with that edge.
Definition: LC_CSR_CSC_Graph.h:348
edge_sort_iterator in_edge_sort_end(GraphNode N)
ending iterator to an edge sorter for in-edges
Definition: LC_CSR_CSC_Graph.h:110
EdgeIndData edgeIndData
Definition: LC_CSR_Graph.h:161
size_t size() const
Definition: LC_CSR_Graph.h:405
typename std::conditional< EdgeDataByValue, EdgeData, EdgeIndData >::type EdgeDataRep
Edge data of inedges can be a value copy of the outedges (i.e.
Definition: LC_CSR_CSC_Graph.h:95
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
Local computation graph (i.e., graph structure does not change).
Definition: LC_CSR_Graph.h:62
void createEdgeData(const uint64_t e_new, const uint64_t e)
Copy the data of outedge by value to inedge.
Definition: LC_CSR_CSC_Graph.h:122
uint64_t value_type
Definition: LargeArray.h:60
uint64_t numNodes
Definition: LC_CSR_Graph.h:165
typename EdgeData::reference edge_data_reference
reference to edge data
Definition: LC_CSR_CSC_Graph.h:84
Definition: Iterable.h:36
internal::EdgeSortIterator< GraphNode, typename EdgeIndData::value_type, EdgeDst, EdgeDataRep > edge_sort_iterator
redefinition of the edge sort iterator in LC_CSR_Graph
Definition: LC_CSR_CSC_Graph.h:102
LargeArray< uint32_t > EdgeDst
large array for edge destinations
Definition: LC_CSR_CSC_Graph.h:75
edge_sort_iterator in_edge_sort_begin(GraphNode N)
beginning iterator to an edge sorter for in-edges
Definition: LC_CSR_CSC_Graph.h:105
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
EdgeData edgeData
Definition: LC_CSR_Graph.h:163
void constructIncomingEdges()
Call only after the LC_CSR_Graph part of this class is fully constructed.
Definition: LC_CSR_CSC_Graph.h:230
EdgeDst edgeDst
Definition: LC_CSR_Graph.h:162
void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
Definition: ParallelSTL.h:247
void determineInEdgeIndices(EdgeIndData &dataBuffer)
Determine the in-edge indices for every node by accumulating how many in-edges each node has...
Definition: LC_CSR_CSC_Graph.h:150
const EdgeIndData & getInEdgePrefixSum() const
Definition: LC_CSR_CSC_Graph.h:388
edge_data_reference getInEdgeData(edge_iterator ni, MethodFlag=MethodFlag::UNPROTECTED) const
Given an edge id for in edge, get the data associated with that edge.
Definition: LC_CSR_CSC_Graph.h:333
void allocateInterleaved(size_type n)
[allocatefunctions] Allocates interleaved across NUMA (memory) nodes.
Definition: LargeArray.h:206
void determineInEdgeDestAndData(EdgeIndData &dataBuffer)
Determine the destination of each in-edge and copy the data associated with an edge (or point to it)...
Definition: LC_CSR_CSC_Graph.h:176
value_type & reference
Definition: LargeArray.h:63
Proxy object for internal EdgeSortReference.
Definition: Details.h:56
edge_iterator in_edge_begin(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Wrapper to get the in edge end of a node; lock if necessary.
Definition: LC_CSR_CSC_Graph.h:278
Definition: Traits.h:206
runtime::iterable< NoDerefIterator< edge_iterator > > in_edges(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Definition: LC_CSR_CSC_Graph.h:308
EdgeIndData inEdgeIndData
edge index data for the reverse edges
Definition: LC_CSR_CSC_Graph.h:88
An bidirectional LC_CSR_Graph that allows the construction of in-edges from its outedges.
Definition: LC_CSR_CSC_Graph.h:54
MethodFlag
What should the runtime do when executing a method.
Definition: MethodFlags.h:34
void sortInEdgesByDst(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Sorts outgoing edges of a node.
Definition: LC_CSR_CSC_Graph.h:397
void readAndConstructBiGraphFromGRFile(const std::string &filename)
Directly reads the GR file to construct CSR graph and then constructs reverse edges based on that...
Definition: LC_CSR_CSC_Graph.h:425
void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if<!_A1 &&!_A2 >::type *=0)
Definition: LC_CSR_Graph.h:189
uint64_t numEdges
Definition: LC_CSR_Graph.h:166
void do_all(const RangeFunc &rangeMaker, FunctionTy &&fn, const Args &...args)
Standard do-all loop.
Definition: Loops.h:71
void start()
Definition: Timer.cpp:82
edge_iterator in_raw_begin(GraphNode N) const
Grabs in edge beginning without lock/safety.
Definition: LC_CSR_CSC_Graph.h:256
void sortAllInEdgesByDst(MethodFlag mflag=MethodFlag::WRITE)
Sorts all incoming edges of all nodes in parallel.
Definition: LC_CSR_CSC_Graph.h:414
edge_iterator in_edge_end(GraphNode N, MethodFlag mflag=MethodFlag::WRITE)
Wrapper to get the in edge end of a node; lock if necessary.
Definition: LC_CSR_CSC_Graph.h:297
auto iterate(C &cont)
Definition: Range.h:323
EdgeDataRep inEdgeData
The data for the reverse edges.
Definition: LC_CSR_CSC_Graph.h:97
EdgeDst inEdgeDst
edge destination data for the reverse edges
Definition: LC_CSR_CSC_Graph.h:90
LC_CSR_CSC_Graph()=default
default constructor
GraphNode getInEdgeDst(edge_iterator ni) const
Given an edge id for in edges, get the destination of the edge.
Definition: LC_CSR_CSC_Graph.h:319
boost::counting_iterator< typename EdgeIndData::value_type > edge_iterator
iterator for edges
Definition: LC_CSR_CSC_Graph.h:82
edge_iterator in_raw_end(GraphNode N) const
Grabs in edge end without lock/safety.
Definition: LC_CSR_CSC_Graph.h:267
void stop()
Definition: Timer.cpp:87
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