00001
00026 #ifndef GALOIS_GRAPH_LC_CSR_GRAPH_H
00027 #define GALOIS_GRAPH_LC_CSR_GRAPH_H
00028
00029 #include "Galois/config.h"
00030 #include "Galois/LargeArray.h"
00031 #include "Galois/Graph/FileGraph.h"
00032 #include "Galois/Graph/Details.h"
00033 #include "Galois/Runtime/MethodFlags.h"
00034
00035 #include GALOIS_CXX11_STD_HEADER(type_traits)
00036
00037 namespace Galois {
00038 namespace Graph {
00039
00090 template<typename NodeTy, typename EdgeTy,
00091 bool HasNoLockable=false,
00092 bool UseNumaAlloc=false,
00093 bool HasOutOfLineLockable=false>
00094 class LC_CSR_Graph:
00095 private boost::noncopyable,
00096 private detail::LocalIteratorFeature<UseNumaAlloc>,
00097 private detail::OutOfLineLockableFeature<HasOutOfLineLockable && !HasNoLockable> {
00098 template<typename Graph> friend class LC_InOut_Graph;
00099
00100 public:
00101 template<bool _has_id>
00102 struct with_id { typedef LC_CSR_Graph type; };
00103
00104 template<typename _node_data>
00105 struct with_node_data { typedef LC_CSR_Graph<_node_data,EdgeTy,HasNoLockable,UseNumaAlloc,HasOutOfLineLockable> type; };
00106
00108 template<bool _has_no_lockable>
00109 struct with_no_lockable { typedef LC_CSR_Graph<NodeTy,EdgeTy,_has_no_lockable,UseNumaAlloc,HasOutOfLineLockable> type; };
00110
00112 template<bool _use_numa_alloc>
00113 struct with_numa_alloc { typedef LC_CSR_Graph<NodeTy,EdgeTy,HasNoLockable,_use_numa_alloc,HasOutOfLineLockable> type; };
00114
00116 template<bool _has_out_of_line_lockable>
00117 struct with_out_of_line_lockable { typedef LC_CSR_Graph<NodeTy,EdgeTy,HasNoLockable,UseNumaAlloc,_has_out_of_line_lockable> type; };
00118
00119 typedef read_default_graph_tag read_tag;
00120
00121 protected:
00122 typedef LargeArray<EdgeTy> EdgeData;
00123 typedef LargeArray<uint32_t> EdgeDst;
00124 typedef detail::NodeInfoBaseTypes<NodeTy,!HasNoLockable && !HasOutOfLineLockable> NodeInfoTypes;
00125 typedef detail::NodeInfoBase<NodeTy,!HasNoLockable && !HasOutOfLineLockable> NodeInfo;
00126 typedef LargeArray<uint64_t> EdgeIndData;
00127 typedef LargeArray<NodeInfo> NodeData;
00128
00129 public:
00130 typedef uint32_t GraphNode;
00131 typedef EdgeTy edge_data_type;
00132 typedef NodeTy node_data_type;
00133 typedef typename EdgeData::reference edge_data_reference;
00134 typedef typename NodeInfoTypes::reference node_data_reference;
00135 typedef boost::counting_iterator<typename EdgeIndData::value_type> edge_iterator;
00136 typedef boost::counting_iterator<typename EdgeDst::value_type> iterator;
00137 typedef iterator const_iterator;
00138 typedef iterator local_iterator;
00139 typedef iterator const_local_iterator;
00140
00141 protected:
00142 NodeData nodeData;
00143 EdgeIndData edgeIndData;
00144 EdgeDst edgeDst;
00145 EdgeData edgeData;
00146
00147 uint64_t numNodes;
00148 uint64_t numEdges;
00149
00150 typedef detail::EdgeSortIterator<GraphNode,typename EdgeIndData::value_type,EdgeDst,EdgeData> edge_sort_iterator;
00151
00152 edge_iterator raw_begin(GraphNode N) const {
00153 return edge_iterator((N == 0) ? 0 : edgeIndData[N-1]);
00154 }
00155
00156 edge_iterator raw_end(GraphNode N) const {
00157 return edge_iterator(edgeIndData[N]);
00158 }
00159
00160 edge_sort_iterator edge_sort_begin(GraphNode N) {
00161 return edge_sort_iterator(*raw_begin(N), &edgeDst, &edgeData);
00162 }
00163
00164 edge_sort_iterator edge_sort_end(GraphNode N) {
00165 return edge_sort_iterator(*raw_end(N), &edgeDst, &edgeData);
00166 }
00167
00168 template<bool _A1 = HasNoLockable, bool _A2 = HasOutOfLineLockable>
00169 void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if<!_A1 && !_A2>::type* = 0) {
00170 Galois::Runtime::acquire(&nodeData[N], mflag);
00171 }
00172
00173 template<bool _A1 = HasOutOfLineLockable, bool _A2 = HasNoLockable>
00174 void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if<_A1 && !_A2>::type* = 0) {
00175 this->outOfLineAcquire(getId(N), mflag);
00176 }
00177
00178 template<bool _A1 = HasOutOfLineLockable, bool _A2 = HasNoLockable>
00179 void acquireNode(GraphNode N, MethodFlag mflag, typename std::enable_if<_A2>::type* = 0) { }
00180
00181 size_t getId(GraphNode N) {
00182 return N;
00183 }
00184
00185 GraphNode getNode(size_t n) {
00186 return n;
00187 }
00188
00189 public:
00190 node_data_reference getData(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00191 Galois::Runtime::checkWrite(mflag, false);
00192 NodeInfo& NI = nodeData[N];
00193 acquireNode(N, mflag);
00194 return NI.getData();
00195 }
00196
00197 edge_data_reference getEdgeData(edge_iterator ni, MethodFlag mflag = MethodFlag::NONE) {
00198 Galois::Runtime::checkWrite(mflag, false);
00199 return edgeData[*ni];
00200 }
00201
00202 GraphNode getEdgeDst(edge_iterator ni) {
00203 return edgeDst[*ni];
00204 }
00205
00206 uint64_t size() const { return numNodes; }
00207 uint64_t sizeEdges() const { return numEdges; }
00208
00209 iterator begin() const { return iterator(0); }
00210 iterator end() const { return iterator(numNodes); }
00211
00212 const_local_iterator local_begin() const { return const_local_iterator(this->localBegin(numNodes)); }
00213 const_local_iterator local_end() const { return const_local_iterator(this->localEnd(numNodes)); }
00214 local_iterator local_begin() { return local_iterator(this->localBegin(numNodes)); }
00215 local_iterator local_end() { return local_iterator(this->localEnd(numNodes)); }
00216
00217 edge_iterator edge_begin(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00218 acquireNode(N, mflag);
00219 if (Galois::Runtime::shouldLock(mflag)) {
00220 for (edge_iterator ii = raw_begin(N), ee = raw_end(N); ii != ee; ++ii) {
00221 acquireNode(edgeDst[*ii], mflag);
00222 }
00223 }
00224 return raw_begin(N);
00225 }
00226
00227 edge_iterator edge_end(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00228 acquireNode(N, mflag);
00229 return raw_end(N);
00230 }
00231
00232 detail::EdgesIterator<LC_CSR_Graph> out_edges(GraphNode N, MethodFlag mflag = MethodFlag::ALL) {
00233 return detail::EdgesIterator<LC_CSR_Graph>(*this, N, mflag);
00234 }
00235
00239 template<typename CompTy>
00240 void sortEdgesByEdgeData(GraphNode N, const CompTy& comp = std::less<EdgeTy>(), MethodFlag mflag = MethodFlag::ALL) {
00241 acquireNode(N, mflag);
00242 std::sort(edge_sort_begin(N), edge_sort_end(N), detail::EdgeSortCompWrapper<EdgeSortValue<GraphNode,EdgeTy>,CompTy>(comp));
00243 }
00244
00248 template<typename CompTy>
00249 void sortEdges(GraphNode N, const CompTy& comp, MethodFlag mflag = MethodFlag::ALL) {
00250 acquireNode(N, mflag);
00251 std::sort(edge_sort_begin(N), edge_sort_end(N), comp);
00252 }
00253
00254 void allocateFrom(FileGraph& graph) {
00255 numNodes = graph.size();
00256 numEdges = graph.sizeEdges();
00257 if (UseNumaAlloc) {
00258 nodeData.allocateLocal(numNodes, false);
00259 edgeIndData.allocateLocal(numNodes, false);
00260 edgeDst.allocateLocal(numEdges, false);
00261 edgeData.allocateLocal(numEdges, false);
00262 this->outOfLineAllocateLocal(numNodes, false);
00263 } else {
00264 nodeData.allocateInterleaved(numNodes);
00265 edgeIndData.allocateInterleaved(numNodes);
00266 edgeDst.allocateInterleaved(numEdges);
00267 edgeData.allocateInterleaved(numEdges);
00268 this->outOfLineAllocateInterleaved(numNodes);
00269 }
00270 }
00271
00272 void constructFrom(FileGraph& graph, unsigned tid, unsigned total) {
00273 auto r = graph.divideBy(
00274 NodeData::size_of::value + EdgeIndData::size_of::value + LC_CSR_Graph::size_of_out_of_line::value,
00275 EdgeDst::size_of::value + EdgeData::size_of::value,
00276 tid, total);
00277 this->setLocalRange(*r.first, *r.second);
00278 for (FileGraph::iterator ii = r.first, ei = r.second; ii != ei; ++ii) {
00279 nodeData.constructAt(*ii);
00280 edgeIndData[*ii] = *graph.edge_end(*ii);
00281 this->outOfLineConstructAt(*ii);
00282 for (FileGraph::edge_iterator nn = graph.edge_begin(*ii), en = graph.edge_end(*ii); nn != en; ++nn) {
00283 if (EdgeData::has_value)
00284 edgeData.set(*nn, graph.getEdgeData<typename EdgeData::value_type>(nn));
00285 edgeDst[*nn] = graph.getEdgeDst(nn);
00286 }
00287 }
00288 }
00289 };
00290
00291 }
00292 }
00293
00294 #endif