00001
00031 #ifndef GALOIS_GRAPH_FILEGRAPH_H
00032 #define GALOIS_GRAPH_FILEGRAPH_H
00033
00034 #include "Galois/Endian.h"
00035 #include "Galois/MethodFlags.h"
00036 #include "Galois/LargeArray.h"
00037 #include "Galois/Graph/Details.h"
00038 #include "Galois/Runtime/Context.h"
00039 #include "Galois/Runtime/ll/CacheLineStorage.h"
00040 #include "Galois/Runtime/ll/CompilerSpecific.h"
00041
00042 #include <boost/iterator/counting_iterator.hpp>
00043 #include <boost/iterator/transform_iterator.hpp>
00044 #include <boost/utility.hpp>
00045
00046 #include GALOIS_CXX11_STD_HEADER(type_traits)
00047
00048
00049 #include <string.h>
00050
00051 namespace Galois {
00052 namespace Graph {
00053
00055 class FileGraph: private boost::noncopyable {
00056 friend class FileGraphAllocator;
00057 public:
00058 typedef uint32_t GraphNode;
00059
00060 protected:
00061 void* volatile masterMapping;
00062 size_t masterLength;
00063 uint64_t sizeofEdge;
00064 int masterFD;
00065
00066 uint64_t* outIdx;
00067 uint32_t* outs;
00068
00069 char* edgeData;
00070
00071 uint64_t numEdges;
00072 uint64_t numNodes;
00073
00074 uint64_t getEdgeIdx(GraphNode src, GraphNode dst) const;
00075 uint32_t* raw_neighbor_begin(GraphNode N) const;
00076 uint32_t* raw_neighbor_end(GraphNode N) const;
00077
00078 struct Convert32: public std::unary_function<uint32_t, uint32_t> {
00079 uint32_t operator()(uint32_t x) const {
00080 return convert_le32(x);
00081 }
00082 };
00083
00084 struct Convert64: public std::unary_function<uint64_t,uint64_t> {
00085 uint64_t operator()(uint64_t x) const {
00086 return convert_le64(x);
00087 }
00088 };
00089
00091 void parse(void* m);
00092
00094 void structureFromMem(void* mem, size_t len, bool clone);
00095
00096 void* structureFromArrays(uint64_t* outIdxs, uint64_t numNodes,
00097 uint32_t* outs, uint64_t numEdges, size_t sizeofEdgeData);
00098
00099 void* structureFromGraph(FileGraph& g, size_t sizeofEdgeData);
00100
00111 size_t findIndex(size_t nodeSize, size_t edgeSize, size_t targetSize, size_t lb, size_t ub);
00112
00113 public:
00114
00115
00117 bool containsNode(const GraphNode n) const {
00118 return n < numNodes;
00119 }
00120
00121
00122 template<typename EdgeTy>
00123 EdgeTy& getEdgeData(GraphNode src, GraphNode dst) {
00124 assert(sizeofEdge == sizeof(EdgeTy));
00125 return reinterpret_cast<EdgeTy*>(edgeData)[getEdgeIdx(src, dst)];
00126 }
00127
00128
00129 typedef boost::counting_iterator<uint64_t> edge_iterator;
00130 edge_iterator edge_begin(GraphNode N) const;
00131 edge_iterator edge_end(GraphNode N) const;
00132
00133 detail::EdgesWithNoFlagIterator<FileGraph> out_edges(GraphNode N) {
00134 return detail::EdgesWithNoFlagIterator<FileGraph>(*this, N);
00135 }
00136
00140 template<typename EdgeTy, typename CompTy>
00141 void sortEdgesByEdgeData(GraphNode N, const CompTy& comp = std::less<EdgeTy>()) {
00142 typedef LargeArray<GraphNode> EdgeDst;
00143 typedef LargeArray<EdgeTy> EdgeData;
00144 typedef detail::EdgeSortIterator<GraphNode,uint64_t,EdgeDst,EdgeData> edge_sort_iterator;
00145
00146 EdgeDst edgeDst(outs, numEdges);
00147 EdgeData ed(edgeData, numEdges);
00148
00149 edge_sort_iterator begin(std::distance(outs, raw_neighbor_begin(N)), &edgeDst, &ed);
00150 edge_sort_iterator end(std::distance(outs, raw_neighbor_end(N)), &edgeDst, &ed);
00151
00152 std::sort(begin, end, detail::EdgeSortCompWrapper<EdgeSortValue<GraphNode,EdgeTy>,CompTy>(comp));
00153 }
00154
00158 template<typename EdgeTy, typename CompTy>
00159 void sortEdges(GraphNode N, const CompTy& comp) {
00160 typedef LargeArray<GraphNode> EdgeDst;
00161 typedef LargeArray<EdgeTy> EdgeData;
00162 typedef detail::EdgeSortIterator<GraphNode,uint64_t,EdgeDst,EdgeData> edge_sort_iterator;
00163
00164 EdgeDst edgeDst(outs, numEdges);
00165 EdgeData ed(edgeData, numEdges);
00166
00167 edge_sort_iterator begin(std::distance(outs, raw_neighbor_begin(N)), &edgeDst, &ed);
00168 edge_sort_iterator end(std::distance(outs, raw_neighbor_end(N)), &edgeDst, &ed);
00169
00170 std::sort(begin, end, comp);
00171 }
00172
00173 template<typename EdgeTy>
00174 EdgeTy& getEdgeData(edge_iterator it) const {
00175 return reinterpret_cast<EdgeTy*>(edgeData)[*it];
00176 }
00177
00178 GraphNode getEdgeDst(edge_iterator it) const;
00179
00180 typedef boost::transform_iterator<Convert32, uint32_t*> neighbor_iterator;
00181 typedef boost::transform_iterator<Convert32, uint32_t*> node_id_iterator;
00182 typedef boost::transform_iterator<Convert64, uint64_t*> edge_id_iterator;
00183 typedef boost::counting_iterator<uint64_t> iterator;
00184
00185 neighbor_iterator neighbor_begin(GraphNode N) const {
00186 return boost::make_transform_iterator(raw_neighbor_begin(N), Convert32());
00187 }
00188
00189 neighbor_iterator neighbor_end(GraphNode N) const {
00190 return boost::make_transform_iterator(raw_neighbor_end(N), Convert32());
00191 }
00192
00193 template<typename EdgeTy>
00194 EdgeTy* edge_data_begin() const {
00195 return reinterpret_cast<EdgeTy*>(edgeData);
00196 }
00197
00198 template<typename EdgeTy>
00199 EdgeTy* edge_data_end() const {
00200 assert(sizeof(EdgeTy) == sizeofEdge);
00201 EdgeTy* r = reinterpret_cast<EdgeTy*>(edgeData);
00202 return &r[numEdges];
00203 }
00204
00205 iterator begin() const;
00206 iterator end() const;
00207
00211 std::pair<iterator,iterator> divideBy(size_t nodeSize, size_t edgeSize, unsigned id, unsigned total);
00212
00213 node_id_iterator node_id_begin() const;
00214 node_id_iterator node_id_end() const;
00215 edge_id_iterator edge_id_begin() const;
00216 edge_id_iterator edge_id_end() const;
00217
00218 template<typename EdgeTy>
00219 EdgeTy& getEdgeData(neighbor_iterator it) {
00220 return reinterpret_cast<EdgeTy*>(edgeData)[std::distance(outs, it.base())];
00221 }
00222
00223 bool hasNeighbor(GraphNode N1, GraphNode N2) const;
00224
00226 unsigned int size() const { return numNodes; }
00227
00229 unsigned int sizeEdges() const { return numEdges; }
00230
00232 size_t edgeSize() const { return sizeofEdge; }
00233
00234 FileGraph();
00235 ~FileGraph();
00236
00238 void structureFromFile(const std::string& filename, bool preFault = true);
00239
00244 void structureFromFileInterleaved(const std::string& filename, size_t sizeofEdgeData);
00245
00246 template<typename EdgeTy>
00247 void structureFromFileInterleaved(const std::string& filename,
00248 typename std::enable_if<!std::is_void<EdgeTy>::value>::type* = 0) {
00249 structureFromFileInterleaved(filename, sizeof(EdgeTy));
00250 }
00251
00252 template<typename EdgeTy>
00253 void structureFromFileInterleaved(const std::string& filename,
00254 typename std::enable_if<std::is_void<EdgeTy>::value>::type* = 0) {
00255 structureFromFileInterleaved(filename, 0);
00256 }
00257
00262 template<typename T>
00263 T* structureFromArrays(uint64_t* outIdxs, uint64_t numNodes,
00264 uint32_t* outs, uint64_t numEdges) {
00265 return reinterpret_cast<T*>(structureFromArrays(outIdx, numNodes, outs, numEdges, sizeof(T)));
00266 }
00267
00272 template<typename T>
00273 T* structureFromGraph(FileGraph& g) {
00274 return reinterpret_cast<T*>(structureFromGraph(g, sizeof(T)));
00275 }
00276
00278 void structureToFile(const std::string& file);
00279
00280 void swap(FileGraph& other);
00281
00282 void cloneFrom(FileGraph& other);
00283 };
00284
00297 class FileGraphWriter: public FileGraph {
00298 uint64_t *outIdx;
00299 uint32_t *starts;
00300 uint32_t *outs;
00301 size_t sizeofEdgeData;
00302
00303 public:
00304 FileGraphWriter(): outIdx(0), starts(0), outs(0), sizeofEdgeData(0) { }
00305
00306 ~FileGraphWriter() {
00307 if (outIdx)
00308 delete [] outIdx;
00309 if (starts)
00310 delete [] starts;
00311 if (outs)
00312 delete [] outs;
00313 }
00314
00315 void setNumNodes(uint64_t n) { this->numNodes = n; }
00316 void setNumEdges(uint64_t n) { this->numEdges = n; }
00317 void setSizeofEdgeData(size_t n) { sizeofEdgeData = n; }
00318
00321 void phase1() {
00322 assert(!outIdx);
00323 outIdx = new uint64_t[this->numNodes];
00324 memset(outIdx, 0, sizeof(*outIdx) * this->numNodes);
00325 }
00326
00328 void incrementDegree(size_t id, int delta = 1) {
00329 assert(id < this->numNodes);
00330 outIdx[id] += delta;
00331 }
00332
00334 void phase2() {
00335 if (this->numNodes == 0)
00336 return;
00337
00338
00339 uint64_t* prev = outIdx;
00340 for (uint64_t *ii = outIdx + 1, *ei = outIdx + this->numNodes; ii != ei; ++ii, ++prev) {
00341 *ii += *prev;
00342 }
00343 assert(outIdx[this->numNodes-1] == this->numEdges);
00344
00345 starts = new uint32_t[this->numNodes];
00346 memset(starts, 0, sizeof(*starts) * this->numNodes);
00347
00348 outs = new uint32_t[this->numEdges];
00349 }
00350
00352 size_t addNeighbor(size_t src, size_t dst) {
00353 size_t base = src ? outIdx[src-1] : 0;
00354 size_t idx = base + starts[src]++;
00355 assert(idx < outIdx[src]);
00356 outs[idx] = dst;
00357 return idx;
00358 }
00359
00364 template<typename T>
00365 T* finish() {
00366 void* ret = structureFromArrays(outIdx, this->numNodes, outs, this->numEdges, sizeofEdgeData);
00367 delete [] outIdx;
00368 outIdx = 0;
00369 delete [] starts;
00370 starts = 0;
00371 delete [] outs;
00372 outs = 0;
00373 return reinterpret_cast<T*>(ret);
00374 }
00375 };
00376
00382 template<typename EdgeTy>
00383 void makeSymmetric(FileGraph& in, FileGraph& out) {
00384 typedef FileGraph::GraphNode GNode;
00385 typedef LargeArray<EdgeTy> EdgeData;
00386 typedef typename EdgeData::value_type edge_value_type;
00387
00388 FileGraphWriter g;
00389 EdgeData edgeData;
00390
00391 size_t numEdges = in.sizeEdges() * 2;
00392 g.setNumNodes(in.size());
00393 g.setNumEdges(numEdges);
00394 g.setSizeofEdgeData(EdgeData::has_value ? sizeof(edge_value_type) : 0);
00395
00396 g.phase1();
00397 for (FileGraph::iterator ii = in.begin(), ei = in.end(); ii != ei; ++ii) {
00398 GNode src = *ii;
00399 for (FileGraph::edge_iterator jj = in.edge_begin(src), ej = in.edge_end(src); jj != ej; ++jj) {
00400 GNode dst = in.getEdgeDst(jj);
00401 g.incrementDegree(src);
00402 g.incrementDegree(dst);
00403 }
00404 }
00405
00406 g.phase2();
00407 edgeData.create(numEdges);
00408 for (FileGraph::iterator ii = in.begin(), ei = in.end(); ii != ei; ++ii) {
00409 GNode src = *ii;
00410 for (FileGraph::edge_iterator jj = in.edge_begin(src), ej = in.edge_end(src); jj != ej; ++jj) {
00411 GNode dst = in.getEdgeDst(jj);
00412 if (EdgeData::has_value) {
00413 edge_value_type& data = in.getEdgeData<edge_value_type>(jj);
00414 edgeData.set(g.addNeighbor(src, dst), data);
00415 edgeData.set(g.addNeighbor(dst, src), data);
00416 } else {
00417 g.addNeighbor(src, dst);
00418 g.addNeighbor(dst, src);
00419 }
00420 }
00421 }
00422
00423 edge_value_type* rawEdgeData = g.finish<edge_value_type>();
00424 if (EdgeData::has_value)
00425 std::copy(edgeData.begin(), edgeData.end(), rawEdgeData);
00426
00427 out.swap(g);
00428 }
00429
00441 template<typename EdgeTy,typename PTy>
00442 void permute(FileGraph& in, const PTy& p, FileGraph& out) {
00443 typedef FileGraph::GraphNode GNode;
00444 typedef LargeArray<EdgeTy> EdgeData;
00445 typedef typename EdgeData::value_type edge_value_type;
00446
00447 FileGraphWriter g;
00448 EdgeData edgeData;
00449
00450 size_t numEdges = in.sizeEdges();
00451 g.setNumNodes(in.size());
00452 g.setNumEdges(numEdges);
00453 g.setSizeofEdgeData(EdgeData::has_value ? sizeof(edge_value_type) : 0);
00454
00455 g.phase1();
00456 for (FileGraph::iterator ii = in.begin(), ei = in.end(); ii != ei; ++ii) {
00457 GNode src = *ii;
00458 for (FileGraph::edge_iterator jj = in.edge_begin(src), ej = in.edge_end(src); jj != ej; ++jj) {
00459 g.incrementDegree(p[src]);
00460 }
00461 }
00462
00463 g.phase2();
00464 edgeData.create(numEdges);
00465 for (FileGraph::iterator ii = in.begin(), ei = in.end(); ii != ei; ++ii) {
00466 GNode src = *ii;
00467 for (FileGraph::edge_iterator jj = in.edge_begin(src), ej = in.edge_end(src); jj != ej; ++jj) {
00468 GNode dst = in.getEdgeDst(jj);
00469 if (EdgeData::has_value) {
00470 edge_value_type& data = in.getEdgeData<edge_value_type>(jj);
00471 edgeData.set(g.addNeighbor(p[src], p[dst]), data);
00472 } else {
00473 g.addNeighbor(p[src], p[dst]);
00474 }
00475 }
00476 }
00477
00478 edge_value_type* rawEdgeData = g.finish<edge_value_type>();
00479 if (EdgeData::has_value)
00480 std::copy(edgeData.begin(), edgeData.end(), rawEdgeData);
00481
00482 out.swap(g);
00483 }
00484
00485 template<typename GraphTy,typename... Args>
00486 GALOIS_ATTRIBUTE_DEPRECATED
00487 void structureFromFile(GraphTy& g, const std::string& fname, Args&&... args) {
00488 FileGraph graph;
00489 graph.structureFromFile(fname);
00490 g.structureFromGraph(graph, std::forward<Args>(args)...);
00491 }
00492
00493 }
00494 }
00495 #endif