00001
00031 #ifndef GALOIS_GRAPHS_FILEGRAPH_H
00032 #define GALOIS_GRAPHS_FILEGRAPH_H
00033
00034 #include "Galois/Endian.h"
00035 #include "Galois/MethodFlags.h"
00036 #include "Galois/LargeArray.h"
00037 #include "Galois/Runtime/Context.h"
00038 #include "Galois/Runtime/ll/CacheLineStorage.h"
00039
00040 #include <boost/iterator/counting_iterator.hpp>
00041 #include <boost/iterator/transform_iterator.hpp>
00042 #include <boost/type_traits/is_pod.hpp>
00043 #include <boost/utility.hpp>
00044
00045 #include <map>
00046 #include <vector>
00047 #include <fstream>
00048
00049 #include <string.h>
00050
00051 namespace Galois {
00052 namespace Graph {
00053
00055 class FileGraph: boost::noncopyable {
00056 public:
00057 typedef uint32_t GraphNode;
00058
00059 protected:
00060 void* volatile masterMapping;
00061 size_t masterLength;
00062 uint64_t sizeEdgeTy;
00063 int masterFD;
00064
00065 uint64_t* outIdx;
00066 uint32_t* outs;
00067
00068 char* edgeData;
00069
00070 uint64_t numEdges;
00071 uint64_t numNodes;
00072
00073 uint64_t getEdgeIdx(GraphNode src, GraphNode dst) const;
00074 uint32_t* raw_neighbor_begin(GraphNode N) const;
00075 uint32_t* raw_neighbor_end(GraphNode N) const;
00076
00077 struct Convert32: public std::unary_function<uint32_t, uint32_t> {
00078 uint32_t operator()(uint32_t x) const {
00079 return le32toh(x);
00080 }
00081 };
00082
00083 struct Convert64: public std::unary_function<uint64_t,uint64_t> {
00084 uint64_t operator()(uint64_t x) const {
00085 return le64toh(x);
00086 }
00087 };
00088
00090 void parse(void* m);
00091
00092 public:
00093
00094
00096 bool containsNode(const GraphNode n) const;
00097
00098
00099 template<typename EdgeTy>
00100 EdgeTy& getEdgeData(GraphNode src, GraphNode dst) {
00101 assert(sizeEdgeTy == sizeof(EdgeTy));
00102 return reinterpret_cast<EdgeTy*>(edgeData)[getEdgeIdx(src, dst)];
00103 }
00104
00105
00106 typedef boost::counting_iterator<uint64_t> edge_iterator;
00107 edge_iterator edge_begin(GraphNode N) const;
00108 edge_iterator edge_end(GraphNode N) const;
00109
00110 template<typename EdgeTy> EdgeTy& getEdgeData(edge_iterator it) const {
00111 return reinterpret_cast<EdgeTy*>(edgeData)[*it];
00112 }
00113
00114 GraphNode getEdgeDst(edge_iterator it) const;
00115
00116 typedef boost::transform_iterator<Convert32, uint32_t*> neighbor_iterator;
00117 typedef boost::transform_iterator<Convert32, uint32_t*> node_id_iterator;
00118 typedef boost::transform_iterator<Convert64, uint64_t*> edge_id_iterator;
00119
00120 neighbor_iterator neighbor_begin(GraphNode N) const {
00121 return boost::make_transform_iterator(raw_neighbor_begin(N), Convert32());
00122 }
00123
00124 neighbor_iterator neighbor_end(GraphNode N) const {
00125 return boost::make_transform_iterator(raw_neighbor_end(N), Convert32());
00126 }
00127
00128 node_id_iterator node_id_begin() const;
00129 node_id_iterator node_id_end() const;
00130 edge_id_iterator edge_id_begin() const;
00131 edge_id_iterator edge_id_end() const;
00132
00133 template<typename EdgeTy>
00134 EdgeTy& getEdgeData(neighbor_iterator it) {
00135 return reinterpret_cast<EdgeTy*>(edgeData)[std::distance(outs, it.base())];
00136 }
00137
00138 template<typename EdgeTy>
00139 EdgeTy* edge_data_begin() const {
00140 return reinterpret_cast<EdgeTy*>(edgeData);
00141 }
00142
00143 template<typename EdgeTy>
00144 EdgeTy* edge_data_end() const {
00145 assert(sizeof(EdgeTy) == sizeEdgeTy);
00146 EdgeTy* r = reinterpret_cast<EdgeTy*>(edgeData);
00147 return &r[numEdges];
00148 }
00149
00150 bool hasNeighbor(GraphNode N1, GraphNode N2) const;
00151
00152 typedef boost::counting_iterator<uint64_t> iterator;
00153
00155 iterator begin() const;
00156
00157 iterator end() const;
00158
00160 unsigned int size() const;
00161
00163 unsigned int sizeEdges() const;
00164
00165 FileGraph();
00166 ~FileGraph();
00167
00169 void structureFromFile(const std::string& filename);
00170
00172 void structureFromMem(void* mem, size_t len, bool clone);
00173
00177 char* structureFromArrays(uint64_t* outIdxs, uint64_t numNodes,
00178 uint32_t* outs, uint64_t numEdges, size_t sizeofEdgeData);
00179
00180
00181 #if 0
00183 template<typename TyG>
00184 void structureFromGraph(TyG& G) {
00185 uint64_t num_nodes = G.size();
00186
00187 typedef typename TyG::GraphNode GNode;
00188 typedef typename TyG::EdgeDataTy EdgeData;
00189
00190 typedef std::vector<GNode> Nodes;
00191 Nodes nodes(G.begin(), G.end());
00192
00193
00194 uint64_t num_edges = 0;
00195 std::vector<uint64_t> out_idx;
00196 std::map<typename TyG::GraphNode, uint32_t> node_ids;
00197 for (uint32_t id = 0; id < num_nodes; ++id) {
00198 GNode& node = nodes[id];
00199 node_ids[node] = id;
00200 num_edges += G.neighborsSize(node);
00201 out_idx.push_back(num_edges);
00202 }
00203
00204
00205 std::vector<uint32_t> outs;
00206 for (typename Nodes::iterator ii = nodes.begin(), ee = nodes.end();
00207 ii != ee; ++ii) {
00208 for (typename TyG::neighbor_iterator ni = G.neighbor_begin(*ii),
00209 ne = G.neighbor_end(*ii); ni != ne; ++ni) {
00210 uint32_t id = node_ids[*ni];
00211 outs.push_back(id);
00212 }
00213 }
00214
00215 EdgeData* edgeData = (EdgeData*) structureFromArrays(&out_idx[0], num_nodes,
00216 &outs[0], num_edges, sizeof(EdgeData));
00217
00218 if (sizeof(EdgeData)) {
00219 for (typename Nodes::iterator ii = nodes.begin(), ee = nodes.end();
00220 ii != ee; ++ii) {
00221 for (typename TyG::neighbor_iterator ni = G.neighbor_begin(*ii),
00222 ne = G.neighbor_end(*ii); ni != ne; ++ni) {
00223 *edgeData++ = G.getEdgeData(*ii, *ni);
00224 }
00225 }
00226 }
00227 }
00228 #endif
00229
00231 void structureToFile(const char* file);
00232
00233 void swap(FileGraph& other);
00234 void clone(FileGraph& other);
00235 };
00236
00249 class FileGraphParser: public FileGraph {
00250 uint64_t *outIdx;
00251 uint32_t *starts;
00252 uint32_t *outs;
00253 size_t sizeofEdgeData;
00254
00255 public:
00256 FileGraphParser(): outIdx(0), starts(0), outs(0), sizeofEdgeData(0) { }
00257
00258 ~FileGraphParser() {
00259 if (outIdx)
00260 delete [] outIdx;
00261 if (starts)
00262 delete [] starts;
00263 if (outs)
00264 delete [] outs;
00265 }
00266
00267 void setNumNodes(uint64_t n) { this->numNodes = n; }
00268 void setNumEdges(uint64_t n) { this->numEdges = n; }
00269 void setSizeofEdgeData(size_t n) { sizeofEdgeData = n; }
00270
00273 void phase1() {
00274 assert(!outIdx);
00275 outIdx = new uint64_t[this->numNodes];
00276 memset(outIdx, 0, sizeof(*outIdx) * this->numNodes);
00277 }
00278
00280 void incrementDegree(size_t id, int delta = 1) {
00281 assert(id < this->numNodes);
00282 outIdx[id] += delta;
00283 }
00284
00286 void phase2() {
00287 if (this->numNodes == 0)
00288 return;
00289
00290
00291 uint64_t* prev = outIdx;
00292 for (uint64_t *ii = outIdx + 1, *ei = outIdx + this->numNodes; ii != ei; ++ii, ++prev) {
00293 *ii += *prev;
00294 }
00295 assert(outIdx[this->numNodes-1] == this->numEdges);
00296
00297 starts = new uint32_t[this->numNodes];
00298 memset(starts, 0, sizeof(*starts) * this->numNodes);
00299
00300 outs = new uint32_t[this->numEdges];
00301 }
00302
00304 size_t addNeighbor(size_t src, size_t dst) {
00305 size_t base = src ? outIdx[src-1] : 0;
00306 size_t idx = base + starts[src]++;
00307 assert(idx < outIdx[src]);
00308 outs[idx] = dst;
00309 return idx;
00310 }
00311
00316 char* finish() {
00317 structureFromArrays(outIdx, this->numNodes, outs, this->numEdges, sizeofEdgeData);
00318 delete [] outIdx;
00319 outIdx = 0;
00320 delete [] starts;
00321 starts = 0;
00322 delete [] outs;
00323 outs = 0;
00324 return this->edgeData;
00325 }
00326 };
00327
00333 template<typename EdgeTy>
00334 void makeSymmetric(FileGraph& in, FileGraph& out) {
00335 typedef FileGraph::GraphNode GNode;
00336 typedef LargeArray<EdgeTy,boost::is_pod<EdgeTy>::value> EdgeData;
00337 typedef typename EdgeData::value_type edge_value_type;
00338
00339 FileGraphParser g;
00340 EdgeData edgeData;
00341
00342 size_t numEdges = in.sizeEdges() * 2;
00343 g.setNumNodes(in.size());
00344 g.setNumEdges(numEdges);
00345 g.setSizeofEdgeData(EdgeData::has_value ? sizeof(edge_value_type) : 0);
00346
00347 g.phase1();
00348 for (FileGraph::iterator ii = in.begin(), ei = in.end(); ii != ei; ++ii) {
00349 GNode src = *ii;
00350 for (FileGraph::edge_iterator jj = in.edge_begin(src), ej = in.edge_end(src); jj != ej; ++jj) {
00351 GNode dst = in.getEdgeDst(jj);
00352 g.incrementDegree(src);
00353 g.incrementDegree(dst);
00354 }
00355 }
00356
00357 g.phase2();
00358 edgeData.allocate(numEdges);
00359 for (FileGraph::iterator ii = in.begin(), ei = in.end(); ii != ei; ++ii) {
00360 GNode src = *ii;
00361 for (FileGraph::edge_iterator jj = in.edge_begin(src), ej = in.edge_end(src); jj != ej; ++jj) {
00362 GNode dst = in.getEdgeDst(jj);
00363 if (EdgeData::has_value) {
00364 edge_value_type& data = in.getEdgeData<edge_value_type>(jj);
00365 edgeData.set(g.addNeighbor(src, dst), data);
00366 edgeData.set(g.addNeighbor(dst, src), data);
00367 } else {
00368 g.addNeighbor(src, dst);
00369 g.addNeighbor(dst, src);
00370 }
00371 }
00372 }
00373
00374 char *rawEdgeData = g.finish();
00375 if (EdgeData::has_value)
00376 std::copy(edgeData.begin(), edgeData.end(), reinterpret_cast<edge_value_type*>(rawEdgeData));
00377
00378 out.swap(g);
00379 }
00380
00383 template<typename NodeTy, typename EdgeTy>
00384 class LC_FileGraph : public FileGraph {
00385
00386 struct gNode : public GaloisRuntime::Lockable {
00387 NodeTy data;
00388 gNode() {}
00389 };
00390
00391
00392 GaloisRuntime::LL::CacheLineStorage<gNode>* nodeData;
00393
00394 public:
00395 GALOIS_ATTRIBUTE_DEPRECATED
00396 LC_FileGraph(): nodeData(0) { }
00397
00398 ~LC_FileGraph() {
00399 if (nodeData)
00400 delete[] nodeData;
00401 }
00402
00403 NodeTy& getData(GraphNode N, MethodFlag mflag = ALL) {
00404 GaloisRuntime::acquire(&nodeData[N].data, mflag);
00405 return nodeData[N].data.data;
00406 }
00407
00408 EdgeTy& getEdgeData(GraphNode src, GraphNode dst, MethodFlag mflag = ALL) {
00409 return FileGraph::getEdgeData<EdgeTy>(src, dst, mflag);
00410 }
00411
00412 EdgeTy& getEdgeData(FileGraph::edge_iterator it, MethodFlag mflag = ALL) {
00413 return FileGraph::getEdgeData<EdgeTy>(it, mflag);
00414 }
00415
00416 EdgeTy& getEdgeData(FileGraph::neighbor_iterator it, MethodFlag mflag = ALL) {
00417 return FileGraph::getEdgeData<EdgeTy>(it, mflag);
00418 }
00419
00420 neighbor_iterator neighbor_begin(GraphNode N, MethodFlag mflag = ALL) const {
00421 return FileGraph::neighbor_begin(N);
00422 }
00423
00424 neighbor_iterator neighbor_end(GraphNode N, MethodFlag mflag = ALL) const {
00425 return FileGraph::neighbor_end(N);
00426 }
00427
00429 void nodeDataFromFile(const char* filename) {
00430 emptyNodeData();
00431 std::ifstream file(filename);
00432 for (uint64_t i = 0; i < size(); ++i)
00433 file >> nodeData[i];
00434 }
00435
00437 void emptyNodeData(NodeTy init = NodeTy()) {
00438 nodeData = new GaloisRuntime::LL::CacheLineStorage<gNode>[size()];
00439 for (uint64_t i = 0; i < size(); ++i)
00440 nodeData[i].data.data = init;
00441 }
00442
00443 void swap(LC_FileGraph& other) {
00444 std::swap(nodeData, other.nodeData);
00445 FileGraph::swap(other);
00446 }
00447
00448 void clone(LC_FileGraph& other) {
00449 nodeData = other.nodeData;
00450 FileGraph::clone(other);
00451 }
00452
00453 template<typename GTy>
00454 void copyGraph(GTy& graph) {
00455 structureFromGraph(graph);
00456 emptyNodeData();
00457 int i = 0;
00458 for (typename GTy::iterator ii = graph.begin(), ee = graph.end(); ii != ee; ++ii, ++i)
00459 nodeData[i].data.data = graph.getData(*ii);
00460 }
00461 };
00462
00464 template<typename EdgeTy>
00465 class LC_FileGraph<void, EdgeTy> : public FileGraph {
00466 struct gNode : public GaloisRuntime::Lockable {
00467 gNode() {}
00468 };
00469
00470
00471 GaloisRuntime::LL::CacheLineStorage<gNode>* nodeData;
00472
00473 public:
00474 GALOIS_ATTRIBUTE_DEPRECATED
00475 LC_FileGraph(): nodeData(0) {}
00476 ~LC_FileGraph() {
00477 if (nodeData)
00478 delete[] nodeData;
00479 }
00480
00481 EdgeTy& getEdgeData(GraphNode src, GraphNode dst, MethodFlag mflag = ALL) {
00482 return FileGraph::getEdgeData<EdgeTy>(src, dst, mflag);
00483 }
00484 EdgeTy& getEdgeData(FileGraph::edge_iterator it, MethodFlag mflag = ALL) {
00485 return FileGraph::getEdgeData<EdgeTy>(it, mflag);
00486 }
00487 EdgeTy& getEdgeData(FileGraph::neighbor_iterator it, MethodFlag mflag = ALL) {
00488 return FileGraph::getEdgeData<EdgeTy>(it, mflag);
00489 }
00490 neighbor_iterator neighbor_begin(GraphNode N, MethodFlag mflag = ALL) const {
00491 return FileGraph::neighbor_begin(N);
00492 }
00493 neighbor_iterator neighbor_end(GraphNode N, MethodFlag mflag = ALL) const {
00494 return FileGraph::neighbor_end(N);
00495 }
00496 };
00497
00498 template<typename NodeTy>
00499 class LC_FileGraph<NodeTy, void>: public FileGraph {
00500 struct gNode : public GaloisRuntime::Lockable {
00501 NodeTy data;
00502 gNode() {}
00503 };
00504
00505
00506 GaloisRuntime::LL::CacheLineStorage<gNode>* nodeData;
00507
00508 public:
00509 GALOIS_ATTRIBUTE_DEPRECATED
00510 LC_FileGraph(): nodeData(0) {}
00511 ~LC_FileGraph() {
00512 if (nodeData)
00513 delete[] nodeData;
00514 }
00515
00516 NodeTy& getData(GraphNode N, MethodFlag mflag = ALL) {
00517 GaloisRuntime::acquire(&nodeData[N].data, mflag);
00518 return nodeData[N].data.data;
00519 }
00520
00521 void nodeDataFromFile(const char* filename) {
00522 emptyNodeData();
00523 std::ifstream file(filename);
00524 for (uint64_t i = 0; i < numNodes; ++i)
00525 file >> nodeData[i];
00526 }
00527
00528 void emptyNodeData(NodeTy init = NodeTy()) {
00529 nodeData = new GaloisRuntime::LL::CacheLineStorage<gNode>[numNodes];
00530 for (uint64_t i = 0; i < numNodes; ++i)
00531 nodeData[i].data.data = init;
00532 }
00533
00534 neighbor_iterator neighbor_begin(GraphNode N, MethodFlag mflag = ALL) const {
00535 return FileGraph::neighbor_begin(N);
00536 }
00537
00538 neighbor_iterator neighbor_end(GraphNode N, MethodFlag mflag = ALL) const {
00539 return FileGraph::neighbor_end(N);
00540 }
00541 };
00542
00543 template<>
00544 class LC_FileGraph<void, void>: public FileGraph {
00545 public:
00546 GALOIS_ATTRIBUTE_DEPRECATED
00547 LC_FileGraph() { }
00548 neighbor_iterator neighbor_begin(GraphNode N, MethodFlag mflag = ALL) const {
00549 return FileGraph::neighbor_begin(N);
00550 }
00551 neighbor_iterator neighbor_end(GraphNode N, MethodFlag mflag = ALL) const {
00552 return FileGraph::neighbor_end(N);
00553 }
00554 };
00555
00556 }
00557 }
00558 #endif