20 #ifndef _GALOIS_DIST_OFFLINE_GRAPH_
21 #define _GALOIS_DIST_OFFLINE_GRAPH_
32 #include <boost/iterator/counting_iterator.hpp>
34 #include "galois/config.h"
64 std::ifstream fileEdgeDst, fileIndex, fileEdgeData;
65 std::streamoff locEdgeDst, locIndex, locEdgeData;
69 uint64_t sizeEdgeData;
72 uint64_t numSeeksEdgeDst, numSeeksIndex, numSeeksEdgeData;
73 uint64_t numBytesReadEdgeDst, numBytesReadIndex, numBytesReadEdgeData;
77 uint64_t outIndexs(uint64_t node) {
78 std::lock_guard<decltype(lock)> lg(lock);
79 std::streamoff pos = (4 + node) *
sizeof(uint64_t);
82 if (locEdgeDst != pos) {
84 fileEdgeDst.seekg(pos, fileEdgeDst.beg);
91 fileEdgeDst.read(reinterpret_cast<char*>(&retval),
sizeof(uint64_t));
92 }
catch (
const std::ifstream::failure& e) {
93 std::cerr <<
"Exception while reading edge destinations:" << e.what()
95 std::cerr <<
"IO error flags: EOF " << fileEdgeDst.eof() <<
" FAIL "
96 << fileEdgeDst.fail() <<
" BAD " << fileEdgeDst.bad() <<
"\n";
100 auto numBytesRead = fileEdgeDst.gcount();
101 assert(numBytesRead ==
sizeof(uint64_t));
102 locEdgeDst += numBytesRead;
103 numBytesReadEdgeDst += numBytesRead;
108 uint64_t outEdges(uint64_t edge) {
109 std::lock_guard<decltype(lock)> lg(lock);
110 std::streamoff pos = (4 + numNodes) *
sizeof(uint64_t) +
111 edge * (v2 ?
sizeof(uint64_t) :
sizeof(uint32_t));
114 if (locIndex != pos) {
116 fileIndex.seekg(pos, fileEdgeDst.beg);
124 fileIndex.read(reinterpret_cast<char*>(&retval),
sizeof(uint64_t));
125 }
catch (
const std::ifstream::failure& e) {
126 std::cerr <<
"Exception while reading index:" << e.what() <<
"\n";
127 std::cerr <<
"IO error flags: EOF " << fileIndex.eof() <<
" FAIL "
128 << fileIndex.fail() <<
" BAD " << fileIndex.bad() <<
"\n";
131 auto numBytesRead = fileIndex.gcount();
132 assert(numBytesRead ==
sizeof(uint64_t));
133 locIndex += numBytesRead;
134 numBytesReadIndex += numBytesRead;
139 fileIndex.read(reinterpret_cast<char*>(&retval),
sizeof(uint32_t));
140 }
catch (
const std::ifstream::failure& e) {
141 std::cerr <<
"Exception while reading index:" << e.what() <<
"\n";
142 std::cerr <<
"IO error flags: EOF " << fileIndex.eof() <<
" FAIL "
143 << fileIndex.fail() <<
" BAD " << fileIndex.bad() <<
"\n";
146 auto numBytesRead = fileIndex.gcount();
147 assert(numBytesRead ==
sizeof(uint32_t));
148 locIndex += numBytesRead;
149 numBytesReadIndex += numBytesRead;
154 template <
typename T>
155 T edgeData(uint64_t edge) {
156 assert(
sizeof(T) <= sizeEdgeData);
157 std::lock_guard<decltype(lock)> lg(lock);
158 std::streamoff pos = (4 + numNodes) *
sizeof(uint64_t) +
159 numEdges * (v2 ?
sizeof(uint64_t) :
sizeof(uint32_t));
162 pos = (pos + 7) & ~7;
163 pos += edge * sizeEdgeData;
165 if (locEdgeData != pos) {
167 fileEdgeData.seekg(pos, fileEdgeDst.beg);
173 fileEdgeData.read(reinterpret_cast<char*>(&retval),
sizeof(T));
174 }
catch (
const std::ifstream::failure& e) {
175 std::cerr <<
"Exception while reading edge data:" << e.what() <<
"\n";
176 std::cerr <<
"IO error flags: EOF " << fileEdgeData.eof() <<
" FAIL "
177 << fileEdgeData.fail() <<
" BAD " << fileEdgeData.bad() <<
"\n";
180 auto numBytesRead = fileEdgeData.gcount();
181 assert(numBytesRead ==
sizeof(T));
182 locEdgeData += numBytesRead;
183 numBytesReadEdgeData += numBytesRead;
193 typedef boost::counting_iterator<uint64_t>
iterator;
198 : fileEdgeDst(name, std::ios_base::binary),
199 fileIndex(name, std::ios_base::binary),
200 fileEdgeData(name, std::ios_base::binary), locEdgeDst(0), locIndex(0),
201 locEdgeData(0), numSeeksEdgeDst(0), numSeeksIndex(0),
202 numSeeksEdgeData(0), numBytesReadEdgeDst(0), numBytesReadIndex(0),
203 numBytesReadEdgeData(0) {
204 if (!fileEdgeDst.is_open() || !fileEdgeDst.good())
205 throw "Bad filename";
206 if (!fileIndex.is_open() || !fileIndex.good())
207 throw "Bad filename";
208 if (!fileEdgeData.is_open() || !fileEdgeData.good())
209 throw "Bad filename";
211 fileEdgeDst.exceptions(std::ifstream::eofbit | std::ifstream::failbit |
212 std::ifstream::badbit);
213 fileIndex.exceptions(std::ifstream::eofbit | std::ifstream::failbit |
214 std::ifstream::badbit);
215 fileEdgeData.exceptions(std::ifstream::eofbit | std::ifstream::failbit |
216 std::ifstream::badbit);
221 fileEdgeDst.read(reinterpret_cast<char*>(&ver),
sizeof(uint64_t));
222 fileEdgeDst.read(reinterpret_cast<char*>(&sizeEdgeData),
224 fileEdgeDst.read(reinterpret_cast<char*>(&numNodes),
sizeof(uint64_t));
225 fileEdgeDst.read(reinterpret_cast<char*>(&numEdges),
sizeof(uint64_t));
226 }
catch (
const std::ifstream::failure& e) {
227 std::cerr <<
"Exception while reading graph header:" << e.what() <<
"\n";
228 std::cerr <<
"IO error flags: EOF " << fileEdgeDst.eof() <<
" FAIL "
229 << fileEdgeDst.fail() <<
" BAD " << fileEdgeDst.bad() <<
"\n";
232 if (ver == 0 || ver > 2)
241 fileEdgeDst.seekg(0, fileEdgeDst.end);
242 length = fileEdgeDst.tellg();
243 if (length <
sizeof(uint64_t) * (4 + numNodes) +
244 (v2 ?
sizeof(uint64_t) :
sizeof(uint32_t)) * numEdges)
245 throw "File too small";
247 fileEdgeDst.seekg(0, std::ios_base::beg);
248 fileEdgeData.seekg(0, std::ios_base::beg);
249 fileIndex.seekg(0, std::ios_base::beg);
255 return numSeeksEdgeDst + numSeeksEdgeData + numSeeksIndex;
261 return numBytesReadEdgeDst + numBytesReadEdgeData + numBytesReadIndex;
265 numSeeksEdgeDst = numSeeksEdgeData = numSeeksIndex = 0;
266 numBytesReadEdgeDst = numBytesReadEdgeData = numBytesReadIndex = 0;
271 size_t size()
const {
return numNodes; }
293 template <
typename T>
295 return edgeData<T>(*ni);
308 typedef std::pair<edge_iterator, edge_iterator>
EdgeRange;
326 std::vector<unsigned> scaleFactor = std::vector<unsigned>())
328 return galois::graphs::divideNodesBinarySearch<OfflineGraph>(
329 numNodes, numEdges, nodeWeight, edgeWeight, id, total, *
this,
336 uint64_t numNodes, numEdges;
339 std::vector<uint64_t> bufferDst;
341 std::deque<uint64_t> edgeOffsets;
343 std::streamoff offsetOfDst(uint64_t edge) {
344 return sizeof(uint64_t) * (4 + numNodes + edge);
346 std::streamoff offsetOfData(uint64_t edge) {
347 return sizeof(uint64_t) * (4 + numNodes + numEdges) +
348 (smallData ?
sizeof(float) :
sizeof(
double)) * edge;
351 void setEdge32(uint64_t src, uint64_t offset, uint64_t dst, uint32_t val) {
353 offset += edgeOffsets[src - 1];
354 file.seekg(offsetOfDst(offset), std::ios_base::beg);
355 file.write(reinterpret_cast<char*>(&dst),
sizeof(uint64_t));
356 file.seekg(offsetOfData(offset), std::ios_base::beg);
357 file.write(reinterpret_cast<char*>(&val),
sizeof(uint32_t));
360 void setEdge64(uint64_t src, uint64_t offset, uint64_t dst, uint64_t val) {
362 offset += edgeOffsets[src - 1];
363 file.seekg(offsetOfDst(offset), std::ios_base::beg);
364 file.write(reinterpret_cast<char*>(&dst),
sizeof(uint64_t));
365 file.seekg(offsetOfData(offset), std::ios_base::beg);
366 file.write(reinterpret_cast<char*>(&val),
sizeof(uint64_t));
369 void setEdge_sorted(uint64_t dst) {
371 uint32_t dst32 = dst;
372 file.write(reinterpret_cast<char*>(&dst32),
sizeof(uint32_t));
374 file.write(reinterpret_cast<char*>(&dst),
sizeof(uint64_t));
378 void setEdge_sortedBuffer() {
380 std::vector<uint32_t> tmp(bufferDst.begin(), bufferDst.end());
381 file.write(reinterpret_cast<char*>(&tmp[0]),
382 (
sizeof(uint32_t) * tmp.size()));
384 file.write(reinterpret_cast<char*>(&bufferDst[0]),
385 (
sizeof(uint64_t) * bufferDst.size()));
394 uint64_t _numNodes = 0, uint64_t _numEdges = 0)
395 : file(name, std::ios_base::in | std::ios_base::out |
396 std::ios_base::binary | std::ios_base::trunc),
397 numNodes(_numNodes), numEdges(_numEdges), smallData(use32), ver(1) {
398 if (!file.is_open() || !file.good())
399 throw "Bad filename";
400 uint64_t etSize = smallData ?
sizeof(float) :
sizeof(
double);
401 file.write(reinterpret_cast<char*>(&ver),
sizeof(uint64_t));
402 file.write(reinterpret_cast<char*>(&etSize),
sizeof(uint64_t));
403 file.write(reinterpret_cast<char*>(&numNodes),
sizeof(uint64_t));
404 file.write(reinterpret_cast<char*>(&numEdges),
sizeof(uint64_t));
405 file.seekg(0, std::ios_base::beg);
412 edgeOffsets = std::move(edgeCounts);
413 numNodes = edgeOffsets.size();
415 std::cout <<
" NUM EDGES : " << numEdges <<
"\n";
417 edgeOffsets.begin());
419 if (numNodes >= 4294967296) {
424 std::cout <<
" USING VERSION : " << ver <<
"\n";
426 file.seekg(0, std::ios_base::beg);
427 file.write(reinterpret_cast<char*>(&ver),
sizeof(uint64_t));
428 file.write(reinterpret_cast<char*>(&etSize),
sizeof(uint64_t));
430 file.write(reinterpret_cast<char*>(&numNodes),
sizeof(uint64_t));
431 file.write(reinterpret_cast<char*>(&numEdges),
sizeof(uint64_t));
432 for (
auto i : edgeOffsets)
433 file.write(reinterpret_cast<char*>(&i),
sizeof(uint64_t));
434 file.seekg(0, std::ios_base::beg);
437 void setEdge(uint64_t src, uint64_t offset, uint64_t dst, uint64_t val) {
439 setEdge32(src, offset, dst, val);
441 setEdge64(src, offset, dst, val);
452 #endif //_GALOIS_DIST_OFFLINE_GRAPH_
iterator end()
Definition: OfflineGraph.h:276
void setCounts(std::deque< uint64_t > edgeCounts)
Definition: OfflineGraph.h:411
std::pair< iterator, iterator > NodeRange
Definition: OfflineGraph.h:307
T getEdgeData(edge_iterator ni)
Definition: OfflineGraph.h:294
uint64_t GraphNode
Definition: OfflineGraph.h:195
auto divideByNode(size_t nodeWeight, size_t edgeWeight, size_t id, size_t total, std::vector< unsigned > scaleFactor=std::vector< unsigned >()) -> GraphRange
Returns 2 ranges (one for nodes, one for edges) for a particular division.
Definition: OfflineGraph.h:324
OfflineGraph(const std::string &name)
Definition: OfflineGraph.h:197
size_t edgeSize() const
Definition: OfflineGraph.h:273
runtime::iterable< NoDerefIterator< edge_iterator > > edges(GraphNode N)
Definition: OfflineGraph.h:289
uint64_t num_bytes_read()
Definition: OfflineGraph.h:258
std::pair< edge_iterator, edge_iterator > EdgeRange
Definition: OfflineGraph.h:308
Definition: Iterable.h:36
Definition: OfflineGraph.h:334
edge_iterator edge_begin(GraphNode N)
Definition: OfflineGraph.h:278
std::pair< NodeRange, EdgeRange > GraphRange
Definition: OfflineGraph.h:309
iterator begin()
Definition: OfflineGraph.h:275
Definition: OfflineGraph.h:63
boost::counting_iterator< uint64_t > edge_iterator
Definition: OfflineGraph.h:194
uint64_t operator[](uint64_t n)
Accesses the prefix sum on disk.
Definition: OfflineGraph.h:304
~OfflineGraphWriter()
Definition: OfflineGraph.h:408
void setEdge(uint64_t src, uint64_t offset, uint64_t dst, uint64_t val)
Definition: OfflineGraph.h:437
OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first)
Does a partial sum from first -> last and writes the results to the d_first iterator.
Definition: ParallelSTL.h:314
GraphNode getEdgeDst(edge_iterator ni)
Definition: OfflineGraph.h:287
void reset_seek_counters()
Definition: OfflineGraph.h:264
size_t size() const
Definition: OfflineGraph.h:271
SimpleLock is a spinlock.
Definition: SimpleLock.h:36
void setEdgeSorted(uint64_t dst)
Definition: OfflineGraph.h:444
uint64_t num_seeks()
Definition: OfflineGraph.h:252
size_t sizeEdges() const
Definition: OfflineGraph.h:272
OfflineGraphWriter(const std::string &name, bool use32=false, uint64_t _numNodes=0, uint64_t _numEdges=0)
Definition: OfflineGraph.h:393
boost::counting_iterator< uint64_t > iterator
Definition: OfflineGraph.h:193
edge_iterator edge_end(GraphNode N)
Definition: OfflineGraph.h:285
T accumulate(InputIterator first, InputIterator last, const T &identity, const BinaryOperation &binary_op)
Definition: ParallelSTL.h:268
void seekEdgesDstStart()
Definition: OfflineGraph.h:446