25 #include <boost/iterator/counting_iterator.hpp>
27 #include "galois/config.h"
59 template <
typename PrefixSumType>
60 size_t findIndexPrefixSum(
size_t nodeWeight,
size_t edgeWeight,
61 size_t targetWeight, uint64_t lb, uint64_t ub,
62 PrefixSumType& edgePrefixSum, uint64_t edgeOffset,
63 uint64_t nodeOffset) {
64 assert(nodeWeight != 0 || edgeWeight != 0);
67 size_t mid = lb + (ub - lb) / 2;
70 if ((mid + nodeOffset) != 0) {
71 num_edges = edgePrefixSum[mid - 1 + nodeOffset] - edgeOffset;
76 size_t weight = num_edges * edgeWeight + mid * nodeWeight;
78 if (weight < targetWeight) {
80 }
else if (weight >= targetWeight) {
99 uint32_t determine_block_division(uint32_t numDivisions,
100 std::vector<unsigned>& scaleFactor);
140 template <
typename PrefixSumType,
typename NodeType = u
int64_t>
142 NodeType numNodes, uint64_t numEdges,
size_t nodeWeight,
size_t edgeWeight,
143 size_t id,
size_t total, PrefixSumType& edgePrefixSum,
144 std::vector<unsigned> scaleFactor = std::vector<unsigned>(),
145 uint64_t edgeOffset = 0, uint64_t nodeOffset = 0) {
146 typedef boost::counting_iterator<NodeType> iterator;
147 typedef boost::counting_iterator<uint64_t> edge_iterator;
148 typedef std::pair<iterator, iterator> NodeRange;
149 typedef std::pair<edge_iterator, edge_iterator> EdgeRange;
150 typedef std::pair<NodeRange, EdgeRange> GraphRange;
154 return GraphRange(NodeRange(iterator(0), iterator(0)),
155 EdgeRange(edge_iterator(0), edge_iterator(0)));
158 assert(nodeWeight != 0 || edgeWeight != 0);
163 uint64_t weight = numNodes * nodeWeight + (numEdges + 1) * edgeWeight;
166 uint32_t numBlocks = internal::determine_block_division(total, scaleFactor);
169 uint64_t blockWeight = (weight + numBlocks - 1) / numBlocks;
177 blockLower = scaleFactor[
id - 1];
182 uint32_t blockUpper = scaleFactor[id];
184 assert(blockLower <= blockUpper);
191 if (blockLower == 0) {
194 nodesLower = internal::findIndexPrefixSum(
195 nodeWeight, edgeWeight, blockWeight * blockLower, 0, numNodes,
196 edgePrefixSum, edgeOffset, nodeOffset);
200 nodesUpper = internal::findIndexPrefixSum(
201 nodeWeight, edgeWeight, blockWeight * blockUpper, nodesLower, numNodes,
202 edgePrefixSum, edgeOffset, nodeOffset);
205 uint64_t edgesLower = numEdges;
206 uint64_t edgesUpper = numEdges;
208 if (nodesLower != nodesUpper) {
209 if ((nodesLower + nodeOffset) != 0) {
210 edgesLower = edgePrefixSum[nodesLower - 1 + nodeOffset] - edgeOffset;
215 edgesUpper = edgePrefixSum[nodesUpper - 1 + nodeOffset] - edgeOffset;
223 NodeRange(iterator(nodesLower), iterator(nodesUpper)),
224 EdgeRange(edge_iterator(edgesLower), edge_iterator(edgesUpper)));
241 bool unitRangeCornerCaseHandle(uint32_t unitsToSplit, uint32_t beginNode,
243 std::vector<uint32_t>& returnRanges);
262 template <
typename GraphTy>
263 void determineUnitRangesLoopGraph(GraphTy& graph, uint32_t unitsToSplit,
264 uint32_t beginNode, uint32_t endNode,
265 std::vector<uint32_t>& returnRanges,
266 uint32_t nodeAlpha) {
267 assert(beginNode != endNode);
269 uint32_t numNodesInRange = endNode - beginNode;
270 uint64_t numEdgesInRange =
271 graph.edge_end(endNode - 1) - graph.edge_begin(beginNode);
272 uint64_t edgeOffset = *graph.edge_begin(beginNode);
274 returnRanges[0] = beginNode;
275 std::vector<unsigned int> dummyScaleFactor;
277 for (uint32_t i = 0; i < unitsToSplit; i++) {
280 divideNodesBinarySearch<GraphTy, uint32_t>(
281 numNodesInRange, numEdgesInRange, nodeAlpha, 1, i, unitsToSplit,
282 graph, dummyScaleFactor, edgeOffset, beginNode)
286 if (nodeSplits.first != nodeSplits.second) {
288 assert(returnRanges[i] == *(nodeSplits.first) + beginNode);
290 assert(returnRanges[i] == beginNode);
292 returnRanges[i + 1] = *(nodeSplits.second) + beginNode;
295 returnRanges[i + 1] = returnRanges[i];
298 galois::gDebug(
"LoopGraph Unit ", i,
" gets nodes ", returnRanges[i],
299 " to ", returnRanges[i + 1],
", num edges is ",
300 graph.edge_end(returnRanges[i + 1] - 1) -
301 graph.edge_begin(returnRanges[i]));
322 template <
typename VectorTy>
323 void determineUnitRangesLoopPrefixSum(VectorTy& prefixSum,
324 uint32_t unitsToSplit, uint32_t beginNode,
326 std::vector<uint32_t>& returnRanges,
327 uint32_t nodeAlpha) {
328 assert(beginNode != endNode);
330 uint32_t numNodesInRange = endNode - beginNode;
332 uint64_t numEdgesInRange;
334 if (beginNode != 0) {
335 numEdgesInRange = prefixSum[endNode - 1] - prefixSum[beginNode - 1];
336 edgeOffset = prefixSum[beginNode - 1];
338 numEdgesInRange = prefixSum[endNode - 1];
342 returnRanges[0] = beginNode;
343 std::vector<unsigned int> dummyScaleFactor;
345 for (uint32_t i = 0; i < unitsToSplit; i++) {
348 divideNodesBinarySearch<VectorTy, uint32_t>(
349 numNodesInRange, numEdgesInRange, nodeAlpha, 1, i, unitsToSplit,
350 prefixSum, dummyScaleFactor, edgeOffset, beginNode)
354 if (nodeSplits.first != nodeSplits.second) {
356 assert(returnRanges[i] == *(nodeSplits.first) + beginNode);
358 assert(returnRanges[i] == beginNode);
360 returnRanges[i + 1] = *(nodeSplits.second) + beginNode;
363 returnRanges[i + 1] = returnRanges[i];
366 galois::gDebug(
"Unit ", i,
" gets nodes ", returnRanges[i],
" to ",
367 returnRanges[i + 1]);
379 void unitRangeSanity(uint32_t unitsToSplit, uint32_t beginNode,
380 uint32_t endNode, std::vector<uint32_t>& returnRanges);
402 template <
typename GraphTy>
404 uint32_t unitsToSplit,
405 uint32_t nodeAlpha = 0) {
406 uint32_t totalNodes = graph.size();
408 std::vector<uint32_t> returnRanges;
409 returnRanges.resize(unitsToSplit + 1);
412 if (internal::unitRangeCornerCaseHandle(unitsToSplit, 0, totalNodes,
419 internal::determineUnitRangesLoopGraph(graph, unitsToSplit, 0, totalNodes,
420 returnRanges, nodeAlpha);
422 internal::unitRangeSanity(unitsToSplit, 0, totalNodes, returnRanges);
447 template <
typename GraphTy>
448 std::vector<uint32_t>
450 uint32_t beginNode, uint32_t endNode,
451 uint32_t nodeAlpha = 0) {
452 std::vector<uint32_t> returnRanges;
453 returnRanges.resize(unitsToSplit + 1);
455 if (internal::unitRangeCornerCaseHandle(unitsToSplit, beginNode, endNode,
462 internal::determineUnitRangesLoopGraph(graph, unitsToSplit, beginNode,
463 endNode, returnRanges, nodeAlpha);
465 internal::unitRangeSanity(unitsToSplit, beginNode, endNode, returnRanges);
483 template <
typename VectorTy>
485 VectorTy& edgePrefixSum,
486 uint32_t nodeAlpha = 0) {
487 assert(unitsToSplit > 0);
489 std::vector<uint32_t> nodeRanges;
490 nodeRanges.resize(unitsToSplit + 1);
494 uint32_t numNodes = edgePrefixSum.size();
499 for (uint32_t i = 0; i < unitsToSplit; i++) {
500 nodeRanges[i + 1] = 0;
505 uint64_t numEdges = edgePrefixSum[numNodes - 1];
507 for (uint32_t i = 0; i < unitsToSplit; i++) {
509 divideNodesBinarySearch<VectorTy, uint32_t>(
510 numNodes, numEdges, nodeAlpha, 1, i, unitsToSplit, edgePrefixSum)
514 if (nodeSplits.first != nodeSplits.second) {
516 assert(nodeRanges[i] == *(nodeSplits.first));
518 assert(nodeRanges[i] == 0);
520 nodeRanges[i + 1] = *(nodeSplits.second);
523 nodeRanges[i + 1] = nodeRanges[i];
549 template <
typename VectorTy>
550 std::vector<uint32_t>
552 uint32_t beginNode, uint32_t endNode,
553 uint32_t nodeAlpha = 0) {
554 std::vector<uint32_t> returnRanges;
555 returnRanges.resize(unitsToSplit + 1);
557 if (internal::unitRangeCornerCaseHandle(unitsToSplit, beginNode, endNode,
564 internal::determineUnitRangesLoopPrefixSum(
565 edgePrefixSum, unitsToSplit, beginNode, endNode, returnRanges, nodeAlpha);
567 internal::unitRangeSanity(unitsToSplit, beginNode, endNode, returnRanges);
auto divideNodesBinarySearch(NodeType numNodes, uint64_t numEdges, size_t nodeWeight, size_t edgeWeight, size_t id, size_t total, PrefixSumType &edgePrefixSum, std::vector< unsigned > scaleFactor=std::vector< unsigned >(), uint64_t edgeOffset=0, uint64_t nodeOffset=0)
Returns 2 ranges (one for nodes, one for edges) for a particular division.
Definition: GraphHelpers.h:141
void gDebug(Args &&...GALOIS_USED_ONLY_IN_DEBUG(args))
Prints a debug string from a sequence of things; prints nothing if NDEBUG is defined.
Definition: gIO.h:72
std::vector< uint32_t > determineUnitRangesFromGraph(GraphTy &graph, uint32_t unitsToSplit, uint32_t nodeAlpha=0)
Determines node division ranges for all nodes in a graph and returns it in an offset vector...
Definition: GraphHelpers.h:403
std::vector< uint32_t > determineUnitRangesFromPrefixSum(uint32_t unitsToSplit, VectorTy &edgePrefixSum, uint32_t nodeAlpha=0)
Uses the divideByNode function (which is binary search based) to divide nodes among units using a pro...
Definition: GraphHelpers.h:484