diff --git a/src/FEMSolver.cu b/src/FEMSolver.cu index f00ed9d..6bb9da9 100644 --- a/src/FEMSolver.cu +++ b/src/FEMSolver.cu @@ -625,7 +625,7 @@ void FEMSolver::debugPrintMatlabels(TetMesh* mesh) { std::cout << "Found " << mesh->matlabels.size() << " elements in matlabels." << std::endl; unsigned int numZeros = 0; - for (vector::iterator it = mesh->matlabels.begin(); it != mesh->matlabels.end(); ++it) + for (std::vector::iterator it = mesh->matlabels.begin(); it != mesh->matlabels.end(); ++it) { if ((*it) == 0) numZeros++; diff --git a/src/core/aggmis/cuda/AggMIS_Aggregation_CPU.cu b/src/core/aggmis/cuda/AggMIS_Aggregation_CPU.cu index 014cef0..3fc5e02 100644 --- a/src/core/aggmis/cuda/AggMIS_Aggregation_CPU.cu +++ b/src/core/aggmis/cuda/AggMIS_Aggregation_CPU.cu @@ -1,16 +1,16 @@ #include namespace AggMIS { namespace Aggregation { - IntVector_h* AggregateToNearest(Graph_h &graph, - IntVector_h &roots) { + Types::IntVector_h* AggregateToNearest(Types::Graph_h &graph, + Types::IntVector_h &roots) { // Allocating an array for distances: - IntVector_h rootDistance(roots.size()); + Types::IntVector_h rootDistance(roots.size()); // Allocating return array - IntVector_h *aggregation = new IntVector_h(roots.size()); + Types::IntVector_h *aggregation = new Types::IntVector_h(roots.size()); // A queue of unallocated nodes - queue toAllocate; + std::queue toAllocate; // Assigning initial distances, numbering aggregates, and adding // nodes to queue for allocation. @@ -93,16 +93,16 @@ namespace AggMIS { return aggregation; } - bool IsValidAggregation(Graph_h &graph, - IntVector_h &aggregation, + bool IsValidAggregation(Types::Graph_h &graph, + Types::IntVector_h &aggregation, bool verbose) { int errorsFound = 0; - IntVector_h* ps = GetPartSizes(aggregation); - IntVector_h &partSizes = *ps; - IntVector_h visitedNodes(graph.Size(), 0); - IntVector_h exploredAggregates(partSizes.size(), 0); - set problemAggregates; - queue toExplore; + Types::IntVector_h* ps = GetPartSizes(aggregation); + Types::IntVector_h &partSizes = *ps; + Types::IntVector_h visitedNodes(graph.Size(), 0); + Types::IntVector_h exploredAggregates(partSizes.size(), 0); + std::set problemAggregates; + std::queue toExplore; for (int i = 0; i < graph.Size(); i++) { int thisAggregate = aggregation[i]; @@ -138,7 +138,7 @@ namespace AggMIS { if (errorsFound > 0) { printf("Found %d errors while checking aggregation!\n", errorsFound); - set::iterator it; + std::set::iterator it; for (it = problemAggregates.begin(); it != problemAggregates.end(); it++) printf("\t%d", *it); printf("\n"); @@ -146,9 +146,9 @@ namespace AggMIS { } return true; } - IntVector_h* GetPartSizes(IntVector_h &aggregation) { + Types::IntVector_h* GetPartSizes(Types::IntVector_h &aggregation) { // Allocate return array - IntVector_h *partSizes = new IntVector_h(); + Types::IntVector_h *partSizes = new Types::IntVector_h(); // Iterate over the aggregation and count nodes for (int i = 0; i < aggregation.size(); i++) { @@ -159,10 +159,10 @@ namespace AggMIS { } return partSizes; } - IntVector_h* GetPartSizes(IntVector_h &aggregation, - IntVector_h &nodeWeights) { + Types::IntVector_h* GetPartSizes(Types::IntVector_h &aggregation, + Types::IntVector_h &nodeWeights) { // Allocate return array - IntVector_h *partSizes = new IntVector_h(); + Types::IntVector_h *partSizes = new Types::IntVector_h(); // Iterate over the aggregation and count nodes for (int i = 0; i < aggregation.size(); i++) { @@ -173,10 +173,10 @@ namespace AggMIS { } return partSizes; } - vector >* GetAggregateGraph(Graph_h& graph, - vector &nodeList) { + std::vector >* GetAggregateGraph(Types::Graph_h& graph, + std::vector &nodeList) { // Create the return structure. - vector > *aggGraph = new vector >(nodeList.size()); + std::vector > *aggGraph = new std::vector >(nodeList.size()); // Fill the adjacency by translating the adjacency to local indices for (int nIt = 0; nIt < nodeList.size(); nIt++) { @@ -193,11 +193,11 @@ namespace AggMIS { } return aggGraph; } - int FindFarthestNode(vector > &graph, + int FindFarthestNode(std::vector > &graph, int start) { // Data structures for flood fill - vector distances(graph.size(), -1); - queue toExplore; + std::vector distances(graph.size(), -1); + std::queue toExplore; toExplore.push(start); distances[start] = 0; @@ -230,20 +230,20 @@ namespace AggMIS { } return farthestNode; } - void MarkDistances(vector >& graph, - vector& distances, + void MarkDistances(std::vector >& graph, + std::vector& distances, int startPoint) { // Put single start point into vector and call vector version. - vector startPoints; + std::vector startPoints; startPoints.push_back(startPoint); MarkDistances(graph, distances, startPoints); } - void MarkDistances(vector >& graph, - vector& distances, - vector startPoints) { + void MarkDistances(std::vector >& graph, + std::vector& distances, + std::vector startPoints) { // Initialize data structures for flood fill distances.assign(graph.size(), -1); - queue toExplore; + std::queue toExplore; // Handle start points for (int i = 0; i < startPoints.size(); i++) { @@ -269,11 +269,11 @@ namespace AggMIS { } } } - int FindMassScore(vector >& graph, + int FindMassScore(std::vector >& graph, int startPoint) { // Initialize data structures for flood fill - vector distances(graph.size(), -1); - queue toExplore; + std::vector distances(graph.size(), -1); + std::queue toExplore; // Put start point on queue toExplore.push(startPoint); @@ -302,9 +302,9 @@ namespace AggMIS { } return score; } - vector* GetCentroid(vector >& graph, + std::vector* GetCentroid(std::vector >& graph, int startPoint) { - vector scores(graph.size(), -1); + std::vector scores(graph.size(), -1); int currentNode = startPoint; // Find score for first node @@ -330,7 +330,7 @@ namespace AggMIS { } // Find any adjacent nodes with equivalent score - vector *result = new vector(); + std::vector *result = new std::vector(); result->push_back(currentNode); for (int i = 0; i < graph[currentNode].size(); i++) { diff --git a/src/core/aggmis/cuda/AggMIS_Aggregation_GPU.cu b/src/core/aggmis/cuda/AggMIS_Aggregation_GPU.cu index f848771..58b0479 100644 --- a/src/core/aggmis/cuda/AggMIS_Aggregation_GPU.cu +++ b/src/core/aggmis/cuda/AggMIS_Aggregation_GPU.cu @@ -1,4 +1,4 @@ -/* +/* * File: AggMIS_Aggregation_GPU.cu * Author: T. James Lewis * @@ -8,283 +8,280 @@ #include "AggMIS_Types.h" #include "AggMIS_GraphHelpers.h" namespace AggMIS { - namespace Aggregation { - using namespace Types; - using namespace std; - namespace Kernels { - __global__ void allocateNodesKernel(int size, - int *adjIndexes, - int *adjacency, - int *partIn, - int *partOut, - int *aggregated) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - if (aggregated[idx] == 0) - { - int start = adjIndexes[idx]; - int end = adjIndexes[idx + 1]; - - // Storage for possible aggregations. - int candidates[10]; - int candidateCounts[10]; - for (int i = 0; i < 10; i++) - { - candidates[i] = -1; - candidateCounts[i] = 0; - } - - // Going through neighbors to aggregate: - for (int i = start; i < end; i++) - { - int candidate = partIn[ adjacency[i] ]; - if (candidate != -1) - { - for (int j = 0; j < 10 && candidate != -1; j++) - { - if (candidates[j] == -1) - { - candidates[j] = candidate; - candidateCounts[j] = 1; - } - else - { - if (candidates[j] == candidate) - { - candidateCounts[j] += 1; - candidate = -1; - } - } - } - } - } - - // Finding the most adjacent aggregate and adding node to it: - int addTo = candidates[0]; - int count = candidateCounts[0]; - for (int i = 1; i < 10; i++) - { - if (candidateCounts[i] > count) - { - count = candidateCounts[i]; - addTo = candidates[i]; - } - } - partOut[idx] = addTo; - if (addTo != -1) - { - aggregated[idx] = 1; - } - } - } + namespace Aggregation { + namespace Kernels { + __global__ void allocateNodesKernel(int size, + int *adjIndexes, + int *adjacency, + int *partIn, + int *partOut, + int *aggregated) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + if (aggregated[idx] == 0) + { + int start = adjIndexes[idx]; + int end = adjIndexes[idx + 1]; + + // Storage for possible aggregations. + int candidates[10]; + int candidateCounts[10]; + for (int i = 0; i < 10; i++) + { + candidates[i] = -1; + candidateCounts[i] = 0; } - __global__ void checkAggregationFillAggregates(int size, - int *adjIndices, - int *adjacency, - int* aggregation, - int* valuesIn, - int* valuesOut, - int* incomplete) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) + + // Going through neighbors to aggregate: + for (int i = start; i < end; i++) + { + int candidate = partIn[adjacency[i]]; + if (candidate != -1) + { + for (int j = 0; j < 10 && candidate != -1; j++) { - // Find the currently marked distance - int currentVal = valuesIn[idx]; - int currentAgg = aggregation[idx]; - - // Checking if any neighbors have a better value - int start = adjIndices[idx]; - int end = adjIndices[idx + 1]; - for (int i = start; i < end; i++) + if (candidates[j] == -1) + { + candidates[j] = candidate; + candidateCounts[j] = 1; + } else + { + if (candidates[j] == candidate) { - int neighborAgg = aggregation[adjacency[i]]; - int neighborVal = valuesIn[adjacency[i]]; - if (neighborAgg == currentAgg && neighborVal > currentVal) - { - currentVal = neighborVal; - incomplete[0] = 1; - } + candidateCounts[j] += 1; + candidate = -1; } - - // Write out the distance to the output vector: - valuesOut[idx] = currentVal; + } } - } - } - - // Functions - IntVector_d* AggregateToNearest(Graph_d &graph, - IntVector_d &roots) { - // Create temp vectors to work with - int size = graph.Size(); - IntVector_d *aggregated = new IntVector_d(roots); - IntVector_d *partIn = new IntVector_d(roots); - - - // Prefix sum to number aggregate roots: - thrust::inclusive_scan(partIn->begin(), partIn->end(), partIn->begin()); - - // Transform non root nodes to -1 - thrust::transform(partIn->begin(), partIn->end(), aggregated->begin(), partIn->begin(), Functors::NumberParts()); - IntVector_d *partOut = new IntVector_d(*partIn); - - // Preparing to call aggregate kernel: - int *partIn_d = thrust::raw_pointer_cast(partIn->data()); // Pointer to partIn vector - int *partOut_d = thrust::raw_pointer_cast(partOut->data()); // Pointer to partOut vector - int *adjIndexes_d = thrust::raw_pointer_cast(graph.indices->data()); // Pointer to adjacency indexes - int *adjacency_d = thrust::raw_pointer_cast(graph.adjacency->data()); // Pointer to adjacency - int *aggregated_d = thrust::raw_pointer_cast(aggregated->data()); // Pointer to aggregated - bool complete = false; // Indicates whether all nodes are aggregated - - // Figuring out block sizes for kernel call: - int blockSize = 256; - int nBlocks = size/blockSize + (size%blockSize == 0?0:1); - - while (!complete) - { - // Allocating nodes - Kernels::allocateNodesKernel <<< nBlocks, blockSize >>> (size, adjIndexes_d, adjacency_d, partIn_d, partOut_d, aggregated_d); - - // Copying partOut to partIn - thrust::copy(partOut->begin(), partOut->end(), partIn->begin()); - - // Checking if done - int unallocatedNodes = thrust::count(aggregated->begin(), aggregated->end(), 0); - complete = unallocatedNodes == 0; + } } - // Cleaning up - aggregated->clear(); - partOut->clear(); - delete aggregated; - delete partOut; - - return partIn; - } - bool IsValidAggregation(Graph_d &graph, - IntVector_d &aggregation, - bool verbose) { - // Counter for number of errors found - int errors = 0; - - // Check to make sure that the aggregate id's are sequential - IntVector_d scratch(aggregation); - thrust::sort(scratch.begin(), scratch.end()); - int newLength = thrust::unique(scratch.begin(),scratch.end()) - scratch.begin(); - scratch.resize(newLength); - - if(scratch[0] != 0 || scratch[scratch.size()-1] != scratch.size() -1) + // Finding the most adjacent aggregate and adding node to it: + int addTo = candidates[0]; + int count = candidateCounts[0]; + for (int i = 1; i < 10; i++) { - if (verbose) { - printf("Error found in aggregation: improper aggregate indices:\n"); - int firstId = scratch[0]; - int lastId = scratch[scratch.size()-1]; - int count = scratch.size(); - printf("\tFirst index is %d, last index is %d, there are %d unique id's\n", firstId, lastId, count); - } - errors++; - return false; + if (candidateCounts[i] > count) + { + count = candidateCounts[i]; + addTo = candidates[i]; + } } - - // Check to make sure each aggregate is a connected component - IntVector_d *valuesIn = GraphHelpers::GetIndicesVector(aggregation.size()); - IntVector_d valuesOut(aggregation.size()); - IntVector_d incomplete(1, 1); - - // Figuring out block sizes for kernel call: - int size = graph.Size(); - int blockSize = 256; - int nBlocks = size/blockSize + (size%blockSize == 0?0:1); - - // Getting raw pointers - int *valuesIn_d = thrust::raw_pointer_cast(valuesIn->data()); - int *valuesOut_d = thrust::raw_pointer_cast(&valuesOut[0]); - int *incomplete_d = thrust::raw_pointer_cast(&incomplete[0]); - int *adjacency_d = thrust::raw_pointer_cast(graph.adjacency->data()); - int *adjIndices_d = thrust::raw_pointer_cast(graph.indices->data()); - int *aggregation_d = thrust::raw_pointer_cast(&aggregation[0]); - - // Flood filling within each aggregate - int *originalOut = valuesIn_d; - while(incomplete[0] == 1) + partOut[idx] = addTo; + if (addTo != -1) { - incomplete[0] = 0; - Kernels::checkAggregationFillAggregates <<< nBlocks, blockSize >>> - (size, adjIndices_d, adjacency_d, aggregation_d, valuesIn_d, valuesOut_d, incomplete_d); - int *temp = valuesIn_d; - valuesIn_d = valuesOut_d; - valuesOut_d = temp; + aggregated[idx] = 1; } + } + } + } + __global__ void checkAggregationFillAggregates(int size, + int *adjIndices, + int *adjacency, + int* aggregation, + int* valuesIn, + int* valuesOut, + int* incomplete) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + // Find the currently marked distance + int currentVal = valuesIn[idx]; + int currentAgg = aggregation[idx]; - if (originalOut != valuesOut_d) - valuesOut.assign(valuesIn->begin(), valuesIn->end()); - valuesIn->assign(aggregation.begin(),aggregation.end()); - - // - int correctLength = newLength; - thrust::sort(thrust::make_zip_iterator(thrust::make_tuple(valuesIn->begin(), valuesOut.begin())), - thrust::make_zip_iterator(thrust::make_tuple(valuesIn->end(), valuesOut.end()))); - newLength = thrust::unique(thrust::make_zip_iterator(thrust::make_tuple(valuesOut.begin(), valuesIn->begin())), - thrust::make_zip_iterator(thrust::make_tuple(valuesOut.end(), valuesIn->end()))) - -thrust::make_zip_iterator(thrust::make_tuple(valuesOut.begin(),valuesIn->begin())); - - valuesIn->resize(newLength); - valuesOut.resize(newLength); - - if (newLength != correctLength) + // Checking if any neighbors have a better value + int start = adjIndices[idx]; + int end = adjIndices[idx + 1]; + for (int i = start; i < end; i++) + { + int neighborAgg = aggregation[adjacency[i]]; + int neighborVal = valuesIn[adjacency[i]]; + if (neighborAgg == currentAgg && neighborVal > currentVal) { - if (verbose) - printf("Error: there were %d connected components found and %d aggregates\n", newLength, correctLength); - errors++; - - IntVector_h aggIds(*valuesIn); - IntVector_h nodeIds(valuesOut); - for (int i = 0; i < valuesOut.size() - 1; i++) - { - int currentAgg = aggIds[i]; - int nextAgg = aggIds[i + 1]; - if (currentAgg == nextAgg && verbose) - printf("Aggregate %d was filled from %d and %d\n", currentAgg, nodeIds[i], nodeIds[i+1]); - } + currentVal = neighborVal; + incomplete[0] = 1; } - - // Clean up - scratch.resize(0); - valuesIn->resize(0); - delete valuesIn; - incomplete.resize(0); - - return errors == 0; + } + + // Write out the distance to the output vector: + valuesOut[idx] = currentVal; + } + } + } + + // Functions + AggMIS::Types::IntVector_d* AggregateToNearest(AggMIS::Types::Graph_d &graph, + AggMIS::Types::IntVector_d &roots) { + // Create temp vectors to work with + int size = graph.Size(); + AggMIS::Types::IntVector_d *aggregated = new AggMIS::Types::IntVector_d(roots); + AggMIS::Types::IntVector_d *partIn = new AggMIS::Types::IntVector_d(roots); + + + // Prefix sum to number aggregate roots: + thrust::inclusive_scan(partIn->begin(), partIn->end(), partIn->begin()); + + // Transform non root nodes to -1 + thrust::transform(partIn->begin(), partIn->end(), aggregated->begin(), partIn->begin(), Functors::NumberParts()); + AggMIS::Types::IntVector_d *partOut = new AggMIS::Types::IntVector_d(*partIn); + + // Preparing to call aggregate kernel: + int *partIn_d = thrust::raw_pointer_cast(partIn->data()); // Pointer to partIn vector + int *partOut_d = thrust::raw_pointer_cast(partOut->data()); // Pointer to partOut vector + int *adjIndexes_d = thrust::raw_pointer_cast(graph.indices->data()); // Pointer to adjacency indexes + int *adjacency_d = thrust::raw_pointer_cast(graph.adjacency->data()); // Pointer to adjacency + int *aggregated_d = thrust::raw_pointer_cast(aggregated->data()); // Pointer to aggregated + bool complete = false; // Indicates whether all nodes are aggregated + + // Figuring out block sizes for kernel call: + int blockSize = 256; + int nBlocks = size / blockSize + (size%blockSize == 0 ? 0 : 1); + + while (!complete) + { + // Allocating nodes + Kernels::allocateNodesKernel << < nBlocks, blockSize >> > (size, adjIndexes_d, adjacency_d, partIn_d, partOut_d, aggregated_d); + + // Copying partOut to partIn + thrust::copy(partOut->begin(), partOut->end(), partIn->begin()); + + // Checking if done + int unallocatedNodes = thrust::count(aggregated->begin(), aggregated->end(), 0); + complete = unallocatedNodes == 0; + } + + // Cleaning up + aggregated->clear(); + partOut->clear(); + delete aggregated; + delete partOut; + + return partIn; + } + bool IsValidAggregation(AggMIS::Types::Graph_d &graph, + AggMIS::Types::IntVector_d &aggregation, + bool verbose) { + // Counter for number of errors found + int errors = 0; + + // Check to make sure that the aggregate id's are sequential + AggMIS::Types::IntVector_d scratch(aggregation); + thrust::sort(scratch.begin(), scratch.end()); + int newLength = thrust::unique(scratch.begin(), scratch.end()) - scratch.begin(); + scratch.resize(newLength); + + if (scratch[0] != 0 || scratch[scratch.size() - 1] != scratch.size() - 1) + { + if (verbose) { + printf("Error found in aggregation: improper aggregate indices:\n"); + int firstId = scratch[0]; + int lastId = scratch[scratch.size() - 1]; + int count = scratch.size(); + printf("\tFirst index is %d, last index is %d, there are %d unique id's\n", firstId, lastId, count); } - Graph_d* GetAggregateMap(IntVector_d& aggregation) { - Graph_d* output = new Graph_d(); - // Setting adjacency of output to be indices - GraphHelpers::SetToIndicesVector(aggregation.size(), *(output->adjacency)); - IntVector_d aggLabels(aggregation.begin(), aggregation.end()); - - // Sorting by key to get node id's grouped by aggregates - thrust::sort_by_key(aggLabels.begin(), aggLabels.end(), output->adjacency->begin()); - - // Resizing the indices to aggregate count - int maxAggregate = aggLabels[aggLabels.size() - 1]; - output->indices->resize(maxAggregate + 2, 0); - - // Figuring out block sizes for kernel call: - int size = aggregation.size(); - int blockSize = 256; - int nBlocks = size/blockSize + (size%blockSize == 0?0:1); - - // Calling kernel to find indices for each part: - GraphHelpers::Kernels::findPartIndicesKernel <<< nBlocks, blockSize >>> - (size, - StartOf(aggLabels), - output->indStart()); - - // Cleaning up - aggLabels.clear(); - - return output; + errors++; + return false; + } + + // Check to make sure each aggregate is a connected component + AggMIS::Types::IntVector_d *valuesIn = GraphHelpers::GetIndicesVector(aggregation.size()); + AggMIS::Types::IntVector_d valuesOut(aggregation.size()); + AggMIS::Types::IntVector_d incomplete(1, 1); + + // Figuring out block sizes for kernel call: + int size = graph.Size(); + int blockSize = 256; + int nBlocks = size / blockSize + (size%blockSize == 0 ? 0 : 1); + + // Getting raw pointers + int *valuesIn_d = thrust::raw_pointer_cast(valuesIn->data()); + int *valuesOut_d = thrust::raw_pointer_cast(&valuesOut[0]); + int *incomplete_d = thrust::raw_pointer_cast(&incomplete[0]); + int *adjacency_d = thrust::raw_pointer_cast(graph.adjacency->data()); + int *adjIndices_d = thrust::raw_pointer_cast(graph.indices->data()); + int *aggregation_d = thrust::raw_pointer_cast(&aggregation[0]); + + // Flood filling within each aggregate + int *originalOut = valuesIn_d; + while (incomplete[0] == 1) + { + incomplete[0] = 0; + Kernels::checkAggregationFillAggregates << < nBlocks, blockSize >> > + (size, adjIndices_d, adjacency_d, aggregation_d, valuesIn_d, valuesOut_d, incomplete_d); + int *temp = valuesIn_d; + valuesIn_d = valuesOut_d; + valuesOut_d = temp; + } + + if (originalOut != valuesOut_d) + valuesOut.assign(valuesIn->begin(), valuesIn->end()); + valuesIn->assign(aggregation.begin(), aggregation.end()); + + // + int correctLength = newLength; + thrust::sort(thrust::make_zip_iterator(thrust::make_tuple(valuesIn->begin(), valuesOut.begin())), + thrust::make_zip_iterator(thrust::make_tuple(valuesIn->end(), valuesOut.end()))); + newLength = thrust::unique(thrust::make_zip_iterator(thrust::make_tuple(valuesOut.begin(), valuesIn->begin())), + thrust::make_zip_iterator(thrust::make_tuple(valuesOut.end(), valuesIn->end()))) + - thrust::make_zip_iterator(thrust::make_tuple(valuesOut.begin(), valuesIn->begin())); + + valuesIn->resize(newLength); + valuesOut.resize(newLength); + + if (newLength != correctLength) + { + if (verbose) + printf("Error: there were %d connected components found and %d aggregates\n", newLength, correctLength); + errors++; + + AggMIS::Types::IntVector_h aggIds(*valuesIn); + AggMIS::Types::IntVector_h nodeIds(valuesOut); + for (int i = 0; i < valuesOut.size() - 1; i++) + { + int currentAgg = aggIds[i]; + int nextAgg = aggIds[i + 1]; + if (currentAgg == nextAgg && verbose) + printf("Aggregate %d was filled from %d and %d\n", currentAgg, nodeIds[i], nodeIds[i + 1]); } + } + + // Clean up + scratch.resize(0); + valuesIn->resize(0); + delete valuesIn; + incomplete.resize(0); + + return errors == 0; + } + AggMIS::Types::Graph_d* GetAggregateMap(AggMIS::Types::IntVector_d& aggregation) { + AggMIS::Types::Graph_d* output = new AggMIS::Types::Graph_d(); + // Setting adjacency of output to be indices + GraphHelpers::SetToIndicesVector(aggregation.size(), *(output->adjacency)); + AggMIS::Types::IntVector_d aggLabels(aggregation.begin(), aggregation.end()); + + // Sorting by key to get node id's grouped by aggregates + thrust::sort_by_key(aggLabels.begin(), aggLabels.end(), output->adjacency->begin()); + + // Resizing the indices to aggregate count + int maxAggregate = aggLabels[aggLabels.size() - 1]; + output->indices->resize(maxAggregate + 2, 0); + + // Figuring out block sizes for kernel call: + int size = aggregation.size(); + int blockSize = 256; + int nBlocks = size / blockSize + (size%blockSize == 0 ? 0 : 1); + + // Calling kernel to find indices for each part: + GraphHelpers::Kernels::findPartIndicesKernel << < nBlocks, blockSize >> > + (size, + AggMIS::Types::StartOf(aggLabels), + output->indStart()); + + // Cleaning up + aggLabels.clear(); + + return output; } + } } diff --git a/src/core/aggmis/cuda/AggMIS_GraphHelpers.cu b/src/core/aggmis/cuda/AggMIS_GraphHelpers.cu index 5256207..7bda760 100644 --- a/src/core/aggmis/cuda/AggMIS_GraphHelpers.cu +++ b/src/core/aggmis/cuda/AggMIS_GraphHelpers.cu @@ -1,436 +1,435 @@ -/* +/* * File: AggMIS_GraphHelpers.cu * Author: T. James Lewis * * Created on April 16, 2013, 2:58 PM */ - #include +#include #include "AggMIS_GraphHelpers.h" namespace AggMIS { - namespace GraphHelpers { - namespace Kernels { - __global__ void mapAdjacencyToBlockKernel(int size, - int *adjIndexes, - int *adjacency, - int *adjacencyBlockLabel, - int *blockMappedAdjacency, - int *fineAggregate) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - int begin = adjIndexes[idx]; - int end = adjIndexes[idx + 1]; - int thisBlock = fineAggregate[idx]; - - // Fill block labeled adjacency and block mapped adjacency vectors - for (int i = begin; i < end; i++) - { - int neighbor = fineAggregate[adjacency[i]]; - - if (thisBlock == neighbor) - { - adjacencyBlockLabel[i] = - 1; - blockMappedAdjacency[i] = - 1; - } - else - { - adjacencyBlockLabel[i] = thisBlock; - blockMappedAdjacency[i] = neighbor; - } - } - } - } - __global__ void findPartIndicesNegStartKernel(int size, - int *array, - int *partIndices) { - int idx = blockIdx.x * blockDim.x + threadIdx.x + 1; - if (idx < size) - { - int value = array[idx]; - int nextValue = array[idx + 1]; - if (value != nextValue) - partIndices[value + 1] = idx; - } - } - __global__ void findPartIndicesKernel(int size, - int *array, - int *partIndices) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - int value = array[idx]; - int nextValue = (idx != size - 1) ? array[idx + 1] : -1; - if (value != nextValue) - { - partIndices[value + 1] = idx + 1; - } - } - } - __global__ void findAdjacencySizesKernel(int size, - int *adjIndexes, - int *output) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - output[idx] = adjIndexes[idx + 1] - adjIndexes[idx]; - } - } - __global__ void accumulatedPartSizesKernel(int size, - int *part, - int *weights, - int *accumulatedSize) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if(idx == size - 1) - accumulatedSize[part[idx]] = weights[idx]; - if(idx < size - 1) - { - int thisPart = part[idx]; - if(thisPart != part[idx + 1]) - accumulatedSize[thisPart] = weights[idx]; - } - } + namespace GraphHelpers { + namespace Kernels { + __global__ void mapAdjacencyToBlockKernel(int size, + int *adjIndexes, + int *adjacency, + int *adjacencyBlockLabel, + int *blockMappedAdjacency, + int *fineAggregate) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + int begin = adjIndexes[idx]; + int end = adjIndexes[idx + 1]; + int thisBlock = fineAggregate[idx]; - __global__ void unaccumulatedPartSizesKernel(int size, int *accumulatedSize, int *sizes) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if(idx == 0) - sizes[idx] = accumulatedSize[0]; + // Fill block labeled adjacency and block mapped adjacency vectors + for (int i = begin; i < end; i++) + { + int neighbor = fineAggregate[adjacency[i]]; - else if(idx < size) - { - sizes[idx] = accumulatedSize[idx] - accumulatedSize[idx - 1]; - } + if (thisBlock == neighbor) + { + adjacencyBlockLabel[i] = -1; + blockMappedAdjacency[i] = -1; + } else + { + adjacencyBlockLabel[i] = thisBlock; + blockMappedAdjacency[i] = neighbor; } - - } - Graph_d* GetInducedGraph(Graph_d &graph, - IntVector_d &aggregation) { - // Get references to parts of input graph and output graph - IntVector_d &adjIndexesIn = *(graph.indices); - IntVector_d &adjacencyIn = *(graph.adjacency); - Graph_d *result = new Graph_d(); - IntVector_d &adjIndexesOut = *(result->indices); - IntVector_d &adjacencyOut = *(result->adjacency); - - // Declaring temporary vectors: - IntVector_d adjacencyBlockLabel, blockMappedAdjacency; - adjacencyBlockLabel.resize(adjacencyIn.size(),0); - blockMappedAdjacency.resize(adjacencyIn.size(),0); - - // Get the blocklabeled adjacency: - mapAdjacencyToBlock(adjIndexesIn, adjacencyIn, adjacencyBlockLabel, blockMappedAdjacency, aggregation); - - // Zip up the block label and block mapped vectors and sort: - thrust::sort(thrust::make_zip_iterator( - thrust::make_tuple(adjacencyBlockLabel.begin(), blockMappedAdjacency.begin())), - thrust::make_zip_iterator( - thrust::make_tuple(adjacencyBlockLabel.end(), blockMappedAdjacency.end()))); - - // Remove Duplicates and resize: - int newSize = thrust::unique( - thrust::make_zip_iterator( - thrust::make_tuple(adjacencyBlockLabel.begin(), blockMappedAdjacency.begin())), - thrust::make_zip_iterator( - thrust::make_tuple(adjacencyBlockLabel.end(), blockMappedAdjacency.end()))) - - thrust::make_zip_iterator(thrust::make_tuple(adjacencyBlockLabel.begin(), blockMappedAdjacency.begin())); - - adjacencyBlockLabel.resize(newSize); - blockMappedAdjacency.resize(newSize); - getPartIndicesNegStart(adjacencyBlockLabel, adjIndexesOut); - adjacencyOut.resize(blockMappedAdjacency.size() - 1); - thrust::copy(blockMappedAdjacency.begin() + 1, blockMappedAdjacency.end(), adjacencyOut.begin()); - return result; + } } - Graph_h* GetInducedGraph(Graph_h& graph, - IntVector_h& aggregation) { - // Get references to graph indices and adjacency - IntVector_h &ind = *(graph.indices); - IntVector_h &adj = *(graph.adjacency); - - // A temporary container for the induced graph - vector > tempGraph; - - // Filling in the temporary container - for (int node = 0; node < graph.Size(); node++) { - int startAgg = aggregation[node]; - for (int nIt = ind[node]; nIt < ind[node + 1]; nIt++) { - int endAgg = aggregation[adj[nIt]]; - - // If this is an edge between two aggregates add to - // the induced graph. - if (startAgg != endAgg && startAgg < endAgg) { - // Making sure that there are entries in temp - if (endAgg >= tempGraph.size()) - tempGraph.resize(endAgg + 1); - - // Adding edge entries - if (tempGraph[startAgg].size() == 0 || - !(std::binary_search(tempGraph[startAgg].begin(), - tempGraph[startAgg].end(), - endAgg))) { - tempGraph[startAgg].push_back(endAgg); - std::sort(tempGraph[startAgg].begin(), tempGraph[startAgg].end()); - } - if (tempGraph[endAgg].size() == 0 || - !(std::binary_search(tempGraph[endAgg].begin(), - tempGraph[endAgg].end(), - startAgg))) { - tempGraph[endAgg].push_back(startAgg); - std::sort(tempGraph[endAgg].begin(), tempGraph[endAgg].end()); - } - } - } - } - - // Copying out to graph format - Graph_h *result = new Graph_h(); - IntVector_h &indOut = *(result->indices); - IntVector_h &adjOut = *(result->adjacency); - - // Getting new indices - indOut.resize(tempGraph.size() + 1); - indOut[0] = 0; - for (int i = 0; i < tempGraph.size(); i++) - indOut[i + 1] = indOut[i] + tempGraph[i].size(); - - // Writing out adjacency - adjOut.resize(indOut.back()); - int insertAt = 0; - for (int i = 0; i < tempGraph.size(); i++) { - for (int j = 0; j < tempGraph[i].size(); j++) { - adjOut[insertAt++] = tempGraph[i][j]; - } - } - - return result; + } + __global__ void findPartIndicesNegStartKernel(int size, + int *array, + int *partIndices) { + int idx = blockIdx.x * blockDim.x + threadIdx.x + 1; + if (idx < size) + { + int value = array[idx]; + int nextValue = array[idx + 1]; + if (value != nextValue) + partIndices[value + 1] = idx; } - void mapAdjacencyToBlock(IntVector_d &adjIndexes, - IntVector_d &adjacency, - IntVector_d &adjacencyBlockLabel, - IntVector_d &blockMappedAdjacency, - IntVector_d &fineAggregate) { - int size = adjIndexes.size() - 1; - - // Get pointers to device memory of arrays - int *adjIndexes_d = thrust::raw_pointer_cast(&adjIndexes[0]); - int *adjacency_d = thrust::raw_pointer_cast(&adjacency[0]); - int *adjacencyBlockLabel_d = thrust::raw_pointer_cast(&adjacencyBlockLabel[0]); - int *blockMappedAdjacency_d = thrust::raw_pointer_cast(&blockMappedAdjacency[0]); - int *fineAggregate_d = thrust::raw_pointer_cast(&fineAggregate[0]); - - // Figuring out block sizes for kernel call: - int blockSize = 256; - int nBlocks = size / blockSize + (size % blockSize == 0?0:1); - - // Calling kernel: - Kernels::mapAdjacencyToBlockKernel <<< nBlocks, blockSize >>> (size, adjIndexes_d, adjacency_d, adjacencyBlockLabel_d, blockMappedAdjacency_d, fineAggregate_d); + } + __global__ void findPartIndicesKernel(int size, + int *array, + int *partIndices) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + int value = array[idx]; + int nextValue = (idx != size - 1) ? array[idx + 1] : -1; + if (value != nextValue) + { + partIndices[value + 1] = idx + 1; + } } - void getPartIndicesNegStart(IntVector_d& sortedPartition, - IntVector_d& partIndices) { - // Sizing the array: - int maxPart = max(0,sortedPartition[sortedPartition.size() - 1]); - partIndices.resize(maxPart + 2, 0); - - // Figuring out block sizes for kernel call: - int size = sortedPartition.size(); - int blockSize = 256; - int nBlocks = size/blockSize + (size%blockSize == 0?0:1); - - // Getting pointers - int *sortedPartition_d = thrust::raw_pointer_cast(&sortedPartition[0]); - int *partIndices_d = thrust::raw_pointer_cast(&partIndices[0]); - - // Calling kernel to find indices for each part: - Kernels::findPartIndicesNegStartKernel <<< nBlocks, blockSize >>> (size, sortedPartition_d, partIndices_d); - partIndices[partIndices.size() - 1] = size - 1; + } + __global__ void findAdjacencySizesKernel(int size, + int *adjIndexes, + int *output) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + output[idx] = adjIndexes[idx + 1] - adjIndexes[idx]; } - IntVector_d* GetIndicesVector(int size) { - thrust::counting_iterator start(0); - thrust::counting_iterator end = start + size; - return new IntVector_d(start, end); + } + __global__ void accumulatedPartSizesKernel(int size, + int *part, + int *weights, + int *accumulatedSize) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx == size - 1) + accumulatedSize[part[idx]] = weights[idx]; + if (idx < size - 1) + { + int thisPart = part[idx]; + if (thisPart != part[idx + 1]) + accumulatedSize[thisPart] = weights[idx]; } - void SetToIndicesVector(int size, - IntVector_d& toSet) { - thrust::counting_iterator start(0); - thrust::counting_iterator end = start + size; - toSet.assign(start, end); + } + + __global__ void unaccumulatedPartSizesKernel(int size, int *accumulatedSize, int *sizes) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx == 0) + sizes[idx] = accumulatedSize[0]; + + else if (idx < size) + { + sizes[idx] = accumulatedSize[idx] - accumulatedSize[idx - 1]; } - void getPartSizes(IntVector_d &aggregation, - IntVector_d &sizes) { - // Make a copy of the partition vector to mess with: - IntVector_d temp(aggregation); + } - // Sort the copy and find largest element - thrust::sort(temp.begin(), temp.end()); - int maxPart = temp[temp.size() - 1]; + } + AggMIS::Types::Graph_d* GetInducedGraph(AggMIS::Types::Graph_d &graph, + AggMIS::Types::IntVector_d &aggregation) { + // Get references to parts of input graph and output graph + AggMIS::Types::IntVector_d &adjIndexesIn = *(graph.indices); + AggMIS::Types::IntVector_d &adjacencyIn = *(graph.adjacency); + AggMIS::Types::Graph_d *result = new AggMIS::Types::Graph_d(); + AggMIS::Types::IntVector_d &adjIndexesOut = *(result->indices); + AggMIS::Types::IntVector_d &adjacencyOut = *(result->adjacency); - // Creating a new array size - IntVector_d partIndices(maxPart + 2, 0); + // Declaring temporary vectors: + AggMIS::Types::IntVector_d adjacencyBlockLabel, blockMappedAdjacency; + adjacencyBlockLabel.resize(adjacencyIn.size(), 0); + blockMappedAdjacency.resize(adjacencyIn.size(), 0); - // Figuring out block sizes for kernel call: - int size = aggregation.size(); - int blockSize = 256; - int nBlocks = size/blockSize + (size%blockSize == 0?0:1); + // Get the blocklabeled adjacency: + mapAdjacencyToBlock(adjIndexesIn, adjacencyIn, adjacencyBlockLabel, blockMappedAdjacency, aggregation); - // Getting pointers - int *temp_d = thrust::raw_pointer_cast(&temp[0]); - int *partIndices_d = thrust::raw_pointer_cast(&partIndices[0]); + // Zip up the block label and block mapped vectors and sort: + thrust::sort(thrust::make_zip_iterator( + thrust::make_tuple(adjacencyBlockLabel.begin(), blockMappedAdjacency.begin())), + thrust::make_zip_iterator( + thrust::make_tuple(adjacencyBlockLabel.end(), blockMappedAdjacency.end()))); - // Calling kernel to find indices for each part: - Kernels::findPartIndicesKernel <<< nBlocks, blockSize >>> (size, temp_d, partIndices_d); + // Remove Duplicates and resize: + int newSize = thrust::unique( + thrust::make_zip_iterator( + thrust::make_tuple(adjacencyBlockLabel.begin(), blockMappedAdjacency.begin())), + thrust::make_zip_iterator( + thrust::make_tuple(adjacencyBlockLabel.end(), blockMappedAdjacency.end()))) - + thrust::make_zip_iterator(thrust::make_tuple(adjacencyBlockLabel.begin(), blockMappedAdjacency.begin())); - // Preparing sizes vector - size = partIndices.size() - 1; - sizes.resize(size); - int *sizes_d = thrust::raw_pointer_cast(&sizes[0]); + adjacencyBlockLabel.resize(newSize); + blockMappedAdjacency.resize(newSize); + getPartIndicesNegStart(adjacencyBlockLabel, adjIndexesOut); + adjacencyOut.resize(blockMappedAdjacency.size() - 1); + thrust::copy(blockMappedAdjacency.begin() + 1, blockMappedAdjacency.end(), adjacencyOut.begin()); + return result; + } + AggMIS::Types::Graph_h* GetInducedGraph(AggMIS::Types::Graph_h& graph, + AggMIS::Types::IntVector_h& aggregation) { + // Get references to graph indices and adjacency + AggMIS::Types::IntVector_h &ind = *(graph.indices); + AggMIS::Types::IntVector_h &adj = *(graph.adjacency); - // Calling kernel to find sizes: - Kernels::findAdjacencySizesKernel <<< nBlocks, blockSize >>> (size, partIndices_d, sizes_d); + // A temporary container for the induced graph + std::vector > tempGraph; - // Cleaning up - temp.resize(0); - partIndices.resize(0); - } - void getPartSizes(IntVector_d& aggregation, - IntVector_d& sizes, - IntVector_d& weights) { - // Make copies to mess with - IntVector_d tempAgg(aggregation.begin(), aggregation.end()); - IntVector_d tempWeight(weights.begin(), weights.end()); - - // Sorting temp vectors together - thrust::sort_by_key(tempAgg.begin(), tempAgg.end(), tempWeight.begin()); - - // Getting prefix sum of values - thrust::inclusive_scan(tempWeight.begin(), tempWeight.end(), tempWeight.begin()); - - // Another temp vector for accumulated size at last nodes - IntVector_d accumulatedSize(tempAgg[tempAgg.size() - 1] + 1); - - // Preparing to call kernel to fill accumulated size vector - int size = tempAgg.size(); - - // Figuring out block sizes for kernel call: - int blockSize = 256; - int nBlocks = size / blockSize + (size % blockSize == 0 ? 0 : 1); - - Kernels::accumulatedPartSizesKernel <<< nBlocks, blockSize >>> - (size, - StartOf(tempAgg), - StartOf(tempWeight), - StartOf(accumulatedSize)); - - // Calling kernel to get the un-accumulated part sizes: - size = accumulatedSize.size(); - nBlocks = size / blockSize + (size % blockSize == 0 ? 0 : 1); - sizes.resize(size); - Kernels::unaccumulatedPartSizesKernel <<< nBlocks, blockSize >>> - (size, - StartOf(accumulatedSize), - StartOf(sizes)); - } - IntVector_d* GetValences(Graph_d &graph) { - IntVector_d *result = new IntVector_d(graph.indices->size()-1); - thrust::adjacent_difference(graph.indices->begin() + 1, - graph.indices->end(), - result->begin()); - return result; - } - IntVector_h* GetValences(Graph_h &graph) { - IntVector_h *result = new IntVector_h(graph.indices->size()-1); - thrust::adjacent_difference(graph.indices->begin() + 1, - graph.indices->end(), - result->begin()); - return result; + // Filling in the temporary container + for (int node = 0; node < graph.Size(); node++) { + int startAgg = aggregation[node]; + for (int nIt = ind[node]; nIt < ind[node + 1]; nIt++) { + int endAgg = aggregation[adj[nIt]]; + + // If this is an edge between two aggregates add to + // the induced graph. + if (startAgg != endAgg && startAgg < endAgg) { + // Making sure that there are entries in temp + if (endAgg >= tempGraph.size()) + tempGraph.resize(endAgg + 1); + + // Adding edge entries + if (tempGraph[startAgg].size() == 0 || + !(std::binary_search(tempGraph[startAgg].begin(), + tempGraph[startAgg].end(), + endAgg))) { + tempGraph[startAgg].push_back(endAgg); + std::sort(tempGraph[startAgg].begin(), tempGraph[startAgg].end()); + } + if (tempGraph[endAgg].size() == 0 || + !(std::binary_search(tempGraph[endAgg].begin(), + tempGraph[endAgg].end(), + startAgg))) { + tempGraph[endAgg].push_back(startAgg); + std::sort(tempGraph[endAgg].begin(), tempGraph[endAgg].end()); + } + } } - bool IsGraphValid(Graph_d& graph) { - // Call the override with the indices and adjacency of the graph - return IsGraphValid(*graph.indices, *graph.adjacency); + } + + // Copying out to graph format + AggMIS::Types::Graph_h *result = new AggMIS::Types::Graph_h(); + AggMIS::Types::IntVector_h &indOut = *(result->indices); + AggMIS::Types::IntVector_h &adjOut = *(result->adjacency); + + // Getting new indices + indOut.resize(tempGraph.size() + 1); + indOut[0] = 0; + for (int i = 0; i < tempGraph.size(); i++) + indOut[i + 1] = indOut[i] + tempGraph[i].size(); + + // Writing out adjacency + adjOut.resize(indOut.back()); + int insertAt = 0; + for (int i = 0; i < tempGraph.size(); i++) { + for (int j = 0; j < tempGraph[i].size(); j++) { + adjOut[insertAt++] = tempGraph[i][j]; } - bool IsGraphValid(Graph_h& graph) { - // Call the override with the indices and adjacency of the graph - return IsGraphValid(*graph.indices, *graph.adjacency); + } + + return result; + } + void mapAdjacencyToBlock(AggMIS::Types::IntVector_d &adjIndexes, + AggMIS::Types::IntVector_d &adjacency, + AggMIS::Types::IntVector_d &adjacencyBlockLabel, + AggMIS::Types::IntVector_d &blockMappedAdjacency, + AggMIS::Types::IntVector_d &fineAggregate) { + int size = adjIndexes.size() - 1; + + // Get pointers to device memory of arrays + int *adjIndexes_d = thrust::raw_pointer_cast(&adjIndexes[0]); + int *adjacency_d = thrust::raw_pointer_cast(&adjacency[0]); + int *adjacencyBlockLabel_d = thrust::raw_pointer_cast(&adjacencyBlockLabel[0]); + int *blockMappedAdjacency_d = thrust::raw_pointer_cast(&blockMappedAdjacency[0]); + int *fineAggregate_d = thrust::raw_pointer_cast(&fineAggregate[0]); + + // Figuring out block sizes for kernel call: + int blockSize = 256; + int nBlocks = size / blockSize + (size % blockSize == 0 ? 0 : 1); + + // Calling kernel: + Kernels::mapAdjacencyToBlockKernel << < nBlocks, blockSize >> > (size, adjIndexes_d, adjacency_d, adjacencyBlockLabel_d, blockMappedAdjacency_d, fineAggregate_d); + } + void getPartIndicesNegStart(AggMIS::Types::IntVector_d& sortedPartition, + AggMIS::Types::IntVector_d& partIndices) { + // Sizing the array: + int maxPart = max(0, sortedPartition[sortedPartition.size() - 1]); + partIndices.resize(maxPart + 2, 0); + + // Figuring out block sizes for kernel call: + int size = sortedPartition.size(); + int blockSize = 256; + int nBlocks = size / blockSize + (size%blockSize == 0 ? 0 : 1); + + // Getting pointers + int *sortedPartition_d = thrust::raw_pointer_cast(&sortedPartition[0]); + int *partIndices_d = thrust::raw_pointer_cast(&partIndices[0]); + + // Calling kernel to find indices for each part: + Kernels::findPartIndicesNegStartKernel << < nBlocks, blockSize >> > (size, sortedPartition_d, partIndices_d); + partIndices[partIndices.size() - 1] = size - 1; + } + AggMIS::Types::IntVector_d* GetIndicesVector(int size) { + thrust::counting_iterator start(0); + thrust::counting_iterator end = start + size; + return new AggMIS::Types::IntVector_d(start, end); + } + void SetToIndicesVector(int size, + AggMIS::Types::IntVector_d& toSet) { + thrust::counting_iterator start(0); + thrust::counting_iterator end = start + size; + toSet.assign(start, end); + } + void getPartSizes(AggMIS::Types::IntVector_d &aggregation, + AggMIS::Types::IntVector_d &sizes) { + // Make a copy of the partition vector to mess with: + AggMIS::Types::IntVector_d temp(aggregation); + + // Sort the copy and find largest element + thrust::sort(temp.begin(), temp.end()); + int maxPart = temp[temp.size() - 1]; + + // Creating a new array size + AggMIS::Types::IntVector_d partIndices(maxPart + 2, 0); + + // Figuring out block sizes for kernel call: + int size = aggregation.size(); + int blockSize = 256; + int nBlocks = size / blockSize + (size%blockSize == 0 ? 0 : 1); + + // Getting pointers + int *temp_d = thrust::raw_pointer_cast(&temp[0]); + int *partIndices_d = thrust::raw_pointer_cast(&partIndices[0]); + + // Calling kernel to find indices for each part: + Kernels::findPartIndicesKernel << < nBlocks, blockSize >> > (size, temp_d, partIndices_d); + + // Preparing sizes vector + size = partIndices.size() - 1; + sizes.resize(size); + int *sizes_d = thrust::raw_pointer_cast(&sizes[0]); + + // Calling kernel to find sizes: + Kernels::findAdjacencySizesKernel << < nBlocks, blockSize >> > (size, partIndices_d, sizes_d); + + // Cleaning up + temp.resize(0); + partIndices.resize(0); + } + void getPartSizes(AggMIS::Types::IntVector_d& aggregation, + AggMIS::Types::IntVector_d& sizes, + AggMIS::Types::IntVector_d& weights) { + // Make copies to mess with + AggMIS::Types::IntVector_d tempAgg(aggregation.begin(), aggregation.end()); + AggMIS::Types::IntVector_d tempWeight(weights.begin(), weights.end()); + + // Sorting temp vectors together + thrust::sort_by_key(tempAgg.begin(), tempAgg.end(), tempWeight.begin()); + + // Getting prefix sum of values + thrust::inclusive_scan(tempWeight.begin(), tempWeight.end(), tempWeight.begin()); + + // Another temp vector for accumulated size at last nodes + AggMIS::Types::IntVector_d accumulatedSize(tempAgg[tempAgg.size() - 1] + 1); + + // Preparing to call kernel to fill accumulated size vector + int size = tempAgg.size(); + + // Figuring out block sizes for kernel call: + int blockSize = 256; + int nBlocks = size / blockSize + (size % blockSize == 0 ? 0 : 1); + + Kernels::accumulatedPartSizesKernel << < nBlocks, blockSize >> > + (size, + AggMIS::Types::StartOf(tempAgg), + AggMIS::Types::StartOf(tempWeight), + AggMIS::Types::StartOf(accumulatedSize)); + + // Calling kernel to get the un-accumulated part sizes: + size = accumulatedSize.size(); + nBlocks = size / blockSize + (size % blockSize == 0 ? 0 : 1); + sizes.resize(size); + Kernels::unaccumulatedPartSizesKernel << < nBlocks, blockSize >> > + (size, + AggMIS::Types::StartOf(accumulatedSize), + AggMIS::Types::StartOf(sizes)); + } + AggMIS::Types::IntVector_d* GetValences(AggMIS::Types::Graph_d &graph) { + AggMIS::Types::IntVector_d *result = new AggMIS::Types::IntVector_d(graph.indices->size() - 1); + thrust::adjacent_difference(graph.indices->begin() + 1, + graph.indices->end(), + result->begin()); + return result; + } + AggMIS::Types::IntVector_h* GetValences(AggMIS::Types::Graph_h &graph) { + AggMIS::Types::IntVector_h *result = new AggMIS::Types::IntVector_h(graph.indices->size() - 1); + thrust::adjacent_difference(graph.indices->begin() + 1, + graph.indices->end(), + result->begin()); + return result; + } + bool IsGraphValid(AggMIS::Types::Graph_d& graph) { + // Call the override with the indices and adjacency of the graph + return IsGraphValid(*graph.indices, *graph.adjacency); + } + bool IsGraphValid(AggMIS::Types::Graph_h& graph) { + // Call the override with the indices and adjacency of the graph + return IsGraphValid(*graph.indices, *graph.adjacency); + } + bool IsGraphValid(AggMIS::Types::IntVector_d& indices, AggMIS::Types::IntVector_d& adjacency) { + // Get temporary host vectors to call with + AggMIS::Types::IntVector_h tempInd(indices); + AggMIS::Types::IntVector_h tempAdj(adjacency); + + // Call host vector override + bool result = IsGraphValid(tempInd, tempAdj); + + // Clean up temp arrays + tempInd.clear(); + tempAdj.clear(); + + return result; + } + bool IsGraphValid(AggMIS::Types::IntVector_h& indices, AggMIS::Types::IntVector_h& adjacency) { + // Get size of graph + int graphSize = indices.size() - 1; + + // If there are no nodes return with error + if (graphSize <= 0) { + printf("Graph is empty, no nodes specified!\n"); + return false; + } + + // Check that the indices are all in order + if (indices[0] != 0) { + int first = indices[0]; + printf("Indices are not proper, start with %d not 0\n", first); + return false; + } + for (int i = 1; i < indices.size(); i++) { + if (indices[i] <= indices[i - 1]) { + int a = indices[i - 1]; + int b = indices[i]; + printf("Non-sequential indices: indices[%d]=%d but indices[%d]=%d\n", + i - 1, a, i, b); + return false; } - bool IsGraphValid(IntVector_d& indices, IntVector_d& adjacency) { - // Get temporary host vectors to call with - IntVector_h tempInd(indices); - IntVector_h tempAdj(adjacency); - - // Call host vector override - bool result = IsGraphValid(tempInd, tempAdj); - - // Clean up temp arrays - tempInd.clear(); - tempAdj.clear(); - - return result; + } + if (indices[indices.size() - 1] > adjacency.size()) { + printf("Largest index points outside of adjacency array!\n"); + return false; + } + + // Check that adjacency contains only valid node Id's + for (int i = 0; i < adjacency.size(); i++) { + int nodeId = adjacency[i]; + if (nodeId < 0 || nodeId >= graphSize) { + printf("adjacency[%d]=%d but graphSize=%d\n", + i, nodeId, graphSize); + return false; } - bool IsGraphValid(IntVector_h& indices, IntVector_h& adjacency) { - // Get size of graph - int graphSize = indices.size() - 1; - - // If there are no nodes return with error - if (graphSize <= 0) { - printf("Graph is empty, no nodes specified!\n"); - return false; - } - - // Check that the indices are all in order - if (indices[0] != 0) { - int first = indices[0]; - printf("Indices are not proper, start with %d not 0\n", first); - return false; - } - for (int i = 1; i < indices.size(); i++) { - if (indices[i] <= indices[i - 1]) { - int a = indices[i - 1]; - int b = indices[i]; - printf("Non-sequential indices: indices[%d]=%d but indices[%d]=%d\n", - i-1, a, i, b); - return false; - } - } - if (indices[indices.size()-1] > adjacency.size()) { - printf("Largest index points outside of adjacency array!\n"); - return false; - } - - // Check that adjacency contains only valid node Id's - for (int i = 0; i < adjacency.size(); i++) { - int nodeId = adjacency[i]; - if (nodeId < 0 || nodeId >= graphSize) { - printf("adjacency[%d]=%d but graphSize=%d\n", - i, nodeId, graphSize); - return false; - } - } - - // Check that all neighbor lists are mutually consistent - int errorCount = 0; - for (int i = 0; i < graphSize; i++) - { - int rootIdx = i; - for (int j = indices[i]; j < indices[i + 1]; j++) - { - int neighborIdx = adjacency[j]; - bool found = false; - for (int jj = indices[neighborIdx]; jj < indices[neighborIdx + 1]; jj++) - { - if (adjacency[jj] == rootIdx) - found = true; - } - if (!found) { - printf("Node %d has neighbor %d but not reverse!\n", rootIdx, neighborIdx); - errorCount++; - } - } - } - if (errorCount > 0) { - printf("Found %d inconsistencies in adjacency.\n", errorCount); - return false; - } - - // If we haven't returned yet things are good. - return true; + } + + // Check that all neighbor lists are mutually consistent + int errorCount = 0; + for (int i = 0; i < graphSize; i++) + { + int rootIdx = i; + for (int j = indices[i]; j < indices[i + 1]; j++) + { + int neighborIdx = adjacency[j]; + bool found = false; + for (int jj = indices[neighborIdx]; jj < indices[neighborIdx + 1]; jj++) + { + if (adjacency[jj] == rootIdx) + found = true; + } + if (!found) { + printf("Node %d has neighbor %d but not reverse!\n", rootIdx, neighborIdx); + errorCount++; + } } + } + if (errorCount > 0) { + printf("Found %d inconsistencies in adjacency.\n", errorCount); + return false; + } + + // If we haven't returned yet things are good. + return true; } + } } \ No newline at end of file diff --git a/src/core/aggmis/cuda/AggMIS_IOHelpers.cu b/src/core/aggmis/cuda/AggMIS_IOHelpers.cu index 4737f52..0564abf 100644 --- a/src/core/aggmis/cuda/AggMIS_IOHelpers.cu +++ b/src/core/aggmis/cuda/AggMIS_IOHelpers.cu @@ -7,40 +7,40 @@ #include "AggMIS_IOHelpers.h" namespace AggMIS { namespace InputHelpers { - string GetNonEmptyLineCIN() { - string b; + std::string GetNonEmptyLineCIN() { + std::string b; char dumb; - while (cin.peek() == '\n') - cin.get(dumb); - getline(cin, b); + while (std::cin.peek() == '\n') + std::cin.get(dumb); + std::getline(std::cin, b); return b; } - int GetSingleIntegerValueCIN() { - string input; + int GetSingleIntegerValuecin() { + std::string input; char dumb; while (true) { - while (cin.peek() == '\n') - cin.get(dumb); - getline(cin, input); - stringstream str(input); + while (std::cin.peek() == '\n') + std::cin.get(dumb); + std::getline(std::cin, input); + std::stringstream str(input); int result; if (str >> result) return result; - cout << "Please enter a number\n:"; + std::cout << "Please enter a number\n:"; } } - vector GetIntegerValuesCIN() { - string input; + std::vector GetIntegerValuescin() { + std::string input; char dumb; int value; - vector values; + std::vector values; while (true) { - while (cin.peek() == '\n') - cin.get(dumb); - getline(cin, input); - stringstream stream(input); + while (std::cin.peek() == '\n') + std::cin.get(dumb); + std::getline(std::cin, input); + std::stringstream stream(input); while(!stream.eof()) { if (stream >> value) @@ -48,13 +48,13 @@ namespace AggMIS { else { stream.clear(); - string dumber; + std::string dumber; stream >> dumber; } } if (values.size() > 0) return values; - cout << "Please enter at least one number\n:"; + std::cout << "Please enter at least one number\n:"; } } } diff --git a/src/core/aggmis/cuda/AggMIS_MIS_CPU.cu b/src/core/aggmis/cuda/AggMIS_MIS_CPU.cu index 2f119fa..f33414c 100644 --- a/src/core/aggmis/cuda/AggMIS_MIS_CPU.cu +++ b/src/core/aggmis/cuda/AggMIS_MIS_CPU.cu @@ -22,13 +22,13 @@ namespace AggMIS { return false; } }; - IntVector_h* FloodFillMIS(int k, Graph_h &graph) { - IntVector_h *m = new IntVector_h(graph.Size(), -1); - IntVector_h &mis = *m; - IntVector_h visited(graph.Size(), 0); - IntVector_h distances(graph.Size(), 1000); - queue frontier; - priority_queue, fringeNodeComparer> fringe; + AggMIS::Types::IntVector_h* FloodFillMIS(int k, AggMIS::Types::Graph_h &graph) { + AggMIS::Types::IntVector_h *m = new AggMIS::Types::IntVector_h(graph.Size(), -1); + AggMIS::Types::IntVector_h &mis = *m; + AggMIS::Types::IntVector_h visited(graph.Size(), 0); + AggMIS::Types::IntVector_h distances(graph.Size(), 1000); + std::queue frontier; + std::priority_queue, fringeNodeComparer> fringe; // Picking a random starting point: @@ -139,10 +139,10 @@ namespace AggMIS { distances.clear(); return m; } - IntVector_h* NaiveMIS(int k, Graph_h graph) { - IntVector_h *m = new IntVector_h(graph.Size(), -1); - IntVector_h &mis = *m; - IntVector_h distances(graph.Size(), 1000); + AggMIS::Types::IntVector_h* NaiveMIS(int k, AggMIS::Types::Graph_h graph) { + AggMIS::Types::IntVector_h *m = new AggMIS::Types::IntVector_h(graph.Size(), -1); + AggMIS::Types::IntVector_h &mis = *m; + AggMIS::Types::IntVector_h distances(graph.Size(), 1000); for (int i = 0; i < graph.Size(); i++) { if (mis[i] == -1) @@ -150,7 +150,7 @@ namespace AggMIS { mis[i] = 1; distances[i] = 0; - queue frontier; + std::queue frontier; // Pushing neighbors of mis node onto frontier to start out int start = (*(graph.indices))[i]; diff --git a/src/core/aggmis/cuda/AggMIS_MIS_GPU.cu b/src/core/aggmis/cuda/AggMIS_MIS_GPU.cu index 077f844..63efe21 100644 --- a/src/core/aggmis/cuda/AggMIS_MIS_GPU.cu +++ b/src/core/aggmis/cuda/AggMIS_MIS_GPU.cu @@ -1,4 +1,4 @@ -/* +/* * File: AggMIS_MIS_GPU.cu * Author: T. James Lewis * @@ -7,398 +7,396 @@ #include "AggMIS_MIS_GPU.h" #include "AggMIS_Types.h" namespace AggMIS { - namespace MIS { - using namespace AggMIS::Types; - using namespace std; - namespace Kernels { - __global__ void GenerateRandoms(int size, - int iterations, - unsigned int *randoms, - unsigned int *seeds) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - unsigned int z = seeds[idx]; - int offset = idx; - int step = 32768; - - for (int i = 0; i < iterations; i++) - { - if (offset < size) - { - unsigned int b = (((z << 13) ^ z) >> 19); - z = (((z & UINT_MAX) << 12) ^ b); - randoms[offset] = z; - offset += step; - } - } - } - __global__ void PreInitialize(int size, - unsigned int *randoms, - int *bestSeen, - int *origin, - int *mis) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - // Set the origin to be self - origin[idx] = idx; - - // Set MIS to be -1; - mis[idx] = -1; - - // Set the bestSeen value to be random - bestSeen[idx] = randoms[idx] % 1000000; - } - } - __global__ void Initialize(int size, - unsigned int *randoms, - int *bestSeen, - int *origin, - int *mis, - int *incomplete) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - // Taustep is performed with S1=13, S2=19, S3=12, and M=UINT_MAX coded into kernel - unsigned int z = randoms[idx]; - unsigned int b = (((z << 13) ^ z) >> 19); - z = (((z & UINT_MAX) << 12) ^ b); - - // Set the origin to be self - origin[idx] = idx; + namespace MIS { + namespace Kernels { + __global__ void GenerateRandoms(int size, + int iterations, + unsigned int *randoms, + unsigned int *seeds) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + unsigned int z = seeds[idx]; + int offset = idx; + int step = 32768; + + for (int i = 0; i < iterations; i++) + { + if (offset < size) + { + unsigned int b = (((z << 13) ^ z) >> 19); + z = (((z & UINT_MAX) << 12) ^ b); + randoms[offset] = z; + offset += step; + } + } + } + __global__ void PreInitialize(int size, + unsigned int *randoms, + int *bestSeen, + int *origin, + int *mis) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + // Set the origin to be self + origin[idx] = idx; + + // Set MIS to be -1; + mis[idx] = -1; + + // Set the bestSeen value to be random + bestSeen[idx] = randoms[idx] % 1000000; + } + } + __global__ void Initialize(int size, + unsigned int *randoms, + int *bestSeen, + int *origin, + int *mis, + int *incomplete) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + // Taustep is performed with S1=13, S2=19, S3=12, and M=UINT_MAX coded into kernel + unsigned int z = randoms[idx]; + unsigned int b = (((z << 13) ^ z) >> 19); + z = (((z & UINT_MAX) << 12) ^ b); + + // Set the origin to be self + origin[idx] = idx; + + // Set the bestSeen value to be either random from 0-1000000 or 1000001 if in MIS + int status = mis[idx]; + int value = 0; + if (status == 1) + value = 1000001; + + bestSeen[idx] = (mis[idx] == -1) ? (z % 1000000) : value; + + // Write out new random value for seeding + randoms[idx] = z; + } - // Set the bestSeen value to be either random from 0-1000000 or 1000001 if in MIS - int status = mis[idx]; - int value = 0; - if (status == 1) - value = 1000001; + // Reset incomplete value + if (idx == 0) + incomplete[0] = 0; + } + __global__ void Iterate(int size, + int *originIn, + int *originOut, + int *bestSeenIn, + int *bestSeenOut, + int *adjIndexes, + int *adjacency) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + int bestSeen = bestSeenIn[idx]; + int origin = originIn[idx]; + if (bestSeen < 1000001) + { + int start = adjIndexes[idx]; + int end = adjIndexes[idx + 1]; + + // Look at all the neighbors and take best values: + for (int i = start; i < end; i++) + { + int neighbor = adjacency[i]; + int challenger = bestSeenIn[neighbor]; + int challengerOrigin = originIn[neighbor]; - bestSeen[idx] = (mis[idx] == -1) ? (z % 1000000) : value; + if (challenger > 0 && challenger == bestSeen && challengerOrigin > origin) + { + origin = challengerOrigin; + } - // Write out new random value for seeding - randoms[idx] = z; - } - // Reset incomplete value - if (idx == 0) - incomplete[0] = 0; - } - __global__ void Iterate(int size, - int *originIn, - int *originOut, - int *bestSeenIn, - int *bestSeenOut, - int *adjIndexes, - int *adjacency) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - int bestSeen = bestSeenIn[idx]; - int origin = originIn[idx]; - if (bestSeen < 1000001) - { - int start = adjIndexes[idx]; - int end = adjIndexes[idx + 1]; - - // Look at all the neighbors and take best values: - for (int i = start; i < end; i++) - { - int neighbor = adjacency[i]; - int challenger = bestSeenIn[neighbor]; - int challengerOrigin = originIn[neighbor]; - - if (challenger > 0 && challenger == bestSeen && challengerOrigin > origin) - { - origin = challengerOrigin; - } - - - if (challenger > bestSeen) - { - bestSeen = challenger; - origin = challengerOrigin; - } - } - } - - // Write out the best values found - bestSeenOut[idx] = bestSeen; - originOut[idx] = origin; - } - } - __global__ void Finalize(int size, - int *originIn, - int *originOut, - int *bestSeenIn, - int *bestSeenOut, - int *adjIndexes, - int *adjacency, - int *mis, - int *incomplete) { - int idx = blockIdx.x * blockDim.x + threadIdx.x; - if (idx < size) - { - int bestSeen = bestSeenIn[idx]; - int origin = originIn[idx]; - if (bestSeen < 1000001) - { - int start = adjIndexes[idx]; - int end = adjIndexes[idx + 1]; - - // Look at all the neighbors and take best values: - for (int i = start; i < end; i++) - { - int neighbor = adjacency[i]; - unsigned int challenger = bestSeenIn[neighbor]; - int challengerOrigin = originIn[neighbor]; - - if (challenger > 0 && challenger == bestSeen && challengerOrigin > origin) - { - origin = challengerOrigin; - } - - if (challenger > bestSeen) - { - bestSeen = challenger; - origin = challengerOrigin; - } - } - } - - // Write new MIS status - int misStatus = -1; - if (origin == idx) - misStatus = 1; - else if (bestSeen == 1000001) - misStatus = 0; - - mis[idx] = misStatus; - - - // If this node is still unassigned mark - if (misStatus == -1) - { - incomplete[0] = 1; - } - } + if (challenger > bestSeen) + { + bestSeen = challenger; + origin = challengerOrigin; + } } + } + + // Write out the best values found + bestSeenOut[idx] = bestSeen; + originOut[idx] = origin; } - IntVector_d* RandomizedMIS(int k, Graph_d &graph) { - // Setting to prefer the cache: - cudaFuncSetCacheConfig(Kernels::Initialize, cudaFuncCachePreferL1); - cudaFuncSetCacheConfig(Kernels::Iterate, cudaFuncCachePreferL1); - cudaFuncSetCacheConfig(Kernels::Finalize, cudaFuncCachePreferL1); - - cudaEvent_t start, end; - cudaEventCreate(&start); - cudaEventCreate(&end); - - IntVector_d incomplete(1); // This is a single value that will be marked with 1 by initialize kernel if there are unallocated nodes - IntVector_d *misIn = new IntVector_d(graph.Size()); // The current MIS assignments 1 = in MIS, 0 = not in MIS, -1 = undetermined - UIntVector_d randoms(graph.Size()); // Set of random values generated by each threads random generator - IntVector_d bestSeenIn(graph.Size()); // Holds the highest value seen so far propogated through neigbhors each iteration - IntVector_d bestSeenOut(graph.Size()); // Holds the highest value seen so far propogated through neigbhors each iteration - IntVector_d originIn(graph.Size()); // The index where the best seen value originated - IntVector_d originOut(graph.Size()); // The index where the best seen value originated - UIntVector_d seeds(32768); // Stores the first few seeds for the random generation process - - // Getting raw pointers: - int *incomplete_d = thrust::raw_pointer_cast(&incomplete[0]); - int *mis_d = thrust::raw_pointer_cast(misIn->data()); - unsigned *randoms_d = thrust::raw_pointer_cast(&randoms[0]); - unsigned *seeds_d = thrust::raw_pointer_cast(&seeds[0]); - int *bestSeenIn_d = thrust::raw_pointer_cast(&bestSeenIn[0]); - int *bestSeenOut_d = thrust::raw_pointer_cast(&bestSeenOut[0]); - int *originIn_d = thrust::raw_pointer_cast(&originIn[0]); - int *originOut_d = thrust::raw_pointer_cast(&originOut[0]); - int *adjIndexes_d = thrust::raw_pointer_cast(graph.indices->data()); - int *adjacency_d = thrust::raw_pointer_cast(graph.adjacency->data()); - - // Setting up for kernel launches - int blockSize = 512; - int nBlocks = graph.Size() / blockSize + (graph.Size() % blockSize == 0 ? 0 : 1); - - // Seeding the randoms array: - srand(time(NULL)); - unsigned *seeds_h = new unsigned[32768]; - for (int i = 0; i < 32768; i++) - seeds_h[i] = (unsigned)rand(); - - thrust::copy(seeds_h, seeds_h + 32768, seeds.begin()); - int iterations = (graph.Size() + 32767) / 32768; - - Kernels::GenerateRandoms <<<128, 256>>> (graph.Size(), iterations, randoms_d, seeds_d); - - // Running the initialize kernel: - Kernels::PreInitialize <<< nBlocks, blockSize >>> (graph.Size(), randoms_d, bestSeenIn_d, originIn_d, mis_d); - - // Running the iteration kernel k times swapping in and out for each iteration - for (int i = 0; i < k; i++) + } + __global__ void Finalize(int size, + int *originIn, + int *originOut, + int *bestSeenIn, + int *bestSeenOut, + int *adjIndexes, + int *adjacency, + int *mis, + int *incomplete) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < size) + { + int bestSeen = bestSeenIn[idx]; + int origin = originIn[idx]; + if (bestSeen < 1000001) + { + int start = adjIndexes[idx]; + int end = adjIndexes[idx + 1]; + + // Look at all the neighbors and take best values: + for (int i = start; i < end; i++) { - if (i < k - 1) - Kernels::Iterate <<< nBlocks, blockSize >>> (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d); - else - Kernels::Finalize <<< nBlocks, blockSize >>> (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d, mis_d, incomplete_d); - - - // Swap the pointers for the next iteration: - int *temp = originIn_d; - originIn_d = originOut_d; - originOut_d = temp; - - int *temp2 = bestSeenIn_d; - bestSeenIn_d = bestSeenOut_d; - bestSeenOut_d = temp2; + int neighbor = adjacency[i]; + unsigned int challenger = bestSeenIn[neighbor]; + int challengerOrigin = originIn[neighbor]; + + if (challenger > 0 && challenger == bestSeen && challengerOrigin > origin) + { + origin = challengerOrigin; + } + + if (challenger > bestSeen) + { + bestSeen = challenger; + origin = challengerOrigin; + } } + } - // If not complete get new randoms and repeat - cudaThreadSynchronize(); - int unallocated = incomplete[0]; + // Write new MIS status + int misStatus = -1; + if (origin == idx) + misStatus = 1; + else if (bestSeen == 1000001) + misStatus = 0; - while (unallocated == 1) - { - // Initialize kernel - Kernels::Initialize <<< nBlocks, blockSize >>> (graph.Size(), randoms_d, bestSeenIn_d, originIn_d, mis_d, incomplete_d); + mis[idx] = misStatus; - // Running the iteration kernel k times swapping in and out for each iteration - for (int i = 0; i < k; i++) - { - if (i < k - 1) - Kernels::Iterate <<< nBlocks, blockSize >>> (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d); - else - Kernels::Finalize <<< nBlocks, blockSize >>> (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d, mis_d, incomplete_d); - - // Swap the pointers for the next iteration: - int *temp = originIn_d; - originIn_d = originOut_d; - originOut_d = temp; - - int *temp2 = bestSeenIn_d; - bestSeenIn_d = bestSeenOut_d; - bestSeenOut_d = temp2; - } - - // Checking if done: - cudaThreadSynchronize(); - unallocated = incomplete[0]; - } - // Deallocating temporary arrays: - incomplete.resize(0); - randoms.resize(0); - bestSeenIn.resize(0); - bestSeenOut.resize(0); - originIn.resize(0); - originOut.resize(0); - - // Returning the mis - //return misIn; - return misIn; + // If this node is still unassigned mark + if (misStatus == -1) + { + incomplete[0] = 1; + } + } + } + } + AggMIS::Types::IntVector_d* RandomizedMIS(int k, AggMIS::Types::Graph_d &graph) { + // Setting to prefer the cache: + cudaFuncSetCacheConfig(Kernels::Initialize, cudaFuncCachePreferL1); + cudaFuncSetCacheConfig(Kernels::Iterate, cudaFuncCachePreferL1); + cudaFuncSetCacheConfig(Kernels::Finalize, cudaFuncCachePreferL1); + + cudaEvent_t start, end; + cudaEventCreate(&start); + cudaEventCreate(&end); + + AggMIS::Types::IntVector_d incomplete(1); // This is a single value that will be marked with 1 by initialize kernel if there are unallocated nodes + AggMIS::Types::IntVector_d *misIn = new AggMIS::Types::IntVector_d(graph.Size()); // The current MIS assignments 1 = in MIS, 0 = not in MIS, -1 = undetermined + AggMIS::Types::UIntVector_d randoms(graph.Size()); // Set of random values generated by each threads random generator + AggMIS::Types::IntVector_d bestSeenIn(graph.Size()); // Holds the highest value seen so far propogated through neigbhors each iteration + AggMIS::Types::IntVector_d bestSeenOut(graph.Size()); // Holds the highest value seen so far propogated through neigbhors each iteration + AggMIS::Types::IntVector_d originIn(graph.Size()); // The index where the best seen value originated + AggMIS::Types::IntVector_d originOut(graph.Size()); // The index where the best seen value originated + AggMIS::Types::UIntVector_d seeds(32768); // Stores the first few seeds for the random generation process + + // Getting raw pointers: + int *incomplete_d = thrust::raw_pointer_cast(&incomplete[0]); + int *mis_d = thrust::raw_pointer_cast(misIn->data()); + unsigned *randoms_d = thrust::raw_pointer_cast(&randoms[0]); + unsigned *seeds_d = thrust::raw_pointer_cast(&seeds[0]); + int *bestSeenIn_d = thrust::raw_pointer_cast(&bestSeenIn[0]); + int *bestSeenOut_d = thrust::raw_pointer_cast(&bestSeenOut[0]); + int *originIn_d = thrust::raw_pointer_cast(&originIn[0]); + int *originOut_d = thrust::raw_pointer_cast(&originOut[0]); + int *adjIndexes_d = thrust::raw_pointer_cast(graph.indices->data()); + int *adjacency_d = thrust::raw_pointer_cast(graph.adjacency->data()); + + // Setting up for kernel launches + int blockSize = 512; + int nBlocks = graph.Size() / blockSize + (graph.Size() % blockSize == 0 ? 0 : 1); + + // Seeding the randoms array: + srand(time(NULL)); + unsigned *seeds_h = new unsigned[32768]; + for (int i = 0; i < 32768; i++) + seeds_h[i] = (unsigned)rand(); + + thrust::copy(seeds_h, seeds_h + 32768, seeds.begin()); + int iterations = (graph.Size() + 32767) / 32768; + + Kernels::GenerateRandoms << <128, 256 >> > (graph.Size(), iterations, randoms_d, seeds_d); + + // Running the initialize kernel: + Kernels::PreInitialize << < nBlocks, blockSize >> > (graph.Size(), randoms_d, bestSeenIn_d, originIn_d, mis_d); + + // Running the iteration kernel k times swapping in and out for each iteration + for (int i = 0; i < k; i++) + { + if (i < k - 1) + Kernels::Iterate << < nBlocks, blockSize >> > (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d); + else + Kernels::Finalize << < nBlocks, blockSize >> > (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d, mis_d, incomplete_d); + + + // Swap the pointers for the next iteration: + int *temp = originIn_d; + originIn_d = originOut_d; + originOut_d = temp; + + int *temp2 = bestSeenIn_d; + bestSeenIn_d = bestSeenOut_d; + bestSeenOut_d = temp2; + } + + // If not complete get new randoms and repeat + cudaThreadSynchronize(); + int unallocated = incomplete[0]; + + while (unallocated == 1) + { + // Initialize kernel + Kernels::Initialize << < nBlocks, blockSize >> > (graph.Size(), randoms_d, bestSeenIn_d, originIn_d, mis_d, incomplete_d); + + // Running the iteration kernel k times swapping in and out for each iteration + for (int i = 0; i < k; i++) + { + if (i < k - 1) + Kernels::Iterate << < nBlocks, blockSize >> > (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d); + else + Kernels::Finalize << < nBlocks, blockSize >> > (graph.Size(), originIn_d, originOut_d, bestSeenIn_d, bestSeenOut_d, adjIndexes_d, adjacency_d, mis_d, incomplete_d); + + // Swap the pointers for the next iteration: + int *temp = originIn_d; + originIn_d = originOut_d; + originOut_d = temp; + + int *temp2 = bestSeenIn_d; + bestSeenIn_d = bestSeenOut_d; + bestSeenOut_d = temp2; } - bool IsValidKMIS(IntVector_d& misIn, Graph_d& graphIn, int k, bool verbose) { - // Copy to host data - Graph_h graph(graphIn); - IntVector_h mis(misIn); - - if (verbose) - printf("Attempting to verify %d-mis properties\n", k); - - // Checking if the mis vector is the right size - int misSize = mis.size(); - int gSize = graph.indices->size() - 1; - if (misSize != gSize || misSize != graph.Size()) - { - if (verbose) - { - printf("The given vector is not the correct size to describe and MIS of the input graph! \n"); - printf("\tMIS size: %d Graph Size: %d\n", misSize, gSize); - } - return false; - } - // Checking that at least one node is marked as in the MIS - int count = 0; - for (int i = 0; i < mis.size(); i++) - if (mis[i] == 1) - count++; - if (count == 0) + // Checking if done: + cudaThreadSynchronize(); + unallocated = incomplete[0]; + } + + // Deallocating temporary arrays: + incomplete.resize(0); + randoms.resize(0); + bestSeenIn.resize(0); + bestSeenOut.resize(0); + originIn.resize(0); + originOut.resize(0); + + // Returning the mis + //return misIn; + return misIn; + } + bool IsValidKMIS(AggMIS::Types::IntVector_d& misIn, AggMIS::Types::Graph_d& graphIn, int k, bool verbose) { + // Copy to host data + AggMIS::Types::Graph_h graph(graphIn); + AggMIS::Types::IntVector_h mis(misIn); + + if (verbose) + printf("Attempting to verify %d-mis properties\n", k); + + // Checking if the mis vector is the right size + int misSize = mis.size(); + int gSize = graph.indices->size() - 1; + if (misSize != gSize || misSize != graph.Size()) + { + if (verbose) + { + printf("The given vector is not the correct size to describe and MIS of the input graph! \n"); + printf("\tMIS size: %d Graph Size: %d\n", misSize, gSize); + } + return false; + } + + // Checking that at least one node is marked as in the MIS + int count = 0; + for (int i = 0; i < mis.size(); i++) + if (mis[i] == 1) + count++; + if (count == 0) + { + if (verbose) + { + printf("No nodes are designated as in the MIS!\n"); + // debugHelpers::printVector(mis, std::string("The MIS")); + } + return false; + } + + // Checking that every node not in the MIS has a path to a root node + // of less than k and that every node in the MIS does not + for (int i = 0; i < mis.size(); i++) + { + std::vector< std::vector > rings(k + 1); + int distance = INT_MAX; + rings[0].push_back(i); + + // Filling in the rings with breadth first search + for (int j = 1; j < rings.size(); j++) + { + for (int root = 0; root < rings[j - 1].size(); root++) + { + int rootPoint = rings[j - 1][root]; + int start = graph.indices->data()[rootPoint]; + int end = graph.indices->data()[rootPoint + 1]; + for (int nIt = start; nIt < end; nIt++) { - if (verbose) + int neighbor = graph.adjacency->data()[nIt]; + bool visited = false; + for (int vLevel = 0; vLevel < j + 1; vLevel++) + { + for (int vIt = 0; vIt < rings[vLevel].size(); vIt++) { - printf("No nodes are designated as in the MIS!\n"); -// debugHelpers::printVector(mis, std::string("The MIS")); + if (rings[vLevel][vIt] == neighbor) + visited = true; } - return false; + } + + if (!visited) + { + rings[j].push_back(neighbor); + if (mis[neighbor] == 1 && distance > j) + distance = j; + if (mis[i] == 1 && mis[neighbor] == 1) + printf("Found a %d-path from root node %d to root node %d\n", distance, neighbor, i); + } } + } + } - // Checking that every node not in the MIS has a path to a root node - // of less than k and that every node in the MIS does not - for (int i = 0; i < mis.size(); i++) - { - vector< vector > rings(k + 1); - int distance = INT_MAX; - rings[0].push_back(i); + // If this node is not in the MIS distance should be less than k + if (mis[i] == 1 && distance <= k) + { + if (verbose) + { + printf("Node %d is in the MIS but has a %d-path to another root node!\n", i, distance); + // debugHelpers::printVector(mis, std::string("The MIS:")); + // debugHelpers::printGraph(graph); + } + + return false; + } + if (mis[i] == 0 && distance > k) + { + if (verbose) + printf("Node %d is not in the MIS but has no conflicts with MIS nodes!\n", i); + // debugHelpers::printVector(mis, std::string("The MIS:")); + // debugHelpers::printGraph(graph); + return false; + } - // Filling in the rings with breadth first search - for (int j = 1; j < rings.size(); j++) - { - for (int root = 0; root < rings[j - 1].size(); root++) - { - int rootPoint = rings[j - 1][root]; - int start = graph.indices->data()[rootPoint]; - int end = graph.indices->data()[rootPoint + 1]; - for (int nIt = start; nIt < end; nIt++) - { - int neighbor = graph.adjacency->data()[nIt]; - bool visited = false; - for (int vLevel = 0; vLevel < j + 1; vLevel++) - { - for (int vIt = 0; vIt < rings[vLevel].size(); vIt++) - { - if (rings[vLevel][vIt] == neighbor) - visited = true; - } - } - - if (!visited) - { - rings[j].push_back(neighbor); - if (mis[neighbor] == 1 && distance > j) - distance = j; - if (mis[i] == 1 && mis[neighbor] == 1) - printf("Found a %d-path from root node %d to root node %d\n", distance, neighbor, i); - } - } - } - } + } - // If this node is not in the MIS distance should be less than k - if (mis[i] == 1 && distance <= k) - { - if (verbose) - { - printf("Node %d is in the MIS but has a %d-path to another root node!\n", i, distance); -// debugHelpers::printVector(mis, std::string("The MIS:")); -// debugHelpers::printGraph(graph); - } - - return false; - } - if (mis[i] == 0 && distance > k) - { - if (verbose) - printf("Node %d is not in the MIS but has no conflicts with MIS nodes!\n", i); -// debugHelpers::printVector(mis, std::string("The MIS:")); -// debugHelpers::printGraph(graph); - return false; - } + // Clean up temp memory + mis.resize(0); - } - - // Clean up temp memory - mis.resize(0); - - // If we got this far the MIS must be valid (both maximal and independent) - return true; - } + // If we got this far the MIS must be valid (both maximal and independent) + return true; } + } } \ No newline at end of file diff --git a/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner.cu b/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner.cu index 788de7e..05a64ac 100644 --- a/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner.cu +++ b/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner.cu @@ -1542,8 +1542,8 @@ namespace AggMIS { } // Public methods for merge split conditioner - MergeSplitConditionerGPU::MergeSplitConditionerGPU(Graph_d& graph, - IntVector_d& aggregation) { + MergeSplitConditionerGPU::MergeSplitConditionerGPU(AggMIS::Types::Graph_d& graph, + AggMIS::Types::IntVector_d& aggregation) { this->graph = &graph; this->aggregation.assign(aggregation.begin(), aggregation.end()); inducedGraph = GraphHelpers::GetInducedGraph(graph, aggregation); @@ -1567,14 +1567,14 @@ namespace AggMIS { void MergeSplitConditionerGPU::SetVerbose(bool v) { verbose = v; } - void MergeSplitConditionerGPU::SetNodeWeights(IntVector_d &input) { + void MergeSplitConditionerGPU::SetNodeWeights(AggMIS::Types::IntVector_d &input) { nodeWeights.swap(input); GraphHelpers::getPartSizes(aggregation, weightedSizes, nodeWeights); } - IntVector_d* MergeSplitConditionerGPU::GetAggregation() { + AggMIS::Types::IntVector_d* MergeSplitConditionerGPU::GetAggregation() { return &aggregation; } - IntVector_d* MergeSplitConditionerGPU::GetNodeWeights() { + AggMIS::Types::IntVector_d* MergeSplitConditionerGPU::GetNodeWeights() { return &nodeWeights; } void MergeSplitConditionerGPU::CycleMerges(bool force) { @@ -1603,7 +1603,7 @@ namespace AggMIS { bool somethingDone = MakeMergeSplits(desiredSize); // Choosing which sizes to use: - IntVector_d *sizes = &partSizes; + AggMIS::Types::IntVector_d *sizes = &partSizes; if (nodeWeights.size() > 0) sizes = &weightedSizes; @@ -1628,7 +1628,7 @@ namespace AggMIS { float minImprove, int maxCycles) { if (verbose) - PrintProgress(&cout, "Starting conditioning.", true, true, true, true); + PrintProgress(&std::cout, "Starting conditioning.", true, true, true, true); // Start by making any optimal merges and splits if (verbose) @@ -1672,9 +1672,9 @@ namespace AggMIS { if (verbose) { - stringstream ss; + std::stringstream ss; ss << "After condition cycle: " << counter; - PrintProgress(&cout, ss.str(), true, true, true, true); + PrintProgress(&std::cout, ss.str(), true, true, true, true); } } @@ -1701,10 +1701,10 @@ namespace AggMIS { // else { // printf("Aggregation does not validate after conditioning!\n"); // int t; -// cin >> t; +// std::cin >> t; // } if (verbose) - PrintProgress(&cout, "After conditioning completed.", true, true, true, true); + PrintProgress(&std::cout, "After conditioning completed.", true, true, true, true); // Checking if the size constraints are met for the return if (respectUpper) @@ -1713,8 +1713,8 @@ namespace AggMIS { return (undersized == 0 && (float)outsizedParts / partSizes.size() < tolerance); } - void MergeSplitConditionerGPU::PrintProgress(ostream* output, - string note, + void MergeSplitConditionerGPU::PrintProgress(std::ostream* output, + std::string note, bool graphStat, bool progressStat, bool sizeStat, @@ -1736,13 +1736,13 @@ namespace AggMIS { *output << "-----------------------------------------------------\n\n"; } - void MergeSplitConditionerGPU::PrintSizeStats(ostream* output, + void MergeSplitConditionerGPU::PrintSizeStats(std::ostream* output, bool makeHeader) { if (makeHeader) *output << "\n--------------------- Size Check --------------------\n"; // Choosing which sizes to use: - IntVector_d *sizes = &partSizes; + AggMIS::Types::IntVector_d *sizes = &partSizes; if (nodeWeights.size() > 0) sizes = &weightedSizes; @@ -1784,7 +1784,7 @@ namespace AggMIS { if (makeHeader) *output << "-----------------------------------------------------\n\n"; } - void MergeSplitConditionerGPU::PrintMemoryStats(ostream* output, + void MergeSplitConditionerGPU::PrintMemoryStats(std::ostream* output, bool makeHeader) { if (makeHeader) *output << "\n-------------------- Memory Check -------------------\n"; @@ -1802,7 +1802,7 @@ namespace AggMIS { if (makeHeader) *output << "-----------------------------------------------------\n\n"; } - void MergeSplitConditionerGPU::PrintProgressStats(ostream* output, + void MergeSplitConditionerGPU::PrintProgressStats(std::ostream* output, bool makeHeader) { if (makeHeader) *output << "\n------------------- Progress Check ------------------\n"; @@ -1815,7 +1815,7 @@ namespace AggMIS { if (makeHeader) *output << "-----------------------------------------------------\n\n"; } - void MergeSplitConditionerGPU::PrintGraphStats(ostream* output, + void MergeSplitConditionerGPU::PrintGraphStats(std::ostream* output, bool makeHeader) { if (makeHeader) *output << "\n----------------- Graph Information -----------------\n"; @@ -1830,7 +1830,7 @@ namespace AggMIS { 0, thrust::maximum()); - IntVector_d *valences = GraphHelpers::GetValences(*graph); + AggMIS::Types::IntVector_d *valences = GraphHelpers::GetValences(*graph); int minValence = thrust::reduce(valences->begin(), valences->end(), INT_MAX, @@ -1864,9 +1864,9 @@ namespace AggMIS { if (makeHeader) *output << "-----------------------------------------------------\n\n"; } - void MergeSplitConditionerGPU::InteractiveConsole(string message) { + void MergeSplitConditionerGPU::InteractiveConsole(std::string message) { // Start off by printing overall status info and message - PrintProgress(&cout, message, true, true, true, false); + PrintProgress(&std::cout, message, true, true, true, false); // Setting needed variables to defaults float minImprove = .1; @@ -1879,13 +1879,13 @@ namespace AggMIS { // Starting the main prompt: char operation; printf("\nIC:"); - cin >> operation; + std::cin >> operation; while (operation != 'd') { if (operation == 'o' || operation == 'f') { bool force = operation == 'f'; - cin >> operation; + std::cin >> operation; if (operation == 'm') { if (cycling) @@ -1894,8 +1894,8 @@ namespace AggMIS { MarkMerges(force); MakeMerges(false); } - string msg = force ? "After forced merges" : "After optimal merges"; - PrintProgress(&cout, msg, false, true, true, false); + std::string msg = force ? "After forced merges" : "After optimal merges"; + PrintProgress(&std::cout, msg, false, true, true, false); } if (operation == 's') { @@ -1905,8 +1905,8 @@ namespace AggMIS { MarkSplits(force); MakeSplits(); } - string msg = force ? "After forced splits" : "After optimal splits"; - PrintProgress(&cout, msg, false, true, true, false); + std::string msg = force ? "After forced splits" : "After optimal splits"; + PrintProgress(&std::cout, msg, false, true, true, false); } if (operation == 'g') { @@ -1914,51 +1914,51 @@ namespace AggMIS { CycleMergeSplits(minImprove, desiredSize); else MakeMergeSplits(desiredSize); - PrintProgress(&cout, "After merge-splits", false, true, true, false); + PrintProgress(&std::cout, "After merge-splits", false, true, true, false); } } else if (operation == 's') { // Printing the current values of the variables - string cyclingFlag = cycling ? "True" : "False"; - string respectUpperFlag = respectUpper ? "True" : "False"; - cout << "\nCurrent values of variables:"; - cout << "\n\tminSize: " << minSize; - cout << " maxSize: " << maxSize; - cout << " desiredSize: " << desiredSize; - cout << " maxCycles: " << maxCycles; - cout << "\n\tminImprove: " << minImprove; - cout << " tolerance: " << tolerance; - cout << " cycling: " << cyclingFlag; - cout << " respectUpper: " << respectUpperFlag; - cout << "\n\nEnter new values in same order\nIC:"; + std::string cyclingFlag = cycling ? "True" : "False"; + std::string respectUpperFlag = respectUpper ? "True" : "False"; + std::cout << "\nCurrent values of variables:"; + std::cout << "\n\tminSize: " << minSize; + std::cout << " maxSize: " << maxSize; + std::cout << " desiredSize: " << desiredSize; + std::cout << " maxCycles: " << maxCycles; + std::cout << "\n\tminImprove: " << minImprove; + std::cout << " tolerance: " << tolerance; + std::cout << " cycling: " << cyclingFlag; + std::cout << " respectUpper: " << respectUpperFlag; + std::cout << "\n\nEnter new values in same order\nIC:"; // Grabbing the new values - cin >> minSize; - cin >> maxSize; - cin >> desiredSize; - cin >> maxCycles; - cin >> minImprove; - cin >> tolerance; - cin >> cycling; - cin >> respectUpper; + std::cin >> minSize; + std::cin >> maxSize; + std::cin >> desiredSize; + std::cin >> maxCycles; + std::cin >> minImprove; + std::cin >> tolerance; + std::cin >> cycling; + std::cin >> respectUpper; // Confirming the entry cyclingFlag = cycling ? "True" : "False"; respectUpperFlag = respectUpper ? "True" : "False"; - cout << "\nNew values of variables:"; - cout << "\n\tminSize: " << minSize; - cout << " maxSize: " << maxSize; - cout << " desiredSize: " << desiredSize; - cout << " maxCycles: " << maxCycles; - cout << "\n\tminImprove: " << minImprove; - cout << " tolerance: " << tolerance; - cout << " cycling: " << cyclingFlag; - cout << " respectUpper: " << respectUpperFlag << "\n\n"; + std::cout << "\nNew values of variables:"; + std::cout << "\n\tminSize: " << minSize; + std::cout << " maxSize: " << maxSize; + std::cout << " desiredSize: " << desiredSize; + std::cout << " maxCycles: " << maxCycles; + std::cout << "\n\tminImprove: " << minImprove; + std::cout << " tolerance: " << tolerance; + std::cout << " cycling: " << cyclingFlag; + std::cout << " respectUpper: " << respectUpperFlag << "\n\n"; } else if (operation == 'c') { Condition(desiredSize, respectUpper, tolerance, minImprove, maxCycles); - PrintProgress(&cout, "After conditioning", false, true, true, false); + PrintProgress(&std::cout, "After conditioning", false, true, true, false); } else if (operation == 'v') { bool valid = Aggregation::IsValidAggregation(*graph, aggregation, false); @@ -1969,14 +1969,14 @@ namespace AggMIS { } else if (operation == 'l') { bool v; - cin >> v; + std::cin >> v; SetVerbose(v); printf("Set verbose to %s\n", v ? "True" : "False"); } // Printing prompt for another go printf("IC:"); - cin >> operation; + std::cin >> operation; } } @@ -1989,15 +1989,15 @@ namespace AggMIS { mergesToMake.assign(negOne, negOne + inducedGraph->Size()); // Choosing which sizes to use: - IntVector_d *sizes = &partSizes; + AggMIS::Types::IntVector_d *sizes = &partSizes; if (nodeWeights.size() > 0) sizes = &weightedSizes; // Declaring temp arrays int size = inducedGraph->Size(); - IntVector_d desiredMerges(size, -1); - IntVector_d merging(size, 0); - IntVector_d incomplete(1,1); + AggMIS::Types::IntVector_d desiredMerges(size, -1); + AggMIS::Types::IntVector_d merging(size, 0); + AggMIS::Types::IntVector_d incomplete(1,1); // Figuring out block sizes for kernel call: int blockSize = 256; @@ -2005,7 +2005,7 @@ namespace AggMIS { while (incomplete[0] == 1) { -// IntVector_h before(desiredMerges); +// AggMIS::Types::IntVector_h before(desiredMerges); incomplete[0] = 0; if (verbose) printf("Calling FindDesirableMerges Kernel <<<%d, %d>>>\n", @@ -2017,18 +2017,18 @@ namespace AggMIS { force, inducedGraph->indStart(), inducedGraph->adjStart(), - StartOf(sizes), - StartOf(desiredMerges), - StartOf(merging)); + AggMIS::Types::StartOf(sizes), + AggMIS::Types::StartOf(desiredMerges), + AggMIS::Types::StartOf(merging)); if (verbose) printf("Calling MarkMerges Kernel <<<%d, %d>>>\n", blockSize, nBlocks); Kernels::MarkMerges <<>> (size, - StartOf(desiredMerges), - StartOf(merging), - StartOf(mergesToMake), - StartOf(incomplete)); + AggMIS::Types::StartOf(desiredMerges), + AggMIS::Types::StartOf(merging), + AggMIS::Types::StartOf(mergesToMake), + AggMIS::Types::StartOf(incomplete)); } int marked = -1; @@ -2042,8 +2042,8 @@ namespace AggMIS { catch (thrust::system::system_error &e) { printf("Caught exception at end of MarkMerges!\n"); - cerr << e.what() << endl; - cerr << "Error code: " << e.code() << endl; + std::cerr << e.what() << std::endl; + std::cerr << "Error code: " << e.code() << std::endl; InputHelpers::GetNonEmptyLineCIN(); } @@ -2061,7 +2061,7 @@ namespace AggMIS { splitsToMake.assign(zero, zero + size); // Choosing which sizes to use: - IntVector_d *sizes = &partSizes; + AggMIS::Types::IntVector_d *sizes = &partSizes; if (nodeWeights.size() > 0) sizes = &weightedSizes; @@ -2086,8 +2086,8 @@ namespace AggMIS { force, minSize, maxSize, - StartOf(sizes), - StartOf(splitsToMake)); + AggMIS::Types::StartOf(sizes), + AggMIS::Types::StartOf(splitsToMake)); int marked = thrust::count(splitsToMake.begin(), splitsToMake.end(), 1); @@ -2103,7 +2103,7 @@ namespace AggMIS { int size = inducedGraph->Size(); // Choosing which sizes to use: - IntVector_d *sizes = &partSizes; + AggMIS::Types::IntVector_d *sizes = &partSizes; if (nodeWeights.size() > 0) sizes = &weightedSizes; @@ -2112,9 +2112,9 @@ namespace AggMIS { mergesToMake.assign(negOne, negOne + size); // Declaring temp arrays - IntVector_d desiredMerges(size, -1); - IntVector_d merging(size, 0); - IntVector_d incomplete(1,1); + AggMIS::Types::IntVector_d desiredMerges(size, -1); + AggMIS::Types::IntVector_d merging(size, 0); + AggMIS::Types::IntVector_d incomplete(1,1); // Figuring out block sizes for kernel call: int blockSize = 256; @@ -2133,18 +2133,18 @@ namespace AggMIS { desiredSize, inducedGraph->indStart(), inducedGraph->adjStart(), - StartOf(sizes), - StartOf(desiredMerges), - StartOf(merging)); + AggMIS::Types::StartOf(sizes), + AggMIS::Types::StartOf(desiredMerges), + AggMIS::Types::StartOf(merging)); if (verbose) printf("Calling MarkMerges Kernel <<<%d, %d>>>\n", blockSize, nBlocks); Kernels::MarkMerges <<>> (size, - StartOf(desiredMerges), - StartOf(merging), - StartOf(mergesToMake), - StartOf(incomplete)); + AggMIS::Types::StartOf(desiredMerges), + AggMIS::Types::StartOf(merging), + AggMIS::Types::StartOf(mergesToMake), + AggMIS::Types::StartOf(incomplete)); } // Checking for marked merges @@ -2164,7 +2164,7 @@ namespace AggMIS { thrust::counting_iterator zero(0); // Get list of all small aggregates to split 0-64 - IntVector_d smallSplits(splitsToMake.size()); + AggMIS::Types::IntVector_d smallSplits(splitsToMake.size()); int smallSplitsCount = thrust::copy_if(zero, zero + splitsToMake.size(), thrust::make_zip_iterator( @@ -2179,7 +2179,7 @@ namespace AggMIS { printf("Found %d small splits to do.\n", smallSplitsCount); // Get list of all big aggregates to split 65-256 - IntVector_d bigSplits(splitsToMake.size()); + AggMIS::Types::IntVector_d bigSplits(splitsToMake.size()); int bigSplitsCount = thrust::copy_if(zero, zero + splitsToMake.size(), thrust::make_zip_iterator( @@ -2200,9 +2200,9 @@ namespace AggMIS { // printf("There should be %d total splits.\n", total); // // int d; -// std::cin >> d; +// std::std::cin >> d; - Graph_d* aggMap = Aggregation::GetAggregateMap(aggregation); + AggMIS::Types::Graph_d* aggMap = Aggregation::GetAggregateMap(aggregation); // Making the splits is different for weighted/non-weighted if (nodeWeights.size() == 0) { @@ -2219,8 +2219,8 @@ namespace AggMIS { Kernels::MakeSplits <<< toDo, 64 >>> (aggMap->Size() + offset, - StartOf(smallSplits) + offset, - StartOf(aggregation), + AggMIS::Types::StartOf(smallSplits) + offset, + AggMIS::Types::StartOf(aggregation), aggMap->indStart(), aggMap->adjStart(), graph->indStart(), @@ -2239,15 +2239,15 @@ namespace AggMIS { printf("Calling MakeSplits_Large Kernel <<<%d, %d>>>\n", toDo, 256); - Display::Print(bigSplits, "Big splits"); - IntVector_h sizes(bigSplits.size()); + AggMIS::Types::Display::Print(bigSplits, "Big splits"); + AggMIS::Types::IntVector_h sizes(bigSplits.size()); for (int i = 0; i < bigSplits.size(); i++) sizes[i] = partSizes[bigSplits[i]]; - Display::Print(sizes, "Sizes of big splits"); + AggMIS::Types::Display::Print(sizes, "Sizes of big splits"); Kernels::MakeSplits_Large <<< toDo, 256 >>> (aggMap->Size() + smallSplitsCount + offset, - StartOf(bigSplits) + offset, - StartOf(aggregation), + AggMIS::Types::StartOf(bigSplits) + offset, + AggMIS::Types::StartOf(aggregation), aggMap->indStart(), aggMap->adjStart(), graph->indStart(), @@ -2271,13 +2271,13 @@ namespace AggMIS { Kernels::MakeSplitsWeighted <<< toDo, 64 >>> (aggMap->Size() + offset, - StartOf(smallSplits) + offset, - StartOf(aggregation), + AggMIS::Types::StartOf(smallSplits) + offset, + AggMIS::Types::StartOf(aggregation), aggMap->indStart(), aggMap->adjStart(), graph->indStart(), graph->adjStart(), - StartOf(nodeWeights)); + AggMIS::Types::StartOf(nodeWeights)); offset += toDo; } @@ -2294,13 +2294,13 @@ namespace AggMIS { Kernels::MakeSplitsWeighted_Large <<< toDo, 256 >>> (aggMap->Size() + smallSplitsCount + offset, - StartOf(bigSplits) + offset, - StartOf(aggregation), + AggMIS::Types::StartOf(bigSplits) + offset, + AggMIS::Types::StartOf(aggregation), aggMap->indStart(), aggMap->adjStart(), graph->indStart(), graph->adjStart(), - StartOf(nodeWeights)); + AggMIS::Types::StartOf(nodeWeights)); offset += toDo; } cudaDeviceSynchronize(); @@ -2315,15 +2315,15 @@ namespace AggMIS { if (nodeWeights.size() > 0) GraphHelpers::getPartSizes(aggregation, weightedSizes, nodeWeights); -// IntVector_d afterSizes(bigSplits.size()); +// AggMIS::Types::IntVector_d afterSizes(bigSplits.size()); // for (int i = 0; i < bigSplits.size(); i++) // afterSizes[i] = partSizes[bigSplits[i]]; -// Display::Print(afterSizes, "Sizes of big splits after splitting"); +// AggMIS::Types::Display::Print(afterSizes, "Sizes of big splits after splitting"); // -// IntVector_d afterSizes2(bigSplits.size()); +// AggMIS::Types::IntVector_d afterSizes2(bigSplits.size()); // for (int i = 0; i < bigSplits.size(); i++) // afterSizes2[i] = partSizes[i + aggMap->Size() + smallSplitsCount]; -// Display::Print(afterSizes, "Sizes of big splits after splitting 2"); +// AggMIS::Types::Display::Print(afterSizes, "Sizes of big splits after splitting 2"); // Clean up smallSplits.clear(); @@ -2370,10 +2370,10 @@ namespace AggMIS { nBlocks, blockSize); Kernels::MakeMerges_MarkSplits <<>> (size, - StartOf(mergesToMake), - StartOf(mergeOffsets), - StartOf(aggregation), - StartOf(splitsToMake)); + AggMIS::Types::StartOf(mergesToMake), + AggMIS::Types::StartOf(mergeOffsets), + AggMIS::Types::StartOf(aggregation), + AggMIS::Types::StartOf(splitsToMake)); CheckCudaError(cudaDeviceSynchronize(), __FILE__, __LINE__); } else { @@ -2382,9 +2382,9 @@ namespace AggMIS { nBlocks, blockSize); Kernels::MakeMerges <<>> (size, - StartOf(mergesToMake), - StartOf(mergeOffsets), - StartOf(aggregation)); + AggMIS::Types::StartOf(mergesToMake), + AggMIS::Types::StartOf(mergeOffsets), + AggMIS::Types::StartOf(aggregation)); if (CheckCudaError(cudaDeviceSynchronize(), __FILE__, __LINE__)) { } diff --git a/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner_CPU.cu b/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner_CPU.cu index 9ff9c05..3f702be 100644 --- a/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner_CPU.cu +++ b/src/core/aggmis/cuda/AggMIS_MergeSplitConditioner_CPU.cu @@ -1,1145 +1,1136 @@ -/* +/* * File: AggMIS_MergeSplitConditioner_CPU.cu * Author: T. James Lewis * * Created on July 4, 2013, 1:14 PM */ - #include +#include #include "AggMIS_MergeSplitConditioner_CPU.h" namespace AggMIS { - namespace MergeSplitCPU { - MergeSplitConditionerCPU::MergeSplitConditionerCPU(Graph_h &graph, - IntVector_h &aggregation) { - this->graph = &graph; - this->aggregation.assign(aggregation.begin(), aggregation.end()); - inducedGraph = GraphHelpers::GetInducedGraph(graph, aggregation); - - // Getting the sizes of each aggregate: - IntVector_h* ps = Aggregation::GetPartSizes(aggregation); - partSizes.swap(*ps); - delete ps; - - // Filling in - FillAggAdjacency(); - FillAggMap(); - - verbose = false; - minSize = 20; - maxSize = 30; - outsizedParts = 0; - merges = 0; - mergeSplits = 0; - splits = 0; - } - void MergeSplitConditionerCPU::SetSizeBounds(int min, - int max) { - minSize = min; - maxSize = max; - } - void MergeSplitConditionerCPU::SetVerbose(bool v) { - verbose = v; - } - void MergeSplitConditionerCPU::SetNodeWeights(IntVector_h &input) { - nodeWeights.swap(input); - IntVector_h *ws = Aggregation::GetPartSizes(aggregation, nodeWeights); - weightedSizes.swap(*ws); - ws->clear(); - delete ws; - } - IntVector_h* MergeSplitConditionerCPU::GetAggregation() { - return &aggregation; - } - IntVector_h* MergeSplitConditionerCPU::GetNodeWeights() { - return &nodeWeights; + namespace MergeSplitCPU { + MergeSplitConditionerCPU::MergeSplitConditionerCPU(AggMIS::Types::Graph_h &graph, + AggMIS::Types::IntVector_h &aggregation) { + this->graph = &graph; + this->aggregation.assign(aggregation.begin(), aggregation.end()); + inducedGraph = GraphHelpers::GetInducedGraph(graph, aggregation); + + // Getting the sizes of each aggregate: + AggMIS::Types::IntVector_h* ps = Aggregation::GetPartSizes(aggregation); + partSizes.swap(*ps); + delete ps; + + // Filling in + FillAggAdjacency(); + FillAggMap(); + + verbose = false; + minSize = 20; + maxSize = 30; + outsizedParts = 0; + merges = 0; + mergeSplits = 0; + splits = 0; + } + void MergeSplitConditionerCPU::SetSizeBounds(int min, + int max) { + minSize = min; + maxSize = max; + } + void MergeSplitConditionerCPU::SetVerbose(bool v) { + verbose = v; + } + void MergeSplitConditionerCPU::SetNodeWeights(AggMIS::Types::IntVector_h &input) { + nodeWeights.swap(input); + AggMIS::Types::IntVector_h *ws = Aggregation::GetPartSizes(aggregation, nodeWeights); + weightedSizes.swap(*ws); + ws->clear(); + delete ws; + } + AggMIS::Types::IntVector_h* MergeSplitConditionerCPU::GetAggregation() { + return &aggregation; + } + AggMIS::Types::IntVector_h* MergeSplitConditionerCPU::GetNodeWeights() { + return &nodeWeights; + } + void MergeSplitConditionerCPU::CycleMerges(bool force) { + // int count = 0; + // while (MarkMerges(force)) + // { + // MakeMerges(false); + // count++; + // } + // if (verbose) + // printf("Finished cycling merges after %d cycles.\n", count); + MakeMergesDirect(force); + } + void MergeSplitConditionerCPU::CycleSplits(bool force) { + int count = 0; + // while (MarkSplits(force)) + // { + // MakeSplits(); + // count++; + // } + int splitsMade = 1; + while (splitsMade > 0) { + int startingSplits = splits; + MakeSplitsDirect(force); + splitsMade = splits - startingSplits; + count++; + } + if (verbose) + printf("Finished cycling splits after %d cycles.\n", count); + } + void MergeSplitConditionerCPU::CycleMergeSplits(float minImprove, + int desiredSize) { + // Start with an initial cycle + MakeMergeSplits(desiredSize); + + // Choosing which sizes to use: + AggMIS::Types::IntVector_h *sizes = &partSizes; + if (nodeWeights.size() > 0) + sizes = &weightedSizes; + + // Check to see how much improvement was made + int after = thrust::count_if(sizes->begin(), sizes->end(), Functors::isOutSized(minSize, maxSize)); + float improvement = (float)(outsizedParts - after) / outsizedParts; + outsizedParts = after; + + // While good progress is being made continue cycling + while (improvement > minImprove) + { + // Perform Cycle and check improvement + MakeMergeSplits(desiredSize); + after = thrust::count_if(sizes->begin(), sizes->end(), Functors::isOutSized(minSize, maxSize)); + improvement = (float)(outsizedParts - after) / outsizedParts; + outsizedParts = after; + } + } + bool MergeSplitConditionerCPU::Condition(int desiredSize, + bool respectUpper, + float tolerance, + float minImprove, + int maxCycles) { + if (verbose) + PrintProgress(&std::cout, "Starting conditioning.", true, true, true); + + // Start by making any optimal merges and splits + if (verbose) + printf("Starting to CycleMerges\n"); + CycleMerges(false); + if (verbose) + printf("Starting to CycleSplits\n"); + CycleSplits(false); + + if (verbose) + printf("Starting to CycleMergeSplits\n"); + // Cycle MergeSplits too, to make sure outsizedParts has a value + CycleMergeSplits(minImprove, desiredSize); + + // Find improvement ratio from initial cycle + float currentRatio = (float)outsizedParts / partSizes.size(); + if (verbose) + printf("Initial outsized ratio is: %d / %d = %f\n", + outsizedParts, partSizes.size(), currentRatio); + + // Starting main cycle phase + int counter = 1; + bool highCycle = false; + while (currentRatio > tolerance && counter++ < maxCycles) + { + if (highCycle) + CycleMerges(true); + else + CycleSplits(true); + CycleMergeSplits(minImprove, desiredSize); + + // Checking the current improvement ratio + if ((highCycle && !respectUpper) || (!highCycle && respectUpper)) + currentRatio = (float)outsizedParts / partSizes.size(); + + // Switch cycle type + highCycle = !highCycle; + + if (verbose) + { + std::stringstream ss; + ss << "After condition cycle: " << counter++; + PrintProgress(&std::cout, ss.str(), true, true, true); } - void MergeSplitConditionerCPU::CycleMerges(bool force) { -// int count = 0; -// while (MarkMerges(force)) -// { -// MakeMerges(false); -// count++; -// } -// if (verbose) -// printf("Finished cycling merges after %d cycles.\n", count); + } + + // Cleaning up + if (respectUpper) + { + CycleSplits(true); + CycleMerges(false); + } else + CycleMerges(true); + + // Checking if we match criteria given: + int undersized = thrust::count_if(partSizes.begin(), partSizes.end(), Functors::lessThan(minSize)); + int oversized = thrust::count_if(partSizes.begin(), partSizes.end(), Functors::greaterThan(maxSize)); + + if (verbose) + PrintProgress(&std::cout, "After conditioning completed.", true, true, true); + + // Checking if the size constraints are met for the return + if (respectUpper) + return (oversized == 0 && (float)outsizedParts / partSizes.size() < tolerance); + else + return (undersized == 0 && (float)outsizedParts / partSizes.size() < tolerance); + } + void MergeSplitConditionerCPU::PrintProgress(std::ostream* output, + std::string note, + bool graphStat, + bool progressStat, + bool sizeStat) { + *output << "\n------------------- Progress Check ------------------\n"; + *output << "Note: " << note.c_str() << "\n"; + + if (graphStat) + PrintGraphStats(output, false); + + if (progressStat) + PrintProgressStats(output, false); + + if (sizeStat) + PrintSizeStats(output, false); + + *output << "-----------------------------------------------------\n\n"; + } + void MergeSplitConditionerCPU::PrintSizeStats(std::ostream* output, + bool makeHeader) { + if (makeHeader) + *output << "\n--------------------- Size Check --------------------\n"; + + // Choosing which sizes to use: + AggMIS::Types::IntVector_h *sizes = &partSizes; + if (nodeWeights.size() > 0) + sizes = &weightedSizes; + + int undersized = thrust::count_if(sizes->begin(), + sizes->end(), + Functors::lessThan(minSize)); + int oversized = thrust::count_if(sizes->begin(), + sizes->end(), + Functors::greaterThan(maxSize)); + int largest = thrust::reduce(sizes->begin(), + sizes->end(), + 0, + thrust::maximum()); + int smallest = thrust::reduce(sizes->begin(), + sizes->end(), + INT_MAX, + thrust::minimum()); + + *output << "Aggregate size statistics:"; + *output << "\n\tUndersized(<" << minSize << "): " << undersized << " / " << (partSizes.size()) << " Total"; + *output << "\n\tOversized(>" << maxSize << "): " << oversized << " / " << (partSizes.size()) << " Total"; + *output << "\n\tSmallest: " << smallest; + *output << " Largest: " << largest << "\n"; + + if (nodeWeights.size() > 0) + { + largest = thrust::reduce(partSizes.begin(), + partSizes.end(), + 0, + thrust::maximum()); + smallest = thrust::reduce(partSizes.begin(), + partSizes.end(), + INT_MAX, + thrust::minimum()); + *output << "\n\tUnweighted: Smallest: " << smallest; + *output << " Largest: " << largest << "\n"; + } + + if (makeHeader) + *output << "-----------------------------------------------------\n\n"; + } + void MergeSplitConditionerCPU::PrintProgressStats(std::ostream* output, + bool makeHeader) { + if (makeHeader) + *output << "\n------------------- Progress Check ------------------\n"; + + *output << "Processing done:"; + *output << "\n\tMerges: " << merges; + *output << "\tSplits: " << splits; + *output << "\tMerge-Splits: " << mergeSplits << "\n"; + + if (makeHeader) + *output << "-----------------------------------------------------\n\n"; + } + void MergeSplitConditionerCPU::PrintGraphStats(std::ostream* output, + bool makeHeader) { + if (makeHeader) + *output << "\n----------------- Graph Information -----------------\n"; + + int totalWeight = thrust::reduce(nodeWeights.begin(), nodeWeights.end()); + int minWeight = thrust::reduce(nodeWeights.begin(), + nodeWeights.end(), + INT_MAX, + thrust::minimum()); + int maxWeight = thrust::reduce(nodeWeights.begin(), + nodeWeights.end(), + 0, + thrust::maximum()); + + AggMIS::Types::IntVector_h *valences = GraphHelpers::GetValences(*graph); + int minValence = thrust::reduce(valences->begin(), + valences->end(), + INT_MAX, + thrust::minimum()); + int maxValence = thrust::reduce(valences->begin(), + valences->end(), + 0, + thrust::maximum()); + valences->clear(); + delete valences; + + *output << "Graph Information:"; + *output << "\n\tNodes: " << graph->Size(); + if (nodeWeights.size() > 0) + *output << " Graph is weighted"; + else + *output << " Graph is unweighted"; + + *output << "\n\tMin. Valence: " << minValence; + *output << " Max. Valence: " << maxValence; + *output << " Avg. Valence: " << ((float)graph->adjacency->size() / graph->Size()); + + if (nodeWeights.size() > 0) { + *output << "\n\tTotal Weight: " << totalWeight; + *output << " Avg. Weight: " << ((float)totalWeight / graph->Size()); + *output << " Min. Weight: " << minWeight; + *output << " Max. Weight: " << maxWeight; + } + *output << "\n"; + + if (makeHeader) + *output << "-----------------------------------------------------\n\n"; + } + void MergeSplitConditionerCPU::InteractiveConsole(std::string message) { + // Start off by printing overall status info and message + PrintProgress(&std::cout, message, true, true, true); + + // Setting needed variables to defaults + float minImprove = .1; + int desiredSize = (minSize + maxSize) / 2; + float tolerance = .1; + int maxCycles = 10; + bool cycling = true; + bool respectUpper = true; + + // Starting the main prompt: + char operation; + printf("\nIC:"); + std::cin >> operation; + while (operation != 'd') + { + if (operation == 'o' || operation == 'f') + { + bool force = operation == 'f'; + std::cin >> operation; + if (operation == 'm') + { + // if (cycling) + // CycleMerges(force); + // else { + // MarkMerges(force); + // MakeMerges(false); + // } MakeMergesDirect(force); - } - void MergeSplitConditionerCPU::CycleSplits(bool force) { - int count = 0; -// while (MarkSplits(force)) -// { -// MakeSplits(); -// count++; -// } - int splitsMade = 1; - while (splitsMade > 0) { - int startingSplits = splits; - MakeSplitsDirect(force); - splitsMade = splits - startingSplits; - count++; - } - if (verbose) - printf("Finished cycling splits after %d cycles.\n", count); - } - void MergeSplitConditionerCPU::CycleMergeSplits(float minImprove, - int desiredSize) { - // Start with an initial cycle + std::string msg = force ? "After forced merges" : "After optimal merges"; + PrintProgress(&std::cout, msg, false, true, true); + } + if (operation == 's') + { + // if (cycling) + // CycleSplits(force); + // else { + // MarkSplits(force); + // MakeSplits(); + // } + MakeSplitsDirect(force); + std::string msg = force ? "After forced splits" : "After optimal splits"; + PrintProgress(&std::cout, msg, false, true, true); + } + if (operation == 'g') + { + // if (cycling) + // CycleMergeSplits(minImprove, desiredSize); + // else + // MakeMergeSplits(desiredSize); MakeMergeSplits(desiredSize); - - // Choosing which sizes to use: - IntVector_h *sizes = &partSizes; - if (nodeWeights.size() > 0) - sizes = &weightedSizes; - - // Check to see how much improvement was made - int after = thrust::count_if(sizes->begin(), sizes->end(), Functors::isOutSized(minSize, maxSize)); - float improvement = (float)(outsizedParts - after)/outsizedParts; - outsizedParts = after; - - // While good progress is being made continue cycling - while (improvement > minImprove) - { - // Perform Cycle and check improvement - MakeMergeSplits(desiredSize); - after = thrust::count_if(sizes->begin(), sizes->end(), Functors::isOutSized(minSize, maxSize)); - improvement = (float)(outsizedParts - after)/outsizedParts; - outsizedParts = after; - } + PrintProgress(&std::cout, "After merge-splits", false, true, true); + } + } else if (operation == 's') { + // Printing the current values of the variables + std::string cyclingFlag = cycling ? "True" : "False"; + std::string respectUpperFlag = respectUpper ? "True" : "False"; + std::cout << "\nCurrent values of variables:"; + std::cout << "\n\tminSize: " << minSize; + std::cout << " maxSize: " << maxSize; + std::cout << " desiredSize: " << desiredSize; + std::cout << " maxCycles: " << maxCycles; + std::cout << "\n\tminImprove: " << minImprove; + std::cout << " tolerance: " << tolerance; + std::cout << " cycling: " << cyclingFlag; + std::cout << " respectUpper: " << respectUpperFlag; + std::cout << "\n\nEnter new values in same order\nIC:"; + + // Grabbing the new values + std::cin >> minSize; + std::cin >> maxSize; + std::cin >> desiredSize; + std::cin >> maxCycles; + std::cin >> minImprove; + std::cin >> tolerance; + std::cin >> cycling; + std::cin >> respectUpper; + + // Confirming the entry + cyclingFlag = cycling ? "True" : "False"; + respectUpperFlag = respectUpper ? "True" : "False"; + std::cout << "\nNew values of variables:"; + std::cout << "\n\tminSize: " << minSize; + std::cout << " maxSize: " << maxSize; + std::cout << " desiredSize: " << desiredSize; + std::cout << " maxCycles: " << maxCycles; + std::cout << "\n\tminImprove: " << minImprove; + std::cout << " tolerance: " << tolerance; + std::cout << " cycling: " << cyclingFlag; + std::cout << " respectUpper: " << respectUpperFlag << "\n\n"; + } else if (operation == 'c') + { + Condition(desiredSize, respectUpper, tolerance, minImprove, maxCycles); + PrintProgress(&std::cout, "After conditioning", false, true, true); + } else if (operation == 'v') { + bool valid = Aggregation::IsValidAggregation(*graph, aggregation, false); + if (valid) + printf("Aggregation is valid\n"); + else + printf("Aggregation is not valid!\n"); + } else if (operation == 'l') { + bool v; + std::cin >> v; + SetVerbose(v); + printf("Set verbose to %s\n", v ? "True" : "False"); } - bool MergeSplitConditionerCPU::Condition(int desiredSize, - bool respectUpper, - float tolerance, - float minImprove, - int maxCycles) { - if (verbose) - PrintProgress(&cout, "Starting conditioning.", true, true, true); - - // Start by making any optimal merges and splits - if (verbose) - printf("Starting to CycleMerges\n"); - CycleMerges(false); - if (verbose) - printf("Starting to CycleSplits\n"); - CycleSplits(false); - - if (verbose) - printf("Starting to CycleMergeSplits\n"); - // Cycle MergeSplits too, to make sure outsizedParts has a value - CycleMergeSplits(minImprove, desiredSize); - - // Find improvement ratio from initial cycle - float currentRatio = (float)outsizedParts / partSizes.size(); - if (verbose) - printf("Initial outsized ratio is: %d / %d = %f\n", - outsizedParts, partSizes.size(), currentRatio); - - // Starting main cycle phase - int counter = 1; - bool highCycle = false; - while(currentRatio > tolerance && counter++ < maxCycles) - { - if (highCycle) - CycleMerges(true); - else - CycleSplits(true); - CycleMergeSplits(minImprove, desiredSize); - - // Checking the current improvement ratio - if ((highCycle && !respectUpper) || (!highCycle && respectUpper)) - currentRatio = (float)outsizedParts / partSizes.size(); - - // Switch cycle type - highCycle = !highCycle; - - if (verbose) - { - stringstream ss; - ss << "After condition cycle: " << counter++; - PrintProgress(&cout, ss.str(), true, true, true); - } - } + // Printing prompt for another go + printf("IC:"); + std::cin >> operation; + } + } + bool MergeSplitConditionerCPU::MarkMerges(bool force) { + bool marked = false; + + // Initializing mergesToMake array + mergesToMake.assign(inducedGraph->Size(), -1); + + // Get the appropriate sizes + AggMIS::Types::IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; + + // Figure out how large aggregates should be + int desiredSize = (minSize + maxSize) / 2; + + // For every aggregate see if it should merge + for (int aggId = 0; aggId < inducedGraph->Size(); aggId++) { + // Getting size of current aggregate + int currentSize = sizes[aggId]; + + // Tracking the best seen merge + int bestMerge = -1; + int smallestDifference = INT_MAX; + + // If aggregate too small check for merges: + if (currentSize < minSize && mergesToMake[aggId] == -1) { + // Look at neighboring aggregates + for (int* nIt = inducedGraph->nStart(aggId); + nIt != inducedGraph->nEnd(aggId); + nIt++) { + int neighborAgg = *nIt; - // Cleaning up - if (respectUpper) - { - CycleSplits(true); - CycleMerges(false); + // Only handle neighbors not already merging + if (mergesToMake[neighborAgg] == -1) { + int neighborSize = sizes[neighborAgg]; + int mergedSize = currentSize + neighborSize; + int difference = mergedSize > desiredSize ? + mergedSize - desiredSize : + desiredSize - mergedSize; + if (mergedSize <= maxSize || force) { + if (difference < smallestDifference) { + smallestDifference = difference; + bestMerge = neighborAgg; + } + } } - else - CycleMerges(true); - - // Checking if we match criteria given: - int undersized = thrust::count_if(partSizes.begin(), partSizes.end(), Functors::lessThan(minSize)); - int oversized = thrust::count_if(partSizes.begin(), partSizes.end(), Functors::greaterThan(maxSize)); - - if (verbose) - PrintProgress(&cout, "After conditioning completed.", true, true, true); - - // Checking if the size constraints are met for the return - if (respectUpper) - return (oversized == 0 && (float)outsizedParts / partSizes.size() < tolerance); - else - return (undersized == 0 && (float)outsizedParts / partSizes.size() < tolerance); + } } - void MergeSplitConditionerCPU::PrintProgress(ostream* output, - string note, - bool graphStat, - bool progressStat, - bool sizeStat) { - *output << "\n------------------- Progress Check ------------------\n"; - *output << "Note: " << note.c_str() << "\n"; - - if (graphStat) - PrintGraphStats(output, false); - - if (progressStat) - PrintProgressStats(output, false); - - if (sizeStat) - PrintSizeStats(output, false); - - *output << "-----------------------------------------------------\n\n"; + + if (bestMerge != -1) { + mergesToMake[aggId] = bestMerge; + mergesToMake[bestMerge] = aggId; + marked = true; } - void MergeSplitConditionerCPU::PrintSizeStats(ostream* output, - bool makeHeader) { - if (makeHeader) - *output << "\n--------------------- Size Check --------------------\n"; - - // Choosing which sizes to use: - IntVector_h *sizes = &partSizes; - if (nodeWeights.size() > 0) - sizes = &weightedSizes; - - int undersized = thrust::count_if(sizes->begin(), - sizes->end(), - Functors::lessThan(minSize)); - int oversized = thrust::count_if(sizes->begin(), - sizes->end(), - Functors::greaterThan(maxSize)); - int largest = thrust::reduce(sizes->begin(), - sizes->end(), - 0, - thrust::maximum()); - int smallest = thrust::reduce(sizes->begin(), - sizes->end(), - INT_MAX, - thrust::minimum()); - - *output << "Aggregate size statistics:"; - *output << "\n\tUndersized(<" << minSize << "): " << undersized << " / " << (partSizes.size()) << " Total"; - *output << "\n\tOversized(>" << maxSize << "): " << oversized << " / " << (partSizes.size()) << " Total"; - *output << "\n\tSmallest: " << smallest; - *output << " Largest: " << largest << "\n"; - - if (nodeWeights.size() > 0) - { - largest = thrust::reduce(partSizes.begin(), - partSizes.end(), - 0, - thrust::maximum()); - smallest = thrust::reduce(partSizes.begin(), - partSizes.end(), - INT_MAX, - thrust::minimum()); - *output << "\n\tUnweighted: Smallest: " << smallest; - *output << " Largest: " << largest << "\n"; + } + return marked; + } + bool MergeSplitConditionerCPU::MarkSplits(bool force) { + // Initialize + + + // Get the appropriate sizes + AggMIS::Types::IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; + return false; + } + void MergeSplitConditionerCPU::MarkMergeSplits(int desiredSize) { + + } + void MergeSplitConditionerCPU::MakeSplits() { + + } + void MergeSplitConditionerCPU::MakeMerges(bool markSplits) { + // Figuring the offsets to use + int offset = 0; + mergeOffsets.resize(mergesToMake.size()); + for (int i = 0; i < mergesToMake.size(); i++) + mergeOffsets[i] = mergesToMake[i] != -1 && mergesToMake[i] < i ? + ++offset : offset; + + // Making the merges + for (int i = 0; i < aggregation.size(); i++) { + int aggId = aggregation[i]; + int mergeTo = mergesToMake[aggId]; + if (mergeTo != -1 && mergeTo < aggId) + aggregation[i] = mergeTo - mergeOffsets[mergeTo]; + else + aggregation[i] = aggId - mergeOffsets[aggId]; + } + + // Refiguring stuff + merges += mergeOffsets.back(); + delete inducedGraph; + inducedGraph = GraphHelpers::GetInducedGraph(*graph, aggregation); + AggMIS::Types::IntVector_h *ps = Aggregation::GetPartSizes(aggregation); + partSizes.swap(*ps); + ps->clear(); + delete ps; + if (nodeWeights.size() > 0) { + AggMIS::Types::IntVector_h *ws = Aggregation::GetPartSizes(aggregation, nodeWeights); + weightedSizes.swap(*ws); + ws->clear(); + delete ws; + } + } + void MergeSplitConditionerCPU::MakeMergesDirect(bool force) { + // Get the appropriate sizes + AggMIS::Types::IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; + + // Figure out how large aggregates should be + int desiredSize = (minSize + maxSize) / 2; + + // For every aggregate see if it should merge + int aggId = 0; + while (aggId < aggAdjacency.size()) { + // Getting size of current aggregate + int currentSize = sizes[aggId]; + + // Tracking the best seen merge + int bestMerge = -1; + int smallestDifference = INT_MAX; + + // If aggregate too small check for merges: + while (currentSize < minSize) { + // Look at neighboring aggregates + for (int nIt = 0; nIt < aggAdjacency[aggId].size(); nIt++) { + int neighborAgg = aggAdjacency[aggId][nIt]; + int neighborSize = sizes[neighborAgg]; + int mergedSize = currentSize + neighborSize; + int difference = mergedSize > desiredSize ? + mergedSize - desiredSize : + desiredSize - mergedSize; + if (mergedSize <= maxSize || force) { + if (difference < smallestDifference) { + smallestDifference = difference; + bestMerge = neighborAgg; + } } - - if (makeHeader) - *output << "-----------------------------------------------------\n\n"; - } - void MergeSplitConditionerCPU::PrintProgressStats(ostream* output, - bool makeHeader) { - if (makeHeader) - *output << "\n------------------- Progress Check ------------------\n"; - - *output << "Processing done:"; - *output << "\n\tMerges: " << merges; - *output << "\tSplits: " << splits; - *output << "\tMerge-Splits: " << mergeSplits << "\n"; - - if (makeHeader) - *output << "-----------------------------------------------------\n\n"; - } - void MergeSplitConditionerCPU::PrintGraphStats(ostream* output, - bool makeHeader) { - if (makeHeader) - *output << "\n----------------- Graph Information -----------------\n"; - - int totalWeight = thrust::reduce(nodeWeights.begin(), nodeWeights.end()); - int minWeight = thrust::reduce(nodeWeights.begin(), - nodeWeights.end(), - INT_MAX, - thrust::minimum()); - int maxWeight = thrust::reduce(nodeWeights.begin(), - nodeWeights.end(), - 0, - thrust::maximum()); - - IntVector_h *valences = GraphHelpers::GetValences(*graph); - int minValence = thrust::reduce(valences->begin(), - valences->end(), - INT_MAX, - thrust::minimum()); - int maxValence = thrust::reduce(valences->begin(), - valences->end(), - 0, - thrust::maximum()); - valences->clear(); - delete valences; - - *output << "Graph Information:"; - *output << "\n\tNodes: " << graph->Size(); - if (nodeWeights.size() > 0) - *output << " Graph is weighted"; - else - *output << " Graph is unweighted"; - - *output << "\n\tMin. Valence: " << minValence; - *output << " Max. Valence: " << maxValence; - *output << " Avg. Valence: " << ((float)graph->adjacency->size()/graph->Size()); - - if (nodeWeights.size() > 0) { - *output << "\n\tTotal Weight: " << totalWeight; - *output << " Avg. Weight: " << ((float)totalWeight / graph->Size()); - *output << " Min. Weight: " << minWeight; - *output << " Max. Weight: " << maxWeight; + } + if (bestMerge != -1) { + if (verbose) { + printf("Aggregate %d of size %d found neighbor %d of size %d to merge with.\n", + aggId, currentSize, bestMerge, sizes[bestMerge]); } - *output << "\n"; - - if (makeHeader) - *output << "-----------------------------------------------------\n\n"; - } - void MergeSplitConditionerCPU::InteractiveConsole(string message) { - // Start off by printing overall status info and message - PrintProgress(&cout, message, true, true, true); - - // Setting needed variables to defaults - float minImprove = .1; - int desiredSize = (minSize + maxSize) / 2; - float tolerance = .1; - int maxCycles = 10; - bool cycling = true; - bool respectUpper = true; - - // Starting the main prompt: - char operation; - printf("\nIC:"); - cin >> operation; - while (operation != 'd') - { - if (operation == 'o' || operation == 'f') - { - bool force = operation == 'f'; - cin >> operation; - if (operation == 'm') - { -// if (cycling) -// CycleMerges(force); -// else { -// MarkMerges(force); -// MakeMerges(false); -// } - MakeMergesDirect(force); - string msg = force ? "After forced merges" : "After optimal merges"; - PrintProgress(&cout, msg, false, true, true); - } - if (operation == 's') - { -// if (cycling) -// CycleSplits(force); -// else { -// MarkSplits(force); -// MakeSplits(); -// } - MakeSplitsDirect(force); - string msg = force ? "After forced splits" : "After optimal splits"; - PrintProgress(&cout, msg, false, true, true); - } - if (operation == 'g') - { -// if (cycling) -// CycleMergeSplits(minImprove, desiredSize); -// else -// MakeMergeSplits(desiredSize); - MakeMergeSplits(desiredSize); - PrintProgress(&cout, "After merge-splits", false, true, true); - } - } - else if (operation == 's') { - // Printing the current values of the variables - string cyclingFlag = cycling ? "True" : "False"; - string respectUpperFlag = respectUpper ? "True" : "False"; - cout << "\nCurrent values of variables:"; - cout << "\n\tminSize: " << minSize; - cout << " maxSize: " << maxSize; - cout << " desiredSize: " << desiredSize; - cout << " maxCycles: " << maxCycles; - cout << "\n\tminImprove: " << minImprove; - cout << " tolerance: " << tolerance; - cout << " cycling: " << cyclingFlag; - cout << " respectUpper: " << respectUpperFlag; - cout << "\n\nEnter new values in same order\nIC:"; - - // Grabbing the new values - cin >> minSize; - cin >> maxSize; - cin >> desiredSize; - cin >> maxCycles; - cin >> minImprove; - cin >> tolerance; - cin >> cycling; - cin >> respectUpper; - - // Confirming the entry - cyclingFlag = cycling ? "True" : "False"; - respectUpperFlag = respectUpper ? "True" : "False"; - cout << "\nNew values of variables:"; - cout << "\n\tminSize: " << minSize; - cout << " maxSize: " << maxSize; - cout << " desiredSize: " << desiredSize; - cout << " maxCycles: " << maxCycles; - cout << "\n\tminImprove: " << minImprove; - cout << " tolerance: " << tolerance; - cout << " cycling: " << cyclingFlag; - cout << " respectUpper: " << respectUpperFlag << "\n\n"; - } - else if (operation == 'c') - { - Condition(desiredSize, respectUpper, tolerance, minImprove, maxCycles); - PrintProgress(&cout, "After conditioning", false, true, true); - } - else if (operation == 'v') { - bool valid = Aggregation::IsValidAggregation(*graph, aggregation, false); - if (valid) - printf("Aggregation is valid\n"); - else - printf("Aggregation is not valid!\n"); - } - else if (operation == 'l') { - bool v; - cin >> v; - SetVerbose(v); - printf("Set verbose to %s\n", v ? "True" : "False"); - } - // Printing prompt for another go - printf("IC:"); - cin >> operation; + aggId = MergeAggregates(aggId, bestMerge); + if (verbose) { + printf("After merge Aggregate %d has size %d\n", + aggId, sizes[aggId]); } - } - bool MergeSplitConditionerCPU::MarkMerges(bool force) { - bool marked = false; - - // Initializing mergesToMake array - mergesToMake.assign(inducedGraph->Size(), -1); - - // Get the appropriate sizes - IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; - - // Figure out how large aggregates should be - int desiredSize = (minSize + maxSize) / 2; - - // For every aggregate see if it should merge - for (int aggId = 0; aggId < inducedGraph->Size(); aggId++) { - // Getting size of current aggregate - int currentSize = sizes[aggId]; - - // Tracking the best seen merge - int bestMerge = -1; - int smallestDifference = INT_MAX; - - // If aggregate too small check for merges: - if (currentSize < minSize && mergesToMake[aggId] == -1) { - // Look at neighboring aggregates - for (int* nIt = inducedGraph->nStart(aggId); - nIt != inducedGraph->nEnd(aggId); - nIt++) { - int neighborAgg = *nIt; - - // Only handle neighbors not already merging - if (mergesToMake[neighborAgg] == -1) { - int neighborSize = sizes[neighborAgg]; - int mergedSize = currentSize + neighborSize; - int difference = mergedSize > desiredSize ? - mergedSize - desiredSize : - desiredSize - mergedSize; - if (mergedSize <= maxSize || force) { - if (difference < smallestDifference) { - smallestDifference = difference; - bestMerge = neighborAgg; - } - } - } - } - } - - if (bestMerge != -1) { - mergesToMake[aggId] = bestMerge; - mergesToMake[bestMerge] = aggId; - marked = true; - } + merges++; + + // Resetting to look for other merges + currentSize = sizes[aggId]; + bestMerge = -1; + smallestDifference = INT_MAX; + } else { + if (verbose) { + printf("No merges found for aggregate %d of size %d\n", + aggId, currentSize); } - return marked; + break; + } } - bool MergeSplitConditionerCPU::MarkSplits(bool force) { - // Initialize - - - // Get the appropriate sizes - IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; - return false; - } - void MergeSplitConditionerCPU::MarkMergeSplits(int desiredSize) { - - } - void MergeSplitConditionerCPU::MakeSplits() { - - } - void MergeSplitConditionerCPU::MakeMerges(bool markSplits) { - // Figuring the offsets to use - int offset = 0; - mergeOffsets.resize(mergesToMake.size()); - for (int i = 0; i < mergesToMake.size(); i++) - mergeOffsets[i] = mergesToMake[i] != -1 && mergesToMake[i] < i ? - ++offset : offset; - - // Making the merges - for (int i = 0; i < aggregation.size(); i++) { - int aggId = aggregation[i]; - int mergeTo = mergesToMake[aggId]; - if (mergeTo != -1 && mergeTo < aggId) - aggregation[i] = mergeTo - mergeOffsets[mergeTo]; - else - aggregation[i] = aggId - mergeOffsets[aggId]; - } - - // Refiguring stuff - merges += mergeOffsets.back(); - delete inducedGraph; - inducedGraph = GraphHelpers::GetInducedGraph(*graph, aggregation); - IntVector_h *ps = Aggregation::GetPartSizes(aggregation); - partSizes.swap(*ps); - ps->clear(); - delete ps; - if (nodeWeights.size() > 0) { - IntVector_h *ws = Aggregation::GetPartSizes(aggregation, nodeWeights); - weightedSizes.swap(*ws); - ws->clear(); - delete ws; - } + aggId++; + } + } + int MergeSplitConditionerCPU::MergeAggregates(int aggA, int aggB) { + return MergeAggregates(aggA, aggB, true); + } + int MergeSplitConditionerCPU::MergeAggregates(int aggA, int aggB, bool fillSpot) { + // Make sure aggA has the lower index + if (aggA > aggB) { + int swapper = aggB; + aggB = aggA; + aggA = swapper; + } + + // Mark nodes in aggB as in aggA + for (int nIt = 0; nIt < aggMap[aggB].size(); nIt++) + aggregation[aggMap[aggB][nIt]] = aggA; + + // Add nodes in aggB to aggA's node list + aggMap[aggA].insert(aggMap[aggA].end(), + aggMap[aggB].begin(), + aggMap[aggB].end()); + sort(aggMap[aggA].begin(), aggMap[aggA].end()); + + // Clearing out aggB's node list + aggMap[aggB].clear(); + + // Removing edges to aggB and replastd::cing with edges to aggA + for (int nIt = 0; nIt < aggAdjacency[aggB].size(); nIt++) { + int neighborAgg = aggAdjacency[aggB][nIt]; + + // If the neighbor of aggB is also a neighbor of aggA + // or is aggA just remove reference to aggB. + if (binary_search(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end(), + aggA) || neighborAgg == aggA) { + remove(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end(), + aggB); + aggAdjacency[neighborAgg].pop_back(); } - void MergeSplitConditionerCPU::MakeMergesDirect(bool force) { - // Get the appropriate sizes - IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; - - // Figure out how large aggregates should be - int desiredSize = (minSize + maxSize) / 2; - - // For every aggregate see if it should merge - int aggId = 0; - while (aggId < aggAdjacency.size()) { - // Getting size of current aggregate - int currentSize = sizes[aggId]; - - // Tracking the best seen merge - int bestMerge = -1; - int smallestDifference = INT_MAX; - - // If aggregate too small check for merges: - while (currentSize < minSize) { - // Look at neighboring aggregates - for (int nIt = 0; nIt < aggAdjacency[aggId].size(); nIt++) { - int neighborAgg = aggAdjacency[aggId][nIt]; - int neighborSize = sizes[neighborAgg]; - int mergedSize = currentSize + neighborSize; - int difference = mergedSize > desiredSize ? - mergedSize - desiredSize : - desiredSize - mergedSize; - if (mergedSize <= maxSize || force) { - if (difference < smallestDifference) { - smallestDifference = difference; - bestMerge = neighborAgg; - } - } - } - if (bestMerge != -1) { - if (verbose) { - printf("Aggregate %d of size %d found neighbor %d of size %d to merge with.\n", - aggId, currentSize, bestMerge, sizes[bestMerge]); - } - aggId = MergeAggregates(aggId, bestMerge); - if (verbose) { - printf("After merge Aggregate %d has size %d\n", - aggId, sizes[aggId]); - } - merges++; - - // Resetting to look for other merges - currentSize = sizes[aggId]; - bestMerge = -1; - smallestDifference = INT_MAX; - } - else { - if (verbose) { - printf("No merges found for aggregate %d of size %d\n", - aggId, currentSize); - } - break; - } - } - aggId++; - } + // Otherwise remove the reference to aggB and add one + // to aggA + else { + remove(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end(), + aggB); + aggAdjacency[neighborAgg].back() = aggA; + sort(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end()); } - int MergeSplitConditionerCPU::MergeAggregates(int aggA, int aggB) { - return MergeAggregates(aggA, aggB, true); + } + + // Setting new size of aggA + partSizes[aggA] += partSizes[aggB]; + if (nodeWeights.size() > 0) + weightedSizes[aggA] += weightedSizes[aggB]; + + // Getting the union of adjacency for merged aggregate + std::vector temp(aggAdjacency[aggA].size() + + aggAdjacency[aggB].size()); + remove(aggAdjacency[aggB].begin(), + aggAdjacency[aggB].end(), + aggA); + std::vector::iterator newEnd; + newEnd = set_union(aggAdjacency[aggA].begin(), + aggAdjacency[aggA].end(), + aggAdjacency[aggB].begin(), + aggAdjacency[aggB].end() - 1, + temp.begin()); + temp.resize(newEnd - temp.begin()); + aggAdjacency[aggA].swap(temp); + temp.clear(); + aggAdjacency[aggB].clear(); + + if (fillSpot) { + // Finding an aggregate to shift into the empty spot + if (aggB == aggMap.size() - 1) { + aggMap.pop_back(); + aggAdjacency.pop_back(); + } else { + // Move the last aggregate to fill + int aggToMove = aggMap.size() - 1; + + // Swap out the node list + aggMap[aggB].swap(aggMap[aggToMove]); + aggMap.pop_back(); + + // Mark nodes in aggregation + for (int nIt = 0; nIt < aggMap[aggB].size(); nIt++) + aggregation[aggMap[aggB][nIt]] = aggB; + + // Swap out the adjacency list + aggAdjacency[aggB].swap(aggAdjacency[aggToMove]); + aggAdjacency.pop_back(); + + // Fix neighbor's adjacency lists + for (int nIt = 0; nIt < aggAdjacency[aggB].size(); nIt++) { + // The old Id has to be last in the list + int neighborAgg = aggAdjacency[aggB][nIt]; + aggAdjacency[neighborAgg].back() = aggB; + sort(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end()); + } + + partSizes[aggB] = partSizes[aggToMove]; + if (nodeWeights.size() > 0) + weightedSizes[aggB] = weightedSizes[aggToMove]; } - int MergeSplitConditionerCPU::MergeAggregates(int aggA, int aggB, bool fillSpot) { - // Make sure aggA has the lower index - if (aggA > aggB) { - int swapper = aggB; - aggB = aggA; - aggA = swapper; - } - - // Mark nodes in aggB as in aggA - for (int nIt = 0; nIt < aggMap[aggB].size(); nIt++) - aggregation[aggMap[aggB][nIt]] = aggA; - - // Add nodes in aggB to aggA's node list - aggMap[aggA].insert(aggMap[aggA].end(), - aggMap[aggB].begin(), - aggMap[aggB].end()); - sort(aggMap[aggA].begin(), aggMap[aggA].end()); - - // Clearing out aggB's node list - aggMap[aggB].clear(); - - // Removing edges to aggB and replacing with edges to aggA - for (int nIt = 0; nIt < aggAdjacency[aggB].size(); nIt++) { - int neighborAgg = aggAdjacency[aggB][nIt]; - - // If the neighbor of aggB is also a neighbor of aggA - // or is aggA just remove reference to aggB. - if (binary_search(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end(), - aggA) || neighborAgg == aggA) { - remove(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end(), - aggB); - aggAdjacency[neighborAgg].pop_back(); - } - // Otherwise remove the reference to aggB and add one - // to aggA - else { - remove(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end(), - aggB); - aggAdjacency[neighborAgg].back() = aggA; - sort(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end()); - } - } - - // Setting new size of aggA - partSizes[aggA] += partSizes[aggB]; - if (nodeWeights.size() > 0) - weightedSizes[aggA] += weightedSizes[aggB]; - - // Getting the union of adjacency for merged aggregate - vector temp(aggAdjacency[aggA].size() + - aggAdjacency[aggB].size()); - remove(aggAdjacency[aggB].begin(), - aggAdjacency[aggB].end(), - aggA); - vector::iterator newEnd; - newEnd = set_union(aggAdjacency[aggA].begin(), - aggAdjacency[aggA].end(), - aggAdjacency[aggB].begin(), - aggAdjacency[aggB].end() - 1, - temp.begin()); - temp.resize(newEnd - temp.begin()); - aggAdjacency[aggA].swap(temp); - temp.clear(); - aggAdjacency[aggB].clear(); - - if (fillSpot) { - // Finding an aggregate to shift into the empty spot - if (aggB == aggMap.size() - 1) { - aggMap.pop_back(); - aggAdjacency.pop_back(); - } - else { - // Move the last aggregate to fill - int aggToMove = aggMap.size() - 1; - - // Swap out the node list - aggMap[aggB].swap(aggMap[aggToMove]); - aggMap.pop_back(); - - // Mark nodes in aggregation - for (int nIt = 0; nIt < aggMap[aggB].size(); nIt++) - aggregation[aggMap[aggB][nIt]] = aggB; - - // Swap out the adjacency list - aggAdjacency[aggB].swap(aggAdjacency[aggToMove]); - aggAdjacency.pop_back(); - - // Fix neighbor's adjacency lists - for (int nIt = 0; nIt < aggAdjacency[aggB].size(); nIt++) { - // The old Id has to be last in the list - int neighborAgg = aggAdjacency[aggB][nIt]; - aggAdjacency[neighborAgg].back() = aggB; - sort(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end()); - } - - partSizes[aggB] = partSizes[aggToMove]; - if (nodeWeights.size() > 0) - weightedSizes[aggB] = weightedSizes[aggToMove]; - } - // Resize the sizes arrays - partSizes.pop_back(); - if (nodeWeights.size() > 0) - weightedSizes.pop_back(); - } - ValidateArraySizes("At end of MergeAggregates"); - return aggA; + // Resize the sizes arrays + partSizes.pop_back(); + if (nodeWeights.size() > 0) + weightedSizes.pop_back(); + } + ValidateArraySizes("At end of MergeAggregates"); + return aggA; + } + void MergeSplitConditionerCPU::MakeSplitsDirect(bool force) { + if (verbose) { + printf("Beginning MakeSplitsDirect\n"); + } + + // Get the appropriate sizes + AggMIS::Types::IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; + + // For every aggregate see if it should split + int aggId = 0; + while (aggId < aggAdjacency.size()) { + // Getting size of current aggregate + int currentSize = sizes[aggId]; + + if (verbose) { + printf("Checking if aggregate %d of size %d should split\n", + aggId, currentSize); + } - void MergeSplitConditionerCPU::MakeSplitsDirect(bool force) { - if (verbose) { - printf("Beginning MakeSplitsDirect\n"); - } - - // Get the appropriate sizes - IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; - - // For every aggregate see if it should split - int aggId = 0; - while (aggId < aggAdjacency.size()) { - // Getting size of current aggregate - int currentSize = sizes[aggId]; - - if (verbose) { - printf("Checking if aggregate %d of size %d should split\n", - aggId, currentSize); - - } - - // If aggregate too big split - if (currentSize > maxSize && (currentSize > minSize * 2 || force)) { - if (verbose) { - printf("Aggregate %d of size %d is being split.\n", - aggId, sizes[aggId]); - } - - // Creating empty entry for new aggregate - partSizes.resize(partSizes.size() + 1, 0); - if (nodeWeights.size() > 0) - weightedSizes.resize(weightedSizes.size() + 1, 0); - aggMap.resize(aggMap.size() + 1); - aggAdjacency.resize(aggAdjacency.size() + 1); - - SplitAggregate(aggId, aggMap.size() - 1); - splits++; - - if (verbose) { - printf("Split into aggregate %d of size %d and %d of size %d\n", - aggId, sizes[aggId], aggMap.size() -1, sizes.back()); - } - } - aggId++; - } + + // If aggregate too big split + if (currentSize > maxSize && (currentSize > minSize * 2 || force)) { + if (verbose) { + printf("Aggregate %d of size %d is being split.\n", + aggId, sizes[aggId]); + } + + // Creating empty entry for new aggregate + partSizes.resize(partSizes.size() + 1, 0); + if (nodeWeights.size() > 0) + weightedSizes.resize(weightedSizes.size() + 1, 0); + aggMap.resize(aggMap.size() + 1); + aggAdjacency.resize(aggAdjacency.size() + 1); + + SplitAggregate(aggId, aggMap.size() - 1); + splits++; + + if (verbose) { + printf("Split into aggregate %d of size %d and %d of size %d\n", + aggId, sizes[aggId], aggMap.size() - 1, sizes.back()); + } } - void MergeSplitConditionerCPU::SplitAggregate(int agg, int newAgg) { + aggId++; + } + } + void MergeSplitConditionerCPU::SplitAggregate(int agg, int newAgg) { + if (verbose) { + printf("SplitAggregate called to split aggregate %d into %d and %d\n", + agg, agg, newAgg); + std::stringstream s1; + s1 << "Node list of aggregate " << agg; + AggMIS::Types::Display::Print(aggMap[agg], s1.str()); + } + + if (agg == newAgg) { + printf("Problem! SplitAggregate called with agg=%d and newAgg=%d\n", + agg, newAgg); + int t; + std::cin >> t; + } + + UnlinkAggregate(agg); + + // Getting the graph of the aggregate + std::vector > *am = Aggregation::GetAggregateGraph(*graph, aggMap[agg]); + std::vector > &aggGraph = *am; + + // Getting the node weights if needed + AggMIS::Types::IntVector_h weights; + if (nodeWeights.size() > 0) { + weights.resize(aggMap[agg].size()); + for (int i = 0; i < weights.size(); i++) + weights[i] = nodeWeights[aggMap[agg][i]]; + } + + // Finding the root points: + int rootA = Aggregation::FindFarthestNode(aggGraph, 0); + int rootB = Aggregation::FindFarthestNode(aggGraph, rootA); + + // Keep track of the allocated nodes + std::vector allocated(aggGraph.size(), -1); + + // Storing the Id's of the aggregates + std::vector aggIds; + aggIds.push_back(agg); + aggIds.push_back(newAgg); + + // Queues of possible candidates + std::vector > filler(2); + filler[0].push(rootA); + filler[1].push(rootB); + + // Nodelists for each aggregate + std::vector > nodeLists(2); + + // Sizes of each aggregate + std::vector aggSizes(2, 0); + + // Count of allocated nodes + int done = 0; + + // 0 or 1 for which aggregate is looking to allocate + int activeAgg = 0; + int inactiveAgg = 1; + + while (done < aggGraph.size()) { + // Check if there is any possibilities + if (!filler[activeAgg].empty()) { + // Checking the next candidate on the queue + int node = filler[activeAgg].front(); + filler[activeAgg].pop(); + + // If node is not allocated take it + if (allocated[node] == -1) { + // Mark node as allocated + allocated[node] = 1; + // Add to activeAgg's nodelist + nodeLists[activeAgg].push_back(aggMap[agg][node]); + // Mark in aggregation + aggregation[aggMap[agg][node]] = aggIds[activeAgg]; + // Increment count of done nodes + done++; + if (verbose) { - printf("SplitAggregate called to split aggregate %d into %d and %d\n", - agg, agg, newAgg); - stringstream s1; - s1 << "Node list of aggregate " << agg; - Display::Print(aggMap[agg], s1.str()); - } - - if (agg == newAgg) { - printf("Problem! SplitAggregate called with agg=%d and newAgg=%d\n", - agg, newAgg); - int t; - cin >> t; + printf("Allocated local node %d global node %d to %d. Now %d nodes are done\n", + node, aggMap[agg][node], aggIds[activeAgg], done); } - - UnlinkAggregate(agg); - - // Getting the graph of the aggregate - vector > *am = Aggregation::GetAggregateGraph(*graph, aggMap[agg]); - vector > &aggGraph = *am; - - // Getting the node weights if needed - IntVector_h weights; - if (nodeWeights.size() > 0) { - weights.resize(aggMap[agg].size()); - for (int i = 0; i < weights.size(); i++) - weights[i] = nodeWeights[aggMap[agg][i]]; - } - - // Finding the root points: - int rootA = Aggregation::FindFarthestNode(aggGraph, 0); - int rootB = Aggregation::FindFarthestNode(aggGraph, rootA); - - // Keep track of the allocated nodes - vector allocated(aggGraph.size(), -1); - - // Storing the Id's of the aggregates - vector aggIds; - aggIds.push_back(agg); - aggIds.push_back(newAgg); - - // Queues of possible candidates - vector > filler(2); - filler[0].push(rootA); - filler[1].push(rootB); - - // Nodelists for each aggregate - vector > nodeLists(2); - - // Sizes of each aggregate - vector aggSizes(2,0); - - // Count of allocated nodes - int done = 0; - - // 0 or 1 for which aggregate is looking to allocate - int activeAgg = 0; - int inactiveAgg = 1; - - while (done < aggGraph.size()) { - // Check if there is any possibilities - if (!filler[activeAgg].empty()) { - // Checking the next candidate on the queue - int node = filler[activeAgg].front(); - filler[activeAgg].pop(); - - // If node is not allocated take it - if (allocated[node] == -1) { - // Mark node as allocated - allocated[node] = 1; - // Add to activeAgg's nodelist - nodeLists[activeAgg].push_back(aggMap[agg][node]); - // Mark in aggregation - aggregation[aggMap[agg][node]] = aggIds[activeAgg]; - // Increment count of done nodes - done++; - - if (verbose) { - printf("Allocated local node %d global node %d to %d. Now %d nodes are done\n", - node, aggMap[agg][node], aggIds[activeAgg], done); - } - - // Increment size - if (weights.size() > 0) - aggSizes[activeAgg] += weights[node]; - else - aggSizes[activeAgg]++; - - // Add unallocated neighbors to queue - for (int nIt = 0; nIt < aggGraph[node].size(); nIt++) { - int neighbor = aggGraph[node][nIt]; - if (allocated[neighbor] == -1) - filler[activeAgg].push(neighbor); - } - // Check to see if activeAgg should change - if (aggSizes[activeAgg] > aggSizes[inactiveAgg] - && !filler[inactiveAgg].empty()) { - activeAgg = (activeAgg + 1) % 2; - inactiveAgg = (inactiveAgg + 1) % 2; - } - } - } - else { - activeAgg = (activeAgg + 1) % 2; - inactiveAgg = (inactiveAgg + 1) % 2; - } - } - - // Sort the generated nodelists - sort(nodeLists[0].begin(), nodeLists[0].end()); - sort(nodeLists[1].begin(), nodeLists[1].end()); - - // Swap the generated nodelists into the aggMap - nodeLists[0].swap(aggMap[agg]); - nodeLists[1].swap(aggMap[newAgg]); - - if (verbose) { - stringstream s2; - s2 << "AggMap for " << agg; - Display::Print(aggMap[agg], s2.str()); - stringstream s3; - s3 << "AggMap for " << newAgg; - Display::Print(aggMap[newAgg], s3.str()); - } - - // Link in the split aggregates - LinkAggregate(agg); - LinkAggregate(newAgg); - - // Fix sizes - FixSizesFromAggMap(agg); - FixSizesFromAggMap(newAgg); - - // Clean up temp stuff - delete am; - ValidateArraySizes("At end of SplitAggregate"); - } - void MergeSplitConditionerCPU::MakeMergeSplits(int desiredSize) { - // Get the appropriate sizes - IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; - - // For every aggregate see if it should merge-split - int aggId = 0; - while (aggId < aggAdjacency.size()) { - // Getting size of current aggregate - int currentSize = sizes[aggId]; - - // Tracking the best seen merge - int bestMerge = -1; - int smallestDifference = INT_MAX; - - // If aggregate too small or too big check for merge splits: - if (currentSize < minSize || currentSize > maxSize) { - // Look at neighboring aggregates - for (int nIt = 0; nIt < aggAdjacency[aggId].size(); nIt++) { - int neighborAgg = aggAdjacency[aggId][nIt]; - int neighborSize = sizes[neighborAgg]; - int mergedSize = currentSize + neighborSize; - int difference = mergedSize > (desiredSize * 2) ? - mergedSize - (desiredSize * 2) : - (desiredSize * 2) - mergedSize; - if (mergedSize >= (minSize * 2) && mergedSize <= (maxSize * 2)) { - if (difference < smallestDifference) { - smallestDifference = difference; - bestMerge = neighborAgg; - } - } - } - if (bestMerge != -1) { - if (verbose) { - printf("Aggregate %d of size %d found neighbor %d of size %d to merge-split with.\n", - aggId, currentSize, bestMerge, sizes[bestMerge]); - } - - // Merging the aggregates and then splitting back into - // the same two ID's - int lowId = MergeAggregates(aggId, bestMerge, false); - if (lowId == aggId) - SplitAggregate(aggId, bestMerge); - else - SplitAggregate(bestMerge, aggId); - - if (verbose) { - printf("After merge-split aggregate %d has size %d and aggregate %d has size %d\n", - aggId, sizes[aggId], bestMerge, sizes[bestMerge]); - } - ValidateArraySizes("After doing a merge-split"); - mergeSplits++; - } - else { - if (verbose) { - printf("No merge-split found for aggregate %d of size %d\n", - aggId, currentSize); - } - } - } - aggId++; - } - } - void MergeSplitConditionerCPU::UnlinkAggregate(int aggId) { - // Remove aggId from neighbors adjacency lists - for (int i = 0; i < aggAdjacency[aggId].size(); i++) { - int neighborAgg = aggAdjacency[aggId][i]; - remove(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end(), - aggId); - aggAdjacency[neighborAgg].pop_back(); + // Increment size + if (weights.size() > 0) + aggSizes[activeAgg] += weights[node]; + else + aggSizes[activeAgg]++; + + // Add unallocated neighbors to queue + for (int nIt = 0; nIt < aggGraph[node].size(); nIt++) { + int neighbor = aggGraph[node][nIt]; + if (allocated[neighbor] == -1) + filler[activeAgg].push(neighbor); } - - // Clear adjacency for aggId - aggAdjacency[aggId].clear(); - ValidateArraySizes("At end of UnlinkAggregate"); - } - void MergeSplitConditionerCPU::FixSizesFromAggMap(int aggId) { - partSizes[aggId] = aggMap[aggId].size(); - if (nodeWeights.size() > 0) { - int weight = 0; - for (int i = 0; i < aggMap[aggId].size(); i++) - weight += nodeWeights[aggMap[aggId][i]]; - weightedSizes[aggId] = weight; + // Check to see if activeAgg should change + if (aggSizes[activeAgg] > aggSizes[inactiveAgg] + && !filler[inactiveAgg].empty()) { + activeAgg = (activeAgg + 1) % 2; + inactiveAgg = (inactiveAgg + 1) % 2; } - ValidateArraySizes("At end of FixSizesFromAggMap"); + } + } else { + activeAgg = (activeAgg + 1) % 2; + inactiveAgg = (inactiveAgg + 1) % 2; } - void MergeSplitConditionerCPU::LinkAggregate(int aggId) { - // Check aggregate of all neighbors of nodes in aggId - for (int i = 0; i < aggMap[aggId].size(); i++) { - int node = aggMap[aggId][i]; - for (int* nIt = graph->nStart(node); - nIt != graph->nEnd(node); - nIt++) { - int neighborAgg = aggregation[*nIt]; - if (neighborAgg != aggId) { - aggAdjacency[aggId].push_back(neighborAgg); - - // Insert aggId into neighbor's adjacency if needed - if (!binary_search(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end(), - aggId)) { - aggAdjacency[neighborAgg].push_back(aggId); - sort(aggAdjacency[neighborAgg].begin(), - aggAdjacency[neighborAgg].end()); - } - } - } + } + + // Sort the generated nodelists + sort(nodeLists[0].begin(), nodeLists[0].end()); + sort(nodeLists[1].begin(), nodeLists[1].end()); + + // Swap the generated nodelists into the aggMap + nodeLists[0].swap(aggMap[agg]); + nodeLists[1].swap(aggMap[newAgg]); + + if (verbose) { + std::stringstream s2; + s2 << "AggMap for " << agg; + AggMIS::Types::Display::Print(aggMap[agg], s2.str()); + + std::stringstream s3; + s3 << "AggMap for " << newAgg; + AggMIS::Types::Display::Print(aggMap[newAgg], s3.str()); + } + + // Link in the split aggregates + LinkAggregate(agg); + LinkAggregate(newAgg); + + // Fix sizes + FixSizesFromAggMap(agg); + FixSizesFromAggMap(newAgg); + + // Clean up temp stuff + delete am; + ValidateArraySizes("At end of SplitAggregate"); + } + void MergeSplitConditionerCPU::MakeMergeSplits(int desiredSize) { + // Get the appropriate sizes + AggMIS::Types::IntVector_h &sizes = nodeWeights.size() > 0 ? weightedSizes : partSizes; + + // For every aggregate see if it should merge-split + int aggId = 0; + while (aggId < aggAdjacency.size()) { + // Getting size of current aggregate + int currentSize = sizes[aggId]; + + // Tracking the best seen merge + int bestMerge = -1; + int smallestDifference = INT_MAX; + + // If aggregate too small or too big check for merge splits: + if (currentSize < minSize || currentSize > maxSize) { + // Look at neighboring aggregates + for (int nIt = 0; nIt < aggAdjacency[aggId].size(); nIt++) { + int neighborAgg = aggAdjacency[aggId][nIt]; + int neighborSize = sizes[neighborAgg]; + int mergedSize = currentSize + neighborSize; + int difference = mergedSize > (desiredSize * 2) ? + mergedSize - (desiredSize * 2) : + (desiredSize * 2) - mergedSize; + if (mergedSize >= (minSize * 2) && mergedSize <= (maxSize * 2)) { + if (difference < smallestDifference) { + smallestDifference = difference; + bestMerge = neighborAgg; + } } - - // Sort and remove duplicates - sort(aggAdjacency[aggId].begin(), aggAdjacency[aggId].end()); - vector::iterator newEnd = unique(aggAdjacency[aggId].begin(), - aggAdjacency[aggId].end()); - aggAdjacency[aggId].resize(newEnd - aggAdjacency[aggId].begin()); - ValidateArraySizes("At end of LinkAggregate"); - } - void MergeSplitConditionerCPU::FillAggAdjacency() { - // Clearing anything there out first - for (int i = 0; i < aggAdjacency.size(); i++) - aggAdjacency[i].clear(); - aggAdjacency.clear(); - - // Going through the aggregation vector to fill - for (int node = 0; node < graph->Size(); node++) { - int startAgg = aggregation[node]; - for (int *nIt = graph->nStart(node); nIt != graph->nEnd(node); nIt++) { - int endAgg = aggregation[*nIt]; - - // If this is an edge between two aggregates add to - // the induced graph. - if (startAgg != endAgg && startAgg < endAgg) { - // Making sure that there are entries in temp - if (endAgg >= aggAdjacency.size()) - aggAdjacency.resize(endAgg + 1); - - // Adding edge entries - if (aggAdjacency[startAgg].size() == 0 || - !(std::binary_search(aggAdjacency[startAgg].begin(), - aggAdjacency[startAgg].end(), - endAgg))) { - aggAdjacency[startAgg].push_back(endAgg); - std::sort(aggAdjacency[startAgg].begin(), - aggAdjacency[startAgg].end()); - } - if (aggAdjacency[endAgg].size() == 0 || - !(std::binary_search(aggAdjacency[endAgg].begin(), - aggAdjacency[endAgg].end(), - startAgg))) { - aggAdjacency[endAgg].push_back(startAgg); - std::sort(aggAdjacency[endAgg].begin(), - aggAdjacency[endAgg].end()); - } - } - } - } - } - void MergeSplitConditionerCPU::FillAggMap() { - // Clearing anything there out first - for (int i = 0; i < aggMap.size(); i++) - aggMap[i].clear(); - aggMap.clear(); - - // Going through the aggregation vector to fill - for (int node = 0; node < graph->Size(); node++) { - int aggId = aggregation[node]; - if (aggMap.size() <= aggId) - aggMap.resize(aggId + 1); - aggMap[aggId].push_back(node); + } + if (bestMerge != -1) { + if (verbose) { + printf("Aggregate %d of size %d found neighbor %d of size %d to merge-split with.\n", + aggId, currentSize, bestMerge, sizes[bestMerge]); } - // Make sure each map is sorted - for (int i = 0; i < aggMap.size(); i++) - sort(aggMap[i].begin(), aggMap[i].end()); - } - void MergeSplitConditionerCPU::ValidateAggAdjacency() { - // Move current into new spot - vector > temp(aggAdjacency.size()); - for (int i = 0; i < temp.size(); i++) - temp[i].swap(aggAdjacency[i]); - - // Regenerate member - FillAggAdjacency(); - - // Compare - if (Compare::AreEqual(temp, aggAdjacency, true)) - printf("AggAdjacency validated.\n"); - else { - printf("Failed to validate AggAdjacency.\n"); - int t; - cin >> t; + // Merging the aggregates and then splitting back into + // the same two ID's + int lowId = MergeAggregates(aggId, bestMerge, false); + if (lowId == aggId) + SplitAggregate(aggId, bestMerge); + else + SplitAggregate(bestMerge, aggId); + + if (verbose) { + printf("After merge-split aggregate %d has size %d and aggregate %d has size %d\n", + aggId, sizes[aggId], bestMerge, sizes[bestMerge]); } - for (int i = 0; i < temp.size(); i++) - temp[i].clear(); - } - void MergeSplitConditionerCPU::ValidateAggMap() { - // Move current into new spot - vector > temp(aggMap.size()); - for (int i = 0; i < temp.size(); i++) - temp[i].swap(aggMap[i]); - - // Regenerate member - FillAggMap(); - - // Compare - if (Compare::AreEqual(temp, aggMap, true)) - printf("AggMap validated.\n"); - else { - printf("Failed to validate AggMap.\n"); - int t; - cin >> t; + ValidateArraySizes("After doing a merge-split"); + mergeSplits++; + } else { + if (verbose) { + printf("No merge-split found for aggregate %d of size %d\n", + aggId, currentSize); } - for (int i = 0; i < temp.size(); i++) - temp[i].clear(); + } } - void MergeSplitConditionerCPU::ValidatePartSizes() { - bool failed = false; - IntVector_h *ps = Aggregation::GetPartSizes(aggregation); - if (Compare::AreEqual(*ps, partSizes, true)) - printf("PartSizes validates.\n"); - else { - printf("PartSizes does not validate.\n"); - failed = true; + aggId++; + } + } + void MergeSplitConditionerCPU::UnlinkAggregate(int aggId) { + // Remove aggId from neighbors adjacency lists + for (int i = 0; i < aggAdjacency[aggId].size(); i++) { + int neighborAgg = aggAdjacency[aggId][i]; + remove(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end(), + aggId); + aggAdjacency[neighborAgg].pop_back(); + } + + // Clear adjacency for aggId + aggAdjacency[aggId].clear(); + ValidateArraySizes("At end of UnlinkAggregate"); + } + void MergeSplitConditionerCPU::FixSizesFromAggMap(int aggId) { + partSizes[aggId] = aggMap[aggId].size(); + if (nodeWeights.size() > 0) { + int weight = 0; + for (int i = 0; i < aggMap[aggId].size(); i++) + weight += nodeWeights[aggMap[aggId][i]]; + weightedSizes[aggId] = weight; + } + ValidateArraySizes("At end of FixSizesFromAggMap"); + } + void MergeSplitConditionerCPU::LinkAggregate(int aggId) { + // Check aggregate of all neighbors of nodes in aggId + for (int i = 0; i < aggMap[aggId].size(); i++) { + int node = aggMap[aggId][i]; + for (int* nIt = graph->nStart(node); + nIt != graph->nEnd(node); + nIt++) { + int neighborAgg = aggregation[*nIt]; + if (neighborAgg != aggId) { + aggAdjacency[aggId].push_back(neighborAgg); + + // Insert aggId into neighbor's adjacency if needed + if (!binary_search(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end(), + aggId)) { + aggAdjacency[neighborAgg].push_back(aggId); + sort(aggAdjacency[neighborAgg].begin(), + aggAdjacency[neighborAgg].end()); } - if (nodeWeights.size() > 0) { - IntVector_h* ws = Aggregation::GetPartSizes(aggregation, nodeWeights); - if (Compare::AreEqual(*ws, weightedSizes, true)) - printf("WeightedSizes validates.\n"); - else { - printf("WeightedSizes does not validate.\n"); - failed = true; - } + } + } + } + + // Sort and remove duplicates + sort(aggAdjacency[aggId].begin(), aggAdjacency[aggId].end()); + std::vector::iterator newEnd = unique(aggAdjacency[aggId].begin(), + aggAdjacency[aggId].end()); + aggAdjacency[aggId].resize(newEnd - aggAdjacency[aggId].begin()); + ValidateArraySizes("At end of LinkAggregate"); + } + void MergeSplitConditionerCPU::FillAggAdjacency() { + // Clearing anything there out first + for (int i = 0; i < aggAdjacency.size(); i++) + aggAdjacency[i].clear(); + aggAdjacency.clear(); + + // Going through the aggregation vector to fill + for (int node = 0; node < graph->Size(); node++) { + int startAgg = aggregation[node]; + for (int *nIt = graph->nStart(node); nIt != graph->nEnd(node); nIt++) { + int endAgg = aggregation[*nIt]; + + // If this is an edge between two aggregates add to + // the induced graph. + if (startAgg != endAgg && startAgg < endAgg) { + // Making sure that there are entries in temp + if (endAgg >= aggAdjacency.size()) + aggAdjacency.resize(endAgg + 1); + + // Adding edge entries + if (aggAdjacency[startAgg].size() == 0 || + !(std::binary_search(aggAdjacency[startAgg].begin(), + aggAdjacency[startAgg].end(), + endAgg))) { + aggAdjacency[startAgg].push_back(endAgg); + std::sort(aggAdjacency[startAgg].begin(), + aggAdjacency[startAgg].end()); } - if (failed) { - int d; - cin >> d; + if (aggAdjacency[endAgg].size() == 0 || + !(std::binary_search(aggAdjacency[endAgg].begin(), + aggAdjacency[endAgg].end(), + startAgg))) { + aggAdjacency[endAgg].push_back(startAgg); + std::sort(aggAdjacency[endAgg].begin(), + aggAdjacency[endAgg].end()); } + } } - void MergeSplitConditionerCPU::ValidateArraySizes(string message) { - bool error = nodeWeights.size() > 0 ? - aggAdjacency.size() != aggMap.size() || - aggMap.size() != partSizes.size() || - partSizes.size() != weightedSizes.size() : - aggAdjacency.size() != aggMap.size() || - aggMap.size() != partSizes.size(); - if (error) { - printf("Error with array sizes! %s\n", message.c_str()); - printf("\taggAdjacency.size()=%d aggMap.size()=%d partSizes.size()=%d weightedSizes.size()=%d\n", - aggAdjacency.size(), aggMap.size(), partSizes.size(), weightedSizes.size()); - int t; - cin >> t; - } + } + } + void MergeSplitConditionerCPU::FillAggMap() { + // Clearing anything there out first + for (int i = 0; i < aggMap.size(); i++) + aggMap[i].clear(); + aggMap.clear(); + + // Going through the aggregation vector to fill + for (int node = 0; node < graph->Size(); node++) { + int aggId = aggregation[node]; + if (aggMap.size() <= aggId) + aggMap.resize(aggId + 1); + aggMap[aggId].push_back(node); + } + + // Make sure each map is sorted + for (int i = 0; i < aggMap.size(); i++) + sort(aggMap[i].begin(), aggMap[i].end()); + } + void MergeSplitConditionerCPU::ValidateAggAdjacency() { + // Move current into new spot + std::vector > temp(aggAdjacency.size()); + for (int i = 0; i < temp.size(); i++) + temp[i].swap(aggAdjacency[i]); + + // Regenerate member + FillAggAdjacency(); + + // Compare + if (AggMIS::Types::Compare::AreEqual(temp, aggAdjacency, true)) + printf("AggAdjacency validated.\n"); + else { + printf("Failed to validate AggAdjacency.\n"); + int t; + std::cin >> t; + } + for (int i = 0; i < temp.size(); i++) + temp[i].clear(); + } + void MergeSplitConditionerCPU::ValidateAggMap() { + // Move current into new spot + std::vector > temp(aggMap.size()); + for (int i = 0; i < temp.size(); i++) + temp[i].swap(aggMap[i]); + + // Regenerate member + FillAggMap(); + + // Compare + if (AggMIS::Types::Compare::AreEqual(temp, aggMap, true)) + printf("AggMap validated.\n"); + else { + printf("Failed to validate AggMap.\n"); + int t; + std::cin >> t; + } + for (int i = 0; i < temp.size(); i++) + temp[i].clear(); + } + void MergeSplitConditionerCPU::ValidatePartSizes() { + bool failed = false; + AggMIS::Types::IntVector_h *ps = Aggregation::GetPartSizes(aggregation); + if (AggMIS::Types::Compare::AreEqual(*ps, partSizes, true)) + printf("PartSizes validates.\n"); + else { + printf("PartSizes does not validate.\n"); + failed = true; + } + if (nodeWeights.size() > 0) { + AggMIS::Types::IntVector_h* ws = Aggregation::GetPartSizes(aggregation, nodeWeights); + if (AggMIS::Types::Compare::AreEqual(*ws, weightedSizes, true)) + printf("WeightedSizes validates.\n"); + else { + printf("WeightedSizes does not validate.\n"); + failed = true; } + } + if (failed) { + int d; + std::cin >> d; + } + } + void MergeSplitConditionerCPU::ValidateArraySizes(std::string message) { + bool error = nodeWeights.size() > 0 ? + aggAdjacency.size() != aggMap.size() || + aggMap.size() != partSizes.size() || + partSizes.size() != weightedSizes.size() : + aggAdjacency.size() != aggMap.size() || + aggMap.size() != partSizes.size(); + if (error) { + printf("Error with array sizes! %s\n", message.c_str()); + printf("\taggAdjacency.size()=%d aggMap.size()=%d partSizes.size()=%d weightedSizes.size()=%d\n", + aggAdjacency.size(), aggMap.size(), partSizes.size(), weightedSizes.size()); + int t; + std::cin >> t; + } } + } } diff --git a/src/core/aggmis/cuda/TriMesh_connectivity.cu b/src/core/aggmis/cuda/TriMesh_connectivity.cu index e052b80..0482247 100644 --- a/src/core/aggmis/cuda/TriMesh_connectivity.cu +++ b/src/core/aggmis/cuda/TriMesh_connectivity.cu @@ -10,7 +10,6 @@ #include #include "TriMesh.h" #include -using std::find; void TriMesh::need_meshquality() { @@ -102,7 +101,7 @@ void TriMesh::need_neighbors() printf("Finding vertex neighbors... "); int nv = vertices.size(), nf = faces.size(); - vector numneighbors(nv); + std::vector numneighbors(nv); for (int i = 0; i < nf; i++) { numneighbors[faces[i][0]]++; numneighbors[faces[i][1]]++; @@ -115,12 +114,12 @@ void TriMesh::need_neighbors() for (int i = 0; i < nf; i++) { for (int j = 0; j < 3; j++) { - vector &me = neighbors[faces[i][j]]; + std::vector &me = neighbors[faces[i][j]]; int n1 = faces[i][(j+1)%3]; int n2 = faces[i][(j+2)%3]; - if (find(me.begin(), me.end(), n1) == me.end()) + if (std::find(me.begin(), me.end(), n1) == me.end()) me.push_back(n1); - if (find(me.begin(), me.end(), n2) == me.end()) + if (std::find(me.begin(), me.end(), n2) == me.end()) me.push_back(n2); } } @@ -216,7 +215,7 @@ void TriMesh::need_adjacentfaces() printf("Finding vertex to triangle maps... "); int nv = vertices.size(), nf = faces.size(); - vector numadjacentfaces(nv); + std::vector numadjacentfaces(nv); for (int i = 0; i < nf; i++) { numadjacentfaces[faces[i][0]]++; numadjacentfaces[faces[i][1]]++; @@ -254,14 +253,14 @@ void TriMesh::need_across_edge() continue; int v1 = faces[i][(j+1)%3]; int v2 = faces[i][(j+2)%3]; - const vector &a1 = adjacentfaces[v1]; - const vector &a2 = adjacentfaces[v2]; + const std::vector &a1 = adjacentfaces[v1]; + const std::vector &a2 = adjacentfaces[v2]; for (int k1 = 0; k1 < a1.size(); k1++) { int other = a1[k1]; if (other == i) continue; - vector::const_iterator it = - find(a2.begin(), a2.end(), other); + std::vector::const_iterator it = + std::find(a2.begin(), a2.end(), other); if (it == a2.end()) continue; int ind = (faces[other].indexof(v1)+1)%3; diff --git a/src/core/aggmis/cuda/TriMesh_io.cu b/src/core/aggmis/cuda/TriMesh_io.cu index 569a222..2ab87a5 100644 --- a/src/core/aggmis/cuda/TriMesh_io.cu +++ b/src/core/aggmis/cuda/TriMesh_io.cu @@ -58,8 +58,8 @@ static bool we_are_little_endian(); static void check_need_swap(const point &p, bool &need_swap); static void check_ind_range(TriMesh *mesh); static void skip_comments(FILE *f); -static void tess(const vector &verts, const vector &thisface, - vector &tris); +static void tess(const std::vector &verts, const std::vector &thisface, + std::vector &tris); static void write_ply_ascii(TriMesh *mesh, FILE *f, bool write_norm, bool float_color); @@ -111,10 +111,10 @@ static inline void swap_double(double &x) { unsigned char buf[8]; memcpy(buf, &x, 8); - swap(buf[0], buf[7]); - swap(buf[1], buf[6]); - swap(buf[2], buf[5]); - swap(buf[3], buf[4]); + std::swap(buf[0], buf[7]); + std::swap(buf[1], buf[6]); + std::swap(buf[2], buf[5]); + std::swap(buf[3], buf[4]); memcpy(&x, buf, 8); } @@ -650,7 +650,7 @@ static bool read_ray(FILE *f, TriMesh *mesh) // Read an obj file static bool read_obj(FILE *f, TriMesh *mesh) { - vector thisface; + std::vector thisface; while (1) { skip_comments(f); if (feof(f)) @@ -935,8 +935,8 @@ static bool read_faces_bin(FILE *f, TriMesh *mesh, bool need_swap, // potentially variable-length int face_skip = face_len - face_idx; - vector buf(max(face_idx, face_skip)); - vector thisface; + std::vector buf(max(face_idx, face_skip)); + std::vector thisface; for (int i = 0; i < nfaces; i++) { COND_READ(face_idx > 0, buf[0], face_idx); @@ -982,7 +982,7 @@ static bool read_faces_asc(FILE *f, TriMesh *mesh, int nfaces, char buf[1024]; skip_comments(f); TriMesh::dprintf("\n Reading %d faces... ", nfaces); - vector thisface; + std::vector thisface; for (int i = 0; i < nfaces; i++) { thisface.clear(); int this_face_count = 3; @@ -1236,8 +1236,8 @@ static void skip_comments(FILE *f) // Tesselate an arbitrary n-gon. Appends triangles to "tris". -static void tess(const vector &verts, const vector &thisface, - vector &tris) +static void tess(const std::vector &verts, const std::vector &thisface, + std::vector &tris) { if (thisface.size() < 3) return; diff --git a/src/core/aggmis/include/AggMIS_Aggregation_CPU.h b/src/core/aggmis/include/AggMIS_Aggregation_CPU.h index e0248f8..33fba50 100644 --- a/src/core/aggmis/include/AggMIS_Aggregation_CPU.h +++ b/src/core/aggmis/include/AggMIS_Aggregation_CPU.h @@ -1,4 +1,4 @@ -/* +/* * File: AggMIS_Aggregation_CPU.h * Author: T. James Lewis * @@ -14,100 +14,98 @@ #include namespace AggMIS { - namespace Aggregation { - using namespace Types; - using namespace std; - /** - * This method returns an aggregation where each node in the graph is - * assigned to the nearest root point. - * @param graph The graph being aggregated - * @param roots The root points for the aggregation - * @return An array where return[i] is the ID of the aggregate to which - * node i is assigned. - */ - IntVector_h* AggregateToNearest(Graph_h &graph, - IntVector_h &roots); - /** - * This method checks if the given aggregation is valid. - * @param graph The graph that was aggregated. - * @param aggregation The aggregation array to check - * @param verbose If true, more output will be printed. - * @return True if aggregation is valid, False otherwise. - */ - bool IsValidAggregation(Graph_h &graph, - IntVector_h &aggregation, - bool verbose); - /** - * This method returns an array where each element is the count of - * nodes in the corresponding aggregate. - * @param aggregation The aggregation array. - * @return An array giving the size of each aggregate. - */ - IntVector_h* GetPartSizes(IntVector_h &aggregation); - /** - * This method returns an array where each element is the sum of the - * weights of all nodes in the corresponding aggregate. - * @param aggregation The aggregation array. - * @param nodeWeights The weights of each node. - * @return An array giving the total weight of each aggregate. - */ - IntVector_h* GetPartSizes(IntVector_h &aggregation, - IntVector_h &nodeWeights); - /** - * This method returns a sub-graph of the input graph with only nodes - * contained in nodeList, and only edges between nodes both contained - * in nodeList. - * @param graph The graph to get sub-graph of. - * @param nodeList The list of nodes defining the subgraph - * @return A graph where return[i][j] is the ID of the j'th neighbor - * of the i'th node of the graph. - */ - vector >* GetAggregateGraph(Graph_h &graph, - vector &nodeList); - /** - * Returns a node in the given graph with maximal path distance from the - * specified start node. - * @param graph The graph. - * @param start The start node. - * @return The ID of a node such that no other node has a higher - * distance to the start node. - */ - int FindFarthestNode(vector > &graph, - int start); - /** - * Marks the distance of all nodes in the given graph from the start - * point. After completion distances[i] will contain the distance from - * node i to the startPoint. - * @param graph The input graph. - * @param distances The array to mark distances in. - * @param startPoint The starting point. - */ - void MarkDistances(vector > &graph, - vector &distances, - int startPoint); - /** - * Marks the distance of all nodes in the given graph from the set of - * nodes specified in startPoints. After completion distances[i] will - * contain the distance from node i to the nearest node in startPoints. - * @param graph - * @param distances - * @param startPoints - */ - void MarkDistances(vector > &graph, - vector &distances, - vector startPoints); - /** - * Returns the set of nodes in the given graph for which the sum of all - * distances from them to all other nodes is minimal. - * @param graph The input graph. - * @return The set of nodes in the given graph for which the sum of all - * distances from them to all other nodes is minimal. - */ - int FindMassScore(vector > &graph, - int startPoint); - vector* GetCentroid(vector > &graph, - int startPoint); - } + namespace Aggregation { + /** + * This method returns an aggregation where each node in the graph is + * assigned to the nearest root point. + * @param graph The graph being aggregated + * @param roots The root points for the aggregation + * @return An array where return[i] is the ID of the aggregate to which + * node i is assigned. + */ + Types::IntVector_h* AggregateToNearest(Types::Graph_h &graph, + Types::IntVector_h &roots); + /** + * This method checks if the given aggregation is valid. + * @param graph The graph that was aggregated. + * @param aggregation The aggregation array to check + * @param verbose If true, more output will be printed. + * @return True if aggregation is valid, False otherwise. + */ + bool IsValidAggregation(Types::Graph_h &graph, + Types::IntVector_h &aggregation, + bool verbose); + /** + * This method returns an array where each element is the count of + * nodes in the corresponding aggregate. + * @param aggregation The aggregation array. + * @return An array giving the size of each aggregate. + */ + Types::IntVector_h* GetPartSizes(Types::IntVector_h &aggregation); + /** + * This method returns an array where each element is the sum of the + * weights of all nodes in the corresponding aggregate. + * @param aggregation The aggregation array. + * @param nodeWeights The weights of each node. + * @return An array giving the total weight of each aggregate. + */ + Types::IntVector_h* GetPartSizes(Types::IntVector_h &aggregation, + Types::IntVector_h &nodeWeights); + /** + * This method returns a sub-graph of the input graph with only nodes + * contained in nodeList, and only edges between nodes both contained + * in nodeList. + * @param graph The graph to get sub-graph of. + * @param nodeList The list of nodes defining the subgraph + * @return A graph where return[i][j] is the ID of the j'th neighbor + * of the i'th node of the graph. + */ + std::vector >* GetAggregateGraph(Types::Graph_h &graph, + std::vector &nodeList); + /** + * Returns a node in the given graph with maximal path distance from the + * specified start node. + * @param graph The graph. + * @param start The start node. + * @return The ID of a node such that no other node has a higher + * distance to the start node. + */ + int FindFarthestNode(std::vector > &graph, + int start); + /** + * Marks the distance of all nodes in the given graph from the start + * point. After completion distances[i] will contain the distance from + * node i to the startPoint. + * @param graph The input graph. + * @param distances The array to mark distances in. + * @param startPoint The starting point. + */ + void MarkDistances(std::vector > &graph, + std::vector &distances, + int startPoint); + /** + * Marks the distance of all nodes in the given graph from the set of + * nodes specified in startPoints. After completion distances[i] will + * contain the distance from node i to the nearest node in startPoints. + * @param graph + * @param distances + * @param startPoints + */ + void MarkDistances(std::vector > &graph, + std::vector &distances, + std::vector startPoints); + /** + * Returns the set of nodes in the given graph for which the sum of all + * distances from them to all other nodes is minimal. + * @param graph The input graph. + * @return The set of nodes in the given graph for which the sum of all + * distances from them to all other nodes is minimal. + */ + int FindMassScore(std::vector > &graph, + int startPoint); + std::vector* GetCentroid(std::vector > &graph, + int startPoint); + } } #endif /* AGGMIS_AGGREGATION_CPU_H */ diff --git a/src/core/aggmis/include/AggMIS_Aggregation_GPU.h b/src/core/aggmis/include/AggMIS_Aggregation_GPU.h index 8c5e6f5..0d0f6a0 100644 --- a/src/core/aggmis/include/AggMIS_Aggregation_GPU.h +++ b/src/core/aggmis/include/AggMIS_Aggregation_GPU.h @@ -1,4 +1,4 @@ -/* +/* * File: AggMIS_Aggregation_GPU.h * Author: T. James Lewis * @@ -12,98 +12,96 @@ #include "thrust/scan.h" #include "thrust/count.h" namespace AggMIS { - namespace Aggregation { - using namespace Types; - using namespace std; - namespace Kernels { - /** - * In this kernel each node checks if it has been allocated - * to an aggregate, if it has not, it checks to see if any - * of its neighbors have been. If they have, it finds the - * aggregate to which more neighbors belong to and assigns - * itself to it. - * @param size The number of nodes in the graph - * @param adjIndexes The adjacency indices of the graph - * @param adjacency The adjacency list of the graph - * @param partIn The aggregation labeling from last cycle - * @param partOut The aggregation labeling being found - * @param aggregated Flags whether node has been aggregated - */ - __global__ void allocateNodesKernel(int size, - int *adjIndexes, - int *adjacency, - int *partIn, - int *partOut, - int *aggregated); - /** - * This kernel does the same flood filling that the allocate - * kernel but only propogates between nodes of the same - * aggregate. Used to verify that an aggregation consists of - * aggregates which are connected components. - * @param size Number of nodes in graph - * @param adjIndices Graph adjacency indices - * @param adjacency Graph adjacency - * @param aggregation Current aggregation - * @param valuesIn The values from last cycle - * @param valuesOut The values to write this cycle - * @param incomplete Flag which indicates whether done - */ - __global__ void checkAggregationFillAggregates(int size, - int *adjIndices, - int *adjacency, - int* aggregation, - int* valuesIn, - int* valuesOut, - int* incomplete); - } - namespace Functors { - /** - * This functor is used to sequentially number elements - * in a vector. Argument a is the element in the labeling - * vector. Argument b is the element in the pre-fixed sum - * vector of the labels. If the element is not labeled it - * returns -1. Otherwise it returns the new label id - */ - struct NumberParts { - __host__ __device__ - int operator()(const int &a, const int &b) const - { - if (b == 0) - return -1; + namespace Aggregation { + namespace Kernels { + /** + * In this kernel each node checks if it has been allocated + * to an aggregate, if it has not, it checks to see if any + * of its neighbors have been. If they have, it finds the + * aggregate to which more neighbors belong to and assigns + * itself to it. + * @param size The number of nodes in the graph + * @param adjIndexes The adjacency indices of the graph + * @param adjacency The adjacency list of the graph + * @param partIn The aggregation labeling from last cycle + * @param partOut The aggregation labeling being found + * @param aggregated Flags whether node has been aggregated + */ + __global__ void allocateNodesKernel(int size, + int *adjIndexes, + int *adjacency, + int *partIn, + int *partOut, + int *aggregated); + /** + * This kernel does the same flood filling that the allocate + * kernel but only propogates between nodes of the same + * aggregate. Used to verify that an aggregation consists of + * aggregates which are connected components. + * @param size Number of nodes in graph + * @param adjIndices Graph adjacency indices + * @param adjacency Graph adjacency + * @param aggregation Current aggregation + * @param valuesIn The values from last cycle + * @param valuesOut The values to write this cycle + * @param incomplete Flag which indicates whether done + */ + __global__ void checkAggregationFillAggregates(int size, + int *adjIndices, + int *adjacency, + int* aggregation, + int* valuesIn, + int* valuesOut, + int* incomplete); + } + namespace Functors { + /** + * This functor is used to sequentially number elements + * in a vector. Argument a is the element in the labeling + * vector. Argument b is the element in the pre-fixed sum + * vector of the labels. If the element is not labeled it + * returns -1. Otherwise it returns the new label id + */ + struct NumberParts { + __host__ __device__ + int operator()(const int &a, const int &b) const + { + if (b == 0) + return -1; - return a - 1; - } - }; + return a - 1; } - /** - * This method allocates each node of the graph to the nearest - * root node using simple path distance and breaking ties by - * adjacency. - * @param graph The input graph to be aggregated - * @param roots The set of initial root points as a vector the size - * of the number of graph nodes, with entries being either 0=non root - * or 1=root - * @return A vector with an entry for each graph node indicating which - * zero indexed aggregate it was allocated to. - */ - IntVector_d* AggregateToNearest(Graph_d &graph, - IntVector_d &roots); - /** - * Checks if the given labeling constitutes a valid aggregation - * of the graph. Checks that the aggregate ID's form an - * uninterrupted sequence starting from zero, and that each - * aggregate is a connected component. - * @param graph The graph - * @param aggregation The node labeling to verify - * @param verbose Prints more info if true - * @return True if valid aggregation false otherwise - */ - bool IsValidAggregation(Graph_d &graph, - IntVector_d &aggregation, - bool verbose); - Graph_d* GetAggregateMap(IntVector_d& aggregation); -// double GetEdgeCutRatio(Graph_d &graph, IntVector_d& aggregation); + }; } + /** + * This method allocates each node of the graph to the nearest + * root node using simple path distance and breaking ties by + * adjacency. + * @param graph The input graph to be aggregated + * @param roots The set of initial root points as a vector the size + * of the number of graph nodes, with entries being either 0=non root + * or 1=root + * @return A vector with an entry for each graph node indicating which + * zero indexed aggregate it was allocated to. + */ + Types::IntVector_d* AggregateToNearest(Types::Graph_d &graph, + Types::IntVector_d &roots); + /** + * Checks if the given labeling constitutes a valid aggregation + * of the graph. Checks that the aggregate ID's form an + * uninterrupted sequence starting from zero, and that each + * aggregate is a connected component. + * @param graph The graph + * @param aggregation The node labeling to verify + * @param verbose Prints more info if true + * @return True if valid aggregation false otherwise + */ + bool IsValidAggregation(Types::Graph_d &graph, + Types::IntVector_d &aggregation, + bool verbose); + Types::Graph_d* GetAggregateMap(Types::IntVector_d& aggregation); + // double GetEdgeCutRatio(Graph_d &graph, IntVector_d& aggregation); + } } #endif /* AGGMIS_AGGREGATION_GPU_H */ diff --git a/src/core/aggmis/include/AggMIS_FileIO.h b/src/core/aggmis/include/AggMIS_FileIO.h index c919d29..919ce8a 100644 --- a/src/core/aggmis/include/AggMIS_FileIO.h +++ b/src/core/aggmis/include/AggMIS_FileIO.h @@ -8,7 +8,7 @@ #ifndef AGGMIS_FILEIO_H #define AGGMIS_FILEIO_H -#include +#include #include #include #include @@ -18,54 +18,51 @@ namespace AggMIS { namespace FileIO { - using namespace AggMIS::Types; - using namespace std; - class DataCollector { public: - DataCollector(string title); - void set(string name, double value); - void set(string name, int value); - void set(string name, string value); - void set(string name, double value, bool keep); - void set(string name, int value, bool keep); - void set(string name, string value, bool keep); + DataCollector(std::string title); + void set(std::string name, double value); + void set(std::string name, int value); + void set(std::string name, std::string value); + void set(std::string name, double value, bool keep); + void set(std::string name, int value, bool keep); + void set(std::string name, std::string value, bool keep); void closeRow(); void blankRow(); - void writeOutCSV(ostream *outputStream); + void writeOutCSV(std::ostream *outputStream); private: - vector > data; + vector > data; vector keeping; - string title; + std::string title; bool dirty; }; // Takes a filename and tries to load a graph from it // by automatically detecting the file type. - Graph_h* GetGraphFromFile_Auto(string filename); + Types::Graph_h* GetGraphFromFile_Auto(std::string filename); // Takes an input stream and reads in a graph in text csr format - Graph_h* GetGraphFromFile_CSR(istream *theInput); + Types::Graph_h* GetGraphFromFile_CSR(std::istream *theInput); // Takes an input stream and reads in a graph in .MSH format - Graph_h* GetGraphFromFile_MSH(istream *theInput); + Types::Graph_h* GetGraphFromFile_MSH(std::istream *theInput); // Takes a filename and loads the graph from a triangular mesh // stored in .ply format using Trimesh library - Graph_h* GetGraphFromFile_TriMesh(string filename); + Types::Graph_h* GetGraphFromFile_TriMesh(std::string filename); // Takes a filename and loads the graph from a tetrahedral mesh // stored in .node/.ele format using the tetmesh library - Graph_h* GetGraphFromFile_TetMesh(string filename); + Types::Graph_h* GetGraphFromFile_TetMesh(std::string filename); // Takes a filename and loads a vector from it - IntVector_h* GetVectorFromFile_BIN(string filename); + Types::IntVector_h* GetVectorFromFile_BIN(std::string filename); // Writes out the graph to the specified file in CSR format - void WriteGraphToFile_CSR(Graph_h graph, string filename); + void WriteGraphToFile_CSR(Types::Graph_h graph, std::string filename); // Writes out vector to the specified file - void WriteVectorToFile_BIN(IntVector_h toWrite, string filename); + void WriteVectorToFile_BIN(Types::IntVector_h toWrite, std::string filename); } } #endif /* AGGMIS_FILEIO_H */ diff --git a/src/core/aggmis/include/AggMIS_GraphHelpers.h b/src/core/aggmis/include/AggMIS_GraphHelpers.h index 2a0c5cd..3d960a9 100644 --- a/src/core/aggmis/include/AggMIS_GraphHelpers.h +++ b/src/core/aggmis/include/AggMIS_GraphHelpers.h @@ -11,8 +11,6 @@ #include namespace AggMIS { namespace GraphHelpers { - using namespace AggMIS::Types; - using namespace std; // GPU Kernels namespace Kernels { @@ -39,37 +37,37 @@ namespace AggMIS { int *accumulatedSize, int *sizes); } - Graph_d* GetInducedGraph(Graph_d &graph, - IntVector_d &aggregation); - Graph_h* GetInducedGraph(Graph_h &graph, - IntVector_h &aggregation); - void mapAdjacencyToBlock(IntVector_d &adjIndexes, - IntVector_d &adjacency, - IntVector_d &adjacencyBlockLabel, - IntVector_d &blockMappedAdjacency, - IntVector_d &fineAggregate); - void getPartIndicesNegStart(IntVector_d& sortedPartition, - IntVector_d& partIndices); + Types::Graph_d* GetInducedGraph(Types::Graph_d &graph, + Types::IntVector_d &aggregation); + Types::Graph_h* GetInducedGraph(Types::Graph_h &graph, + Types::IntVector_h &aggregation); + void mapAdjacencyToBlock(Types::IntVector_d &adjIndexes, + Types::IntVector_d &adjacency, + Types::IntVector_d &adjacencyBlockLabel, + Types::IntVector_d &blockMappedAdjacency, + Types::IntVector_d &fineAggregate); + void getPartIndicesNegStart(Types::IntVector_d& sortedPartition, + Types::IntVector_d& partIndices); /** * Gets a vector where the values are the indices of the elements * @param size Size of vector to create * @return A pointer to newly created vector */ - IntVector_d* GetIndicesVector(int size); + Types::IntVector_d* GetIndicesVector(int size); /** * Writes the index of each vector element as its value * @param size The size the vector should be * @param toSet The vector to set (Overwritten) */ void SetToIndicesVector(int size, - IntVector_d& toSet); + Types::IntVector_d& toSet); /** * Gets the size (count of nodes) of each aggregate. * @param aggregation Labels each node with its aggregate ID * @param sizes Vector to output computed sized (Overwritten) */ - void getPartSizes(IntVector_d &aggregation, - IntVector_d &sizes); + void getPartSizes(Types::IntVector_d &aggregation, + Types::IntVector_d &sizes); /** * Gets the size of each aggregate, taking into account the weight of * each node. @@ -77,16 +75,16 @@ namespace AggMIS { * @param sizes Vector to put the computed sizes into (Overwritten) * @param weights The weights of each graph node */ - void getPartSizes(IntVector_d &aggregation, - IntVector_d &sizes, - IntVector_d &weights); + void getPartSizes(Types::IntVector_d &aggregation, + Types::IntVector_d &sizes, + Types::IntVector_d &weights); /** * Finds the valence of each node in the given graph. * @param graph Input graph * @return A vector containing the valence of each node */ - IntVector_d* GetValences(Graph_d &graph); - IntVector_h* GetValences(Graph_h &graph); + Types::IntVector_d* GetValences(Types::Graph_d &graph); + Types::IntVector_h* GetValences(Types::Graph_h &graph); /** * Checks if a graph is a valid undirected graph. Valid being that each * node listing a node as neighbor is a neighbor of the listed node, and @@ -94,7 +92,7 @@ namespace AggMIS { * @param graph The graph to check * @return True if graph is valid, false otherwise */ - bool IsGraphValid(Graph_d &graph); + bool IsGraphValid(Types::Graph_d &graph); /** * Checks if a graph is a valid undirected graph. Valid being that each * node listing a node as neighbor is a neighbor of the listed node, and @@ -102,7 +100,7 @@ namespace AggMIS { * @param graph The graph to check * @return True if graph is valid, false otherwise */ - bool IsGraphValid(Graph_h &graph); + bool IsGraphValid(Types::Graph_h &graph); /** * Checks if a graph is a valid undirected graph. Valid being that each * node listing a node as neighbor is a neighbor of the listed node, and @@ -111,7 +109,7 @@ namespace AggMIS { * @param adjacency The adjacency list * @return True if graph is valid, false otherwise */ - bool IsGraphValid(IntVector_d &indices, IntVector_d &adjacency); + bool IsGraphValid(Types::IntVector_d &indices, Types::IntVector_d &adjacency); /** * Checks if a graph is a valid undirected graph. Valid being that each * node listing a node as neighbor is a neighbor of the listed node, and @@ -120,7 +118,7 @@ namespace AggMIS { * @param adjacency The adjacency list * @return True if graph is valid, false otherwise */ - bool IsGraphValid(IntVector_h &indices, IntVector_h &adjacency); + bool IsGraphValid(Types::IntVector_h &indices, Types::IntVector_h &adjacency); } } #endif /* AGGMIS_GRAPHHELPERS_H */ diff --git a/src/core/aggmis/include/AggMIS_IOHelpers.h b/src/core/aggmis/include/AggMIS_IOHelpers.h index 6a4f4e6..4803532 100644 --- a/src/core/aggmis/include/AggMIS_IOHelpers.h +++ b/src/core/aggmis/include/AggMIS_IOHelpers.h @@ -14,12 +14,10 @@ #include namespace AggMIS { - namespace InputHelpers { - using namespace std; - - string GetNonEmptyLineCIN(); + namespace InputHelpers { + std::string GetNonEmptyLineCIN(); int GetSingleIntegerValueCIN(); - vector GetIntegerValuesCIN(); + std::vector GetIntegerValuesCIN(); } } diff --git a/src/core/aggmis/include/AggMIS_MIS_CPU.h b/src/core/aggmis/include/AggMIS_MIS_CPU.h index fb859a1..ba70aae 100644 --- a/src/core/aggmis/include/AggMIS_MIS_CPU.h +++ b/src/core/aggmis/include/AggMIS_MIS_CPU.h @@ -11,10 +11,8 @@ #include namespace AggMIS { namespace MIS { - using namespace Types; - using namespace std; - IntVector_h* FloodFillMIS(int k, Graph_h &graph); - IntVector_h* NaiveMIS(int k, Graph_h &graph); + Types::IntVector_h* FloodFillMIS(int k, Types::Graph_h &graph); + Types::IntVector_h* NaiveMIS(int k, Types::Graph_h &graph); } } #endif /* AGGMIS_MIS_CPU_H */ diff --git a/src/core/aggmis/include/AggMIS_MIS_GPU.h b/src/core/aggmis/include/AggMIS_MIS_GPU.h index f056d93..48a09be 100644 --- a/src/core/aggmis/include/AggMIS_MIS_GPU.h +++ b/src/core/aggmis/include/AggMIS_MIS_GPU.h @@ -1,4 +1,4 @@ -/* +/* * File: AggMIS_MIS_GPU.h * Author: T. James Lewis * @@ -9,45 +9,44 @@ #define AGGMIS_MIS_GPU_H #include "AggMIS_Types.h" namespace AggMIS { - namespace MIS { - using namespace AggMIS::Types; - using namespace std; - namespace Kernels { - __global__ void GenerateRandoms(int size, - int iterations, - unsigned int *randoms, - unsigned int *seeds); - __global__ void PreInitialize (int size, - unsigned int *randoms, - int *bestSeen, - int *origin, - int *mis); - __global__ void Initialize (int size, - unsigned int *randoms, - int *bestSeen, - int *origin, - int *mis, - int *incomplete); - __global__ void Iterate (int size, - int *originIn, - int *originOut, - int *bestSeenIn, - int *bestSeenOut, - int *adjIndexes, - int *adjacency); - __global__ void Finalize (int size, - int *originIn, - int *originOut, - int *bestSeenIn, - int *bestSeenOut, - int *adjIndexes, - int *adjacency, - int *mis, - int *incomplete); - } - IntVector_d* RandomizedMIS(int k, Graph_d &graph); - bool IsValidKMIS(IntVector_d &misIn, Graph_d &graph, int k, bool verbose); + namespace MIS { + namespace Kernels { + __global__ void GenerateRandoms(int size, + int iterations, + unsigned int *randoms, + unsigned int *seeds); + __global__ void PreInitialize(int size, + unsigned int *randoms, + int *bestSeen, + int *origin, + int *mis); + __global__ void Initialize(int size, + unsigned int *randoms, + int *bestSeen, + int *origin, + int *mis, + int *incomplete); + __global__ void Iterate(int size, + int *originIn, + int *originOut, + int *bestSeenIn, + int *bestSeenOut, + int *adjIndexes, + int *adjacency); + __global__ void Finalize(int size, + int *originIn, + int *originOut, + int *bestSeenIn, + int *bestSeenOut, + int *adjIndexes, + int *adjacency, + int *mis, + int *incomplete); } + Types::IntVector_d* RandomizedMIS(int k, Types::Graph_d &graph); + bool IsValidKMIS(Types::IntVector_d &misIn, + Types::Graph_d &graph, int k, bool verbose); + } } diff --git a/src/core/aggmis/include/AggMIS_MergeSplitConditioner.h b/src/core/aggmis/include/AggMIS_MergeSplitConditioner.h index 5775419..05338e2 100644 --- a/src/core/aggmis/include/AggMIS_MergeSplitConditioner.h +++ b/src/core/aggmis/include/AggMIS_MergeSplitConditioner.h @@ -1,4 +1,4 @@ -/* +/* * File: AggMIS_MergeSplitConditioner.h * Author: T. James Lewis * @@ -16,322 +16,320 @@ #include "thrust/scan.h" namespace AggMIS { - namespace MergeSplitGPU { - using namespace Types; - using namespace std; - - // GPU Kernels - namespace Kernels { - namespace T { - template - struct AddTo { - const T a; - __device__ AddTo(T _a):a(_a){}; - __device__ T operator() (const T &b) const { - return a + b; - } - }; - template - __device__ void Transform(int size, T* array, F f) { - if (threadIdx.x < size) - array[threadIdx.x] = f(array[threadIdx.x]); - __syncthreads(); - } -// template -// __device__ T Reduce(int size, T* input, T* scratch, ) - } - // Device helper functions - namespace D { - /** - * Loads the in aggregate neighbors of the current node into an array, - * translating them into local indices. - * @param neighbors Pointer to array to place neighbor Ids - * @param nextNeighbor Will contain the index of the element past - * the last valid neighbor in the array. - * @param aggSize The count of nodes in the aggregate - * @param nodeIds The sorted list of nodes in the aggregate - * @param adjIndices The graph indices - * @param adjacency The graph adjacency - */ - __device__ void LoadLocalNeighbors(int *neighbors, - int *nextNeighbor, - int aggSize, - int *nodeIds, - int *adjIndices, - int *adjacency); - /** - * Performs a binary search returning the index of the given - * value, or -1 if not found. - * @param value The value to search for. - * @param imin The index beginning the search range. - * @param imax The index after the end of the search range. - * @param array Pointer to array to be searched - * @return The index of the given value, or -1 if not found. - */ - __device__ int BinarySearch(int value, - int imin, - int imax, - int *array); - /** - * This method flood fills distances from the specified node - * within the subgraph. - * @param starter The node to count distances from - * @param array The array to mark the distances of each node - * @param nodeCount The number of nodes in subgraph - * @param neighbors The array of neighbors for the current - * thread's node - * @param neighborCount The count of neighbors of the current - * thread's node - * @param farthestId After the flood fill completes this will - * contain the ID of a node with maximal distance. - * @param incomplete Shared boolean flag to use within method - */ - __device__ void FloodFillDistanceFrom(int starter, - int* array, - int nodeCount, - int *neighbors, - int neighborCount, - int *farthestId, - bool *incomplete); - __device__ void PrintSharedArray(int size, - int *array, - const char *note); - __device__ void WarpReport(const char* note); - __device__ void SillyTest(); - } - __global__ void MakeMerges(int size, - int *mergeWith, - int *offsets, - int *mis); - __global__ void MakeMerges_MarkSplits(int size, - int *mergeWith, - int *offsets, - int *mis, - int *splitsToMake); - __global__ void MakeSplits(int baseAggregateIdx, - int *splitting, - int *aggregation, - int *aggMapAdjIndices, - int *aggMapAdjacency, - int *adjIndices, - int *adjacency); - __global__ void MakeSplitsWeighted(int baseAggregateIdx, - int* splitting, - int* aggregation, - int* aggMapAdjIndices, - int* aggMapAdjacency, - int* adjIndices, - int* adjacency, - int* weights); - __global__ void MakeSplits_Large(int baseAggregateIdx, - int *splitting, - int *aggregation, - int *aggMapAdjIndices, - int *aggMapAdjacency, - int *adjIndices, - int *adjacency); - __global__ void MakeSplitsWeighted_Large(int baseAggregateIdx, - int* splitting, - int* aggregation, - int* aggMapAdjIndices, - int* aggMapAdjacency, - int* adjIndices, - int* adjacency, - int* weights); - __global__ void MarkSplits(int size, - bool force, - int minPartSize, - int maxPartSize, - int *partSizes, - int *splitsToMake); - __global__ void FindDesirableMerges(int size, - int minSize, - int maxSize, - bool force, - int* adjIndices, - int* adjacency, - int *partSizes, - int* desiredMerges, - int* merging); - __global__ void FindDesirableMergeSplits(int size, - int minSize, - int maxSize, - int desiredSize, - int* adjIndices, - int* adjacency, - int* partSizes, - int* desiredMerges, - int* merging); - __global__ void MarkMerges(int size, - int* desiredMerges, - int* merging, - int* mergesToMake, - int* incomplete); + namespace MergeSplitGPU { + + // GPU Kernels + namespace Kernels { + namespace T { + template + struct AddTo { + const T a; + __device__ AddTo(T _a) :a(_a){}; + __device__ T operator() (const T &b) const { + return a + b; + } + }; + template + __device__ void Transform(int size, T* array, F f) { + if (threadIdx.x < size) + array[threadIdx.x] = f(array[threadIdx.x]); + __syncthreads(); } - - // Functors for Thrust calls - namespace Functors { - struct isOutSized:public thrust::unary_function { - const int a, b; - isOutSized(int _a, int _b):a(_a),b(_b){} + // template + // __device__ T Reduce(int size, T* input, T* scratch, ) + } + // Device helper functions + namespace D { + /** + * Loads the in aggregate neighbors of the current node into an array, + * translating them into local indices. + * @param neighbors Pointer to array to place neighbor Ids + * @param nextNeighbor Will contain the index of the element past + * the last valid neighbor in the array. + * @param aggSize The count of nodes in the aggregate + * @param nodeIds The sorted list of nodes in the aggregate + * @param adjIndices The graph indices + * @param adjacency The graph adjacency + */ + __device__ void LoadLocalNeighbors(int *neighbors, + int *nextNeighbor, + int aggSize, + int *nodeIds, + int *adjIndices, + int *adjacency); + /** + * Performs a binary search returning the index of the given + * value, or -1 if not found. + * @param value The value to search for. + * @param imin The index beginning the search range. + * @param imax The index after the end of the search range. + * @param array Pointer to array to be searched + * @return The index of the given value, or -1 if not found. + */ + __device__ int BinarySearch(int value, + int imin, + int imax, + int *array); + /** + * This method flood fills distances from the specified node + * within the subgraph. + * @param starter The node to count distances from + * @param array The array to mark the distances of each node + * @param nodeCount The number of nodes in subgraph + * @param neighbors The array of neighbors for the current + * thread's node + * @param neighborCount The count of neighbors of the current + * thread's node + * @param farthestId After the flood fill completes this will + * contain the ID of a node with maximal distance. + * @param incomplete Shared boolean flag to use within method + */ + __device__ void FloodFillDistanceFrom(int starter, + int* array, + int nodeCount, + int *neighbors, + int neighborCount, + int *farthestId, + bool *incomplete); + __device__ void PrintSharedArray(int size, + int *array, + const char *note); + __device__ void WarpReport(const char* note); + __device__ void SillyTest(); + } + __global__ void MakeMerges(int size, + int *mergeWith, + int *offsets, + int *mis); + __global__ void MakeMerges_MarkSplits(int size, + int *mergeWith, + int *offsets, + int *mis, + int *splitsToMake); + __global__ void MakeSplits(int baseAggregateIdx, + int *splitting, + int *aggregation, + int *aggMapAdjIndices, + int *aggMapAdjacency, + int *adjIndices, + int *adjacency); + __global__ void MakeSplitsWeighted(int baseAggregateIdx, + int* splitting, + int* aggregation, + int* aggMapAdjIndices, + int* aggMapAdjacency, + int* adjIndices, + int* adjacency, + int* weights); + __global__ void MakeSplits_Large(int baseAggregateIdx, + int *splitting, + int *aggregation, + int *aggMapAdjIndices, + int *aggMapAdjacency, + int *adjIndices, + int *adjacency); + __global__ void MakeSplitsWeighted_Large(int baseAggregateIdx, + int* splitting, + int* aggregation, + int* aggMapAdjIndices, + int* aggMapAdjacency, + int* adjIndices, + int* adjacency, + int* weights); + __global__ void MarkSplits(int size, + bool force, + int minPartSize, + int maxPartSize, + int *partSizes, + int *splitsToMake); + __global__ void FindDesirableMerges(int size, + int minSize, + int maxSize, + bool force, + int* adjIndices, + int* adjacency, + int *partSizes, + int* desiredMerges, + int* merging); + __global__ void FindDesirableMergeSplits(int size, + int minSize, + int maxSize, + int desiredSize, + int* adjIndices, + int* adjacency, + int* partSizes, + int* desiredMerges, + int* merging); + __global__ void MarkMerges(int size, + int* desiredMerges, + int* merging, + int* mergesToMake, + int* incomplete); + } + + // Functors for Thrust calls + namespace Functors { + struct isOutSized :public thrust::unary_function { + const int a, b; + isOutSized(int _a, int _b) :a(_a), b(_b){} - __host__ __device__ - bool operator()(const int &x) const - { - return x < a || x > b; - } - }; - struct lessThan:public thrust::unary_function { - const int a; + __host__ __device__ + bool operator()(const int &x) const + { + return x < a || x > b; + } + }; + struct lessThan :public thrust::unary_function { + const int a; - lessThan(int _a): a(_a){} + lessThan(int _a) : a(_a){} - __host__ __device__ - int operator()(const int &x) const - { - return x < a; - } - }; - struct greaterThan:public thrust::unary_function { - const int a; + __host__ __device__ + int operator()(const int &x) const + { + return x < a; + } + }; + struct greaterThan :public thrust::unary_function { + const int a; - greaterThan(int _a): a(_a){} + greaterThan(int _a) : a(_a){} - __host__ __device__ - int operator()(const int &x) const - { - return x > a; - } - }; - struct NotNegOne:public thrust::unary_function { - __host__ __device__ - int operator()(int a) const - { - // If value is negative return 0 else return one - return a < 0 ? 0 : 1; - } - }; - struct EqualTo:public thrust::unary_function { - const int a; + __host__ __device__ + int operator()(const int &x) const + { + return x > a; + } + }; + struct NotNegOne :public thrust::unary_function { + __host__ __device__ + int operator()(int a) const + { + // If value is negative return 0 else return one + return a < 0 ? 0 : 1; + } + }; + struct EqualTo :public thrust::unary_function { + const int a; - EqualTo(int _a): a(_a){} + EqualTo(int _a) : a(_a){} - __host__ __device__ - int operator()(const int &x) const - { - return x == a; - } - }; - struct SquaredDifference:public thrust::unary_function { - const int a; - SquaredDifference(double _a):a(_a){} - __host__ __device__ - double operator()(const int &x) const { - return (a-x)*(a-x); - } - }; - struct SplitFilter { - const int a; - const int b; - SplitFilter(int _a, int _b):a(_a),b(_b){} - __host__ __device__ - bool operator()(const thrust::tuple &x) const { - return thrust::get<0>(x) == 1 && - thrust::get<1>(x) >= a && - thrust::get<1>(x) <= b; - } - }; + __host__ __device__ + int operator()(const int &x) const + { + return x == a; } - - // Merge and Split conditioner main container - class MergeSplitConditionerGPU { - public: - /** - * The primary constructor it creates a conditioner given the - * specified graph and aggregation. It makes an internal copy of - * the aggregation vector, but it uses a pointer back to the given - * Graph object - * @param graph The graph that the aggregation being conditioned - * is an aggregation of. - * @param aggregation A vector which labels every node in the graph - * with an aggregate ID. - */ - MergeSplitConditionerGPU(Graph_d &graph, - IntVector_d &aggregation); - void SetSizeBounds(int min, int max); - void SetVerbose(bool v); - /** - * Sets the node weights by swapping the contents of the provided - * vector into the nodeWeights member. Then it re-computes the part - * sizes with weighting. - * @param nodeWeights A vector containing the weights of each node - * the contents of this vector are swapped out by the method. - */ - void SetNodeWeights(IntVector_d &nodeWeights); - /** - * Getter for the aggregation vector. - * @return A pointer to the current aggregation vector - */ - IntVector_d* GetAggregation(); - /** - * Getter for the NodeWeights vector - * @return A pointer to the current NodeWeights vector - */ - IntVector_d* GetNodeWeights(); - void CycleMerges(bool force); - void CycleSplits(bool force); - void CycleMergeSplits(float minImprove, - int desiredSize); - bool Condition(int desiredSize, - bool respectUpper, - float tolerance, - float minImprove, - int maxCycles); - void PrintProgress(ostream* output, - string note, - bool graphStat, - bool progressStat, - bool sizeStat, - bool memStat); - void PrintSizeStats(ostream* output, - bool makeHeader); - void PrintMemoryStats(ostream* output, - bool makeHeader); - void PrintProgressStats(ostream* output, - bool makeHeader); - void PrintGraphStats(ostream* output, - bool makeHeader); - void InteractiveConsole(string message); - private: - bool MarkMerges(bool force); - bool MarkSplits(bool force); - bool MarkMergeSplits(int desiredSize); - void MakeSplits(); - void MakeMerges(bool markSplits); - bool MakeMergeSplits(int desiredSize); - - // Data members - Graph_d *graph; - Graph_d *inducedGraph; - - int minSize, - maxSize, - outsizedParts, - merges, - mergeSplits, - splits; - - IntVector_d aggregation, - nodeWeights, - partSizes, - weightedSizes, - splitsToMake, - mergesToMake, - mergeOffsets; - - bool verbose; - }; + }; + struct SquaredDifference :public thrust::unary_function { + const int a; + SquaredDifference(double _a) :a(_a){} + __host__ __device__ + double operator()(const int &x) const { + return (a - x)*(a - x); + } + }; + struct SplitFilter { + const int a; + const int b; + SplitFilter(int _a, int _b) :a(_a), b(_b){} + __host__ __device__ + bool operator()(const thrust::tuple &x) const { + return thrust::get<0>(x) == 1 && + thrust::get<1>(x) >= a && + thrust::get<1>(x) <= b; + } + }; } + + // Merge and Split conditioner main container + class MergeSplitConditionerGPU { + public: + /** + * The primary constructor it creates a conditioner given the + * specified graph and aggregation. It makes an internal copy of + * the aggregation vector, but it uses a pointer back to the given + * Graph object + * @param graph The graph that the aggregation being conditioned + * is an aggregation of. + * @param aggregation A vector which labels every node in the graph + * with an aggregate ID. + */ + MergeSplitConditionerGPU(Types::Graph_d &graph, + Types::IntVector_d &aggregation); + void SetSizeBounds(int min, int max); + void SetVerbose(bool v); + /** + * Sets the node weights by swapping the contents of the provided + * vector into the nodeWeights member. Then it re-computes the part + * sizes with weighting. + * @param nodeWeights A vector containing the weights of each node + * the contents of this vector are swapped out by the method. + */ + void SetNodeWeights(Types::IntVector_d &nodeWeights); + /** + * Getter for the aggregation vector. + * @return A pointer to the current aggregation vector + */ + Types::IntVector_d* GetAggregation(); + /** + * Getter for the NodeWeights vector + * @return A pointer to the current NodeWeights vector + */ + Types::IntVector_d* GetNodeWeights(); + void CycleMerges(bool force); + void CycleSplits(bool force); + void CycleMergeSplits(float minImprove, + int desiredSize); + bool Condition(int desiredSize, + bool respectUpper, + float tolerance, + float minImprove, + int maxCycles); + void PrintProgress(std::ostream* output, + std::string note, + bool graphStat, + bool progressStat, + bool sizeStat, + bool memStat); + void PrintSizeStats(std::ostream* output, + bool makeHeader); + void PrintMemoryStats(std::ostream* output, + bool makeHeader); + void PrintProgressStats(std::ostream* output, + bool makeHeader); + void PrintGraphStats(std::ostream* output, + bool makeHeader); + void InteractiveConsole(std::string message); + private: + bool MarkMerges(bool force); + bool MarkSplits(bool force); + bool MarkMergeSplits(int desiredSize); + void MakeSplits(); + void MakeMerges(bool markSplits); + bool MakeMergeSplits(int desiredSize); + + // Data members + Types::Graph_d *graph; + Types::Graph_d *inducedGraph; + + int minSize, + maxSize, + outsizedParts, + merges, + mergeSplits, + splits; + + Types::IntVector_d aggregation, + nodeWeights, + partSizes, + weightedSizes, + splitsToMake, + mergesToMake, + mergeOffsets; + + bool verbose; + }; + } } diff --git a/src/core/aggmis/include/AggMIS_MergeSplitConditioner_CPU.h b/src/core/aggmis/include/AggMIS_MergeSplitConditioner_CPU.h index 9e2e477..7b8af2c 100644 --- a/src/core/aggmis/include/AggMIS_MergeSplitConditioner_CPU.h +++ b/src/core/aggmis/include/AggMIS_MergeSplitConditioner_CPU.h @@ -16,8 +16,6 @@ namespace AggMIS { namespace MergeSplitCPU { - using namespace Types; - using namespace std; // Functors for Thrust calls namespace Functors { @@ -87,8 +85,8 @@ namespace AggMIS { * @param aggregation A vector which labels every node in the graph * with an aggregate ID. */ - MergeSplitConditionerCPU(Graph_h &graph, - IntVector_h &aggregation); + MergeSplitConditionerCPU(Types::Graph_h &graph, + Types::IntVector_h &aggregation); void SetSizeBounds(int min, int max); void SetVerbose(bool v); /** @@ -98,17 +96,17 @@ namespace AggMIS { * @param nodeWeights A vector containing the weights of each node * the contents of this vector are swapped out by the method. */ - void SetNodeWeights(IntVector_h &nodeWeights); + void SetNodeWeights(Types::IntVector_h &nodeWeights); /** * Getter for the aggregation vector. * @return A pointer to the current aggregation vector */ - IntVector_h* GetAggregation(); + Types::IntVector_h* GetAggregation(); /** * Getter for the NodeWeights vector * @return A pointer to the current NodeWeights vector */ - IntVector_h* GetNodeWeights(); + Types::IntVector_h* GetNodeWeights(); void CycleMerges(bool force); void CycleSplits(bool force); void CycleMergeSplits(float minImprove, @@ -118,18 +116,18 @@ namespace AggMIS { float tolerance, float minImprove, int maxCycles); - void PrintProgress(ostream* output, - string note, + void PrintProgress(std::ostream* output, + std::string note, bool graphStat, bool progressStat, bool sizeStat); - void PrintSizeStats(ostream* output, + void PrintSizeStats(std::ostream* output, bool makeHeader); - void PrintProgressStats(ostream* output, + void PrintProgressStats(std::ostream* output, bool makeHeader); - void PrintGraphStats(ostream* output, + void PrintGraphStats(std::ostream* output, bool makeHeader); - void InteractiveConsole(string message); + void InteractiveConsole(std::string message); private: bool MarkMerges(bool force); bool MarkSplits(bool force); @@ -150,11 +148,11 @@ namespace AggMIS { void ValidateAggAdjacency(); void ValidateAggMap(); void ValidatePartSizes(); - void ValidateArraySizes(string message); + void ValidateArraySizes(std::string message); // Data members - Graph_h *graph; - Graph_h *inducedGraph; + Types::Graph_h *graph; + Types::Graph_h *inducedGraph; int minSize, maxSize, @@ -163,7 +161,7 @@ namespace AggMIS { mergeSplits, splits; - IntVector_h aggregation, + Types::IntVector_h aggregation, nodeWeights, distances, partSizes, @@ -173,13 +171,13 @@ namespace AggMIS { mergeOffsets; // Stores lists of nodes in each aggregate - vector > aggMap; + std::vector > aggMap; // Stores the neighbors of each aggregate - vector > aggAdjacency; + std::vector > aggAdjacency; // Stores the root point sets for each aggregate - vector > rootPoints; + std::vector > rootPoints; bool verbose; }; diff --git a/src/core/aggmis/include/AggMIS_Metrics.h b/src/core/aggmis/include/AggMIS_Metrics.h index 673c98e..264688d 100644 --- a/src/core/aggmis/include/AggMIS_Metrics.h +++ b/src/core/aggmis/include/AggMIS_Metrics.h @@ -1,4 +1,4 @@ -/* +/* * File: AggMIS_Metrics.h * Author: T. James Lewis * @@ -13,48 +13,51 @@ #include #include namespace AggMIS { - namespace Metrics { - using namespace Types; - using namespace std; - class MetricsContext { - public: - MetricsContext(Graph_h &graph, IntVector_h &aggregation); - double GetConvexityRatio(int aggId); - double GetEccentricityRatio(int aggId); - double GetMinimumEnclosingBallRatio(int aggId); - int GetAggregateCount(); - - private: - // Data structures - Graph_h *graph; - IntVector_h aggregation; - vector > aggregates; - vector > convexAggregates; - int currentAggregate; - - // Counters - int distanceLookups, makeConvexCalls; - - // Internal Methods - int Distance(int a, int b); - double GetEccentricityRatio(vector &aggregate); - double GetMinimumEnclosingBallRatio(vector &aggregate); - void MakeConvex(vector &aggregate); - void EnsureConvex(int aggId); - vector* FindCentroid(vector& aggregate); - int FindMassScore(int node, vector& aggregate); - map* FindDistances(int rootNode, vector& aggregate); - vector >* GetShortestPaths(int startId, int endId, map &distances); - vector >* FindExternalsInPaths(vector& aggregate, vector >* p); - bool IsPathSatisfied(set& required, vector >& pathOptions); - set* BruteForceMinimalNodes(vector > >& pathOptions); - bool IncrementGuessVector(vector& guess, vector > >& externalOptions); - - // Setup helpers - void Initialize(); - void GetAggregates(); - }; - } + namespace Metrics { + class MetricsContext { + public: + MetricsContext(Types::Graph_h &graph, Types::IntVector_h &aggregation); + double GetConvexityRatio(int aggId); + double GetEccentricityRatio(int aggId); + double GetMinimumEnclosingBallRatio(int aggId); + int GetAggregateCount(); + + private: + // Data structures + Types::Graph_h *graph; + Types::IntVector_h aggregation; + std::vector > aggregates; + std::vector > convexAggregates; + int currentAggregate; + + // Counters + int distanceLookups, makeConvexCalls; + + // Internal Methods + int Distance(int a, int b); + double GetEccentricityRatio(std::vector &aggregate); + double GetMinimumEnclosingBallRatio(std::vector &aggregate); + void MakeConvex(std::vector &aggregate); + void EnsureConvex(int aggId); + std::vector* FindCentroid(std::vector& aggregate); + int FindMassScore(int node, std::vector& aggregate); + std::map* FindDistances(int rootNode, std::vector& aggregate); + std::vector >* GetShortestPaths(int startId, int endId, + std::map &distances); + std::vector >* FindExternalsInPaths(std::vector& aggregate, + std::vector >* p); + bool IsPathSatisfied(std::set& required, + std::vector >& pathOptions); + std::set* BruteForceMinimalNodes(std::vector< + std::vector > >& pathOptions); + bool IncrementGuessVector(std::vector& guess, std::vector > >& externalOptions); + + // Setup helpers + void Initialize(); + void GetAggregates(); + }; + } } #endif /* AGGMIS_METRICS_H */ diff --git a/src/core/aggmis/include/AggMIS_Types.h b/src/core/aggmis/include/AggMIS_Types.h index 4556376..691d18e 100644 --- a/src/core/aggmis/include/AggMIS_Types.h +++ b/src/core/aggmis/include/AggMIS_Types.h @@ -21,7 +21,6 @@ namespace AggMIS { bool CheckCudaError(cudaError_t code, const char *file, int line); namespace Types { - using namespace std; typedef thrust::device_vector IntVector_d; typedef thrust::device_vector UIntVector_d; typedef thrust::host_vector IntVector_h; @@ -114,8 +113,8 @@ namespace AggMIS { bool AreEqual(IntVector_d& a, IntVector_h& b, bool verbose); - bool AreEqual(vector > &a, - vector > &b, + bool AreEqual(std::vector > &a, + std::vector > &b, bool verbose); bool AreEqual(Graph_h& a, Graph_h& b, @@ -131,28 +130,27 @@ namespace AggMIS { bool verbose); } namespace Display { - using namespace std; void Print(IntVector_h& toPrint, int start, int end, - string message); + std::string message); void Print(IntVector_d& toPrint, int start, int end, - string message); + std::string message); void Print(IntVector_d& toPrint, - string message); + std::string message); void Print(IntVector_h& toPrint, - string message); - void Print(vector > >& toPrint, string message); - void Print(vector >& toPrint, - string message); - void Print(vector &toPrint, + std::string message); + void Print(std::vector > >& toPrint, std::string message); + void Print(std::vector >& toPrint, + std::string message); + void Print(std::vector &toPrint, int start, int end, - string message); - void Print(vector &toPrint, - string message); + std::string message); + void Print(std::vector &toPrint, + std::string message); } } } diff --git a/src/core/cuda/AggMIS_Types.cu b/src/core/cuda/AggMIS_Types.cu index 45afa4a..74156f6 100644 --- a/src/core/cuda/AggMIS_Types.cu +++ b/src/core/cuda/AggMIS_Types.cu @@ -217,8 +217,8 @@ namespace AggMIS { bool verbose) { return AreEqual(b, a, verbose); } - bool AreEqual(vector > &a, - vector > &b, + bool AreEqual(std::vector > &a, + std::vector > &b, bool verbose) { // Check that main containers have matching sizes if (a.size() != b.size()) { @@ -234,12 +234,12 @@ namespace AggMIS { printf("Sizes of secondary vectors %d do not match!\n", i); printf("a[%d].size()=%d b[%d].size()=%d\n", i, a[i].size(), i, b[i].size()); - stringstream ss; + std::stringstream ss; ss << "Contents of A[" << i << "]"; - Display::Print(a[i], ss.str()); + AggMIS::Types::Display::Print(a[i], ss.str()); ss.str("Contents of B["); ss << i << "]"; - Display::Print(b[i], ss.str()); + AggMIS::Types::Display::Print(b[i], ss.str()); } return false; } @@ -250,12 +250,12 @@ namespace AggMIS { if (a[i][j] != b[i][j]) { if (verbose) { printf("Element[%d][%d] does not match!\n", i, j); - stringstream ss; + std::stringstream ss; ss << "Contents of A[" << i << "]"; - Display::Print(a[i], ss.str()); + AggMIS::Types::Display::Print(a[i], ss.str()); ss.str("Contents of B["); ss << i << "]"; - Display::Print(b[i], ss.str()); + AggMIS::Types::Display::Print(b[i], ss.str()); } return false; } @@ -263,8 +263,8 @@ namespace AggMIS { } return true; } - bool AreEqual(Graph_h& a, - Graph_h& b, + bool AreEqual(AggMIS::Types::Graph_h& a, + AggMIS::Types::Graph_h& b, bool verbose) { bool indicesMatch = AreEqual(*(a.indices), *(b.indices), @@ -278,8 +278,8 @@ namespace AggMIS { printf("Adjacency lists of graphs differ!\n"); return indicesMatch && adjacencyMatch; } - bool AreEqual(Graph_d& a, - Graph_d& b, + bool AreEqual(AggMIS::Types::Graph_d& a, + AggMIS::Types::Graph_d& b, bool verbose) { bool indicesMatch = AreEqual(*(a.indices), *(b.indices), @@ -308,8 +308,8 @@ namespace AggMIS { printf("Adjacency lists of graphs differ!\n"); return indicesMatch && adjacencyMatch; } - bool AreEqual(Graph_d& a, - Graph_h& b, + bool AreEqual(AggMIS::Types::Graph_d& a, + AggMIS::Types::Graph_h& b, bool verbose) { bool indicesMatch = AreEqual(*(a.indices), *(b.indices), @@ -325,10 +325,10 @@ namespace AggMIS { } } namespace Display { - void Print(IntVector_h& toPrint, + void Print(AggMIS::Types::IntVector_h& toPrint, int start, int end, - string message) { + std::string message) { printf("%s:\n", message.c_str()); printf("\n %8d: ", 0); for (int i = start; i < end; i++) @@ -344,46 +344,46 @@ namespace AggMIS { void Print(IntVector_d& toPrint, int start, int end, - string message) { - IntVector_h temp(toPrint); + std::string message) { + AggMIS::Types::IntVector_h temp(toPrint); Print(temp, start, end, message); temp.clear(); } - void Print(IntVector_d& toPrint, - string message) { - IntVector_h temp(toPrint); + void Print(AggMIS::Types::IntVector_d& toPrint, + std::string message) { + AggMIS::Types::IntVector_h temp(toPrint); Print(temp, 0, temp.size(), message); temp.clear(); } - void Print(IntVector_h& toPrint, - string message) { + void Print(AggMIS::Types::IntVector_h& toPrint, + std::string message) { Print(toPrint, 0, toPrint.size(), message); } - void Print(vector > >& toPrint, - string message) { + void Print(std::vector > >& toPrint, + std::string message) { // Print out general info: printf("Triple vector %s has %d entries:\n", message.c_str(), toPrint.size()); for (int i = 0; i < toPrint.size(); i++) { - cout << message << "[" << i << "]: "; + std::cout << message << "[" << i << "]: "; for (int z = 0; z < toPrint[i].size(); z++) { - cout << "("; + std::cout << "("; for (int zz = 0; zz < toPrint[i][z].size(); zz++) { - cout << toPrint[i][z][zz]; + std::cout << toPrint[i][z][zz]; if (zz < toPrint[i][z].size() -1) - cout << " "; + std::cout << " "; } - cout << ") "; + std::cout << ") "; } - cout << "\n"; + std::cout << "\n"; } - cout << "\n"; + std::cout << "\n"; } - void Print(vector >& toPrint, - string message) { + void Print(std::vector >& toPrint, + std::string message) { printf("%s:\n", message.c_str()); for (int j = 0; j < toPrint.size(); j++) { printf("\n %4d: ", j); @@ -398,15 +398,15 @@ namespace AggMIS { } printf("\n"); } - void Print(vector& toPrint, + void Print(std::vector& toPrint, int start, int end, - string message) { + std::string message) { IntVector_h temp(toPrint.begin(), toPrint.end()); Print(temp, start, end, message); } - void Print(vector& toPrint, - string message) { + void Print(std::vector& toPrint, + std::string message) { Print(toPrint, 0, toPrint.size(), message); } } diff --git a/src/core/cuda/allocator.cu b/src/core/cuda/allocator.cu index 8bb1932..da233f6 100644 --- a/src/core/cuda/allocator.cu +++ b/src/core/cuda/allocator.cu @@ -4,7 +4,6 @@ #include #include -using namespace std; template Allocator::FreeMap Allocator::free_vars; diff --git a/src/core/cuda/amg.cu b/src/core/cuda/amg.cu index ee36d4d..475f6d7 100644 --- a/src/core/cuda/amg.cu +++ b/src/core/cuda/amg.cu @@ -233,19 +233,16 @@ void AMG::printGridStatistics() } -using std::scientific; -using std::fixed; - // print a line of length l, starting at character s void printLine(const int l, const int s) { - cout << setw(s) << " "; + std::cout << std::setw(s) << " "; for (int i = 0; i < l; i++) { - cout << "-"; + std::cout << "-"; } - cout << endl; + std::cout << std::endl; } template diff --git a/src/core/cuda/amg_level.cu b/src/core/cuda/amg_level.cu index 3a50be3..19d8394 100644 --- a/src/core/cuda/amg_level.cu +++ b/src/core/cuda/amg_level.cu @@ -44,7 +44,7 @@ void AMG_Level::cycle(CycleType cycle, Vector_d& b_d, Vector_d& smoother->preRRRFullCsr(AinCSR_d, Aout_d, aggregateIdx_d, partitionIdx_d, restrictorFull_d, ipermutation_d, b_d, x_d, bc_d, level_id, largestblocksize, largest_num_entries, largest_num_per_row); break; default: - cout << "Wrong DStype 1!" << endl; + std::cout << "Wrong DStype 1!" << std::endl; exit(0); } @@ -62,7 +62,7 @@ void AMG_Level::cycle(CycleType cycle, Vector_d& b_d, Vector_d& smoother->postPCRFullCsr(AinCSR_d, Aout_d, AoutBlockIdx_d, aggregateIdx_d, partitionIdx_d, prolongatorFull_d, ipermutation_d, b_d, x_d, xc_d, level_id, largestblocksize, largest_num_entries, largest_num_per_row); break; default: - cout << "Wrong DStype 0!" << endl; + std::cout << "Wrong DStype 0!" << std::endl; exit(0); } @@ -99,7 +99,7 @@ void AMG_Level::cycle_level0(CycleType cycle, Vector_d_CG &b_d_C smoother->preRRRFullCsr(AinCSR_d, Aout_d, aggregateIdx_d, partitionIdx_d, restrictorFull_d, ipermutation_d, b_d, x_d, bc_d, level_id, largestblocksize, largest_num_entries, largest_num_per_row); break; default: - cout << "Wrong DStype 1!" << endl; + std::cout << "Wrong DStype 1!" << std::endl; exit(0); } @@ -117,7 +117,7 @@ void AMG_Level::cycle_level0(CycleType cycle, Vector_d_CG &b_d_C smoother->postPCRFullCsr(AinCSR_d, Aout_d, AoutBlockIdx_d, aggregateIdx_d, partitionIdx_d, prolongatorFull_d, ipermutation_d, b_d, x_d, xc_d, level_id, largestblocksize, largest_num_entries, largest_num_per_row); break; default: - cout << "Wrong DStype 0!" << endl; + std::cout << "Wrong DStype 0!" << std::endl; exit(0); } diff --git a/src/core/cuda/cgcycle.cu b/src/core/cuda/cgcycle.cu index a38fc62..6cb60c7 100644 --- a/src/core/cuda/cgcycle.cu +++ b/src/core/cuda/cgcycle.cu @@ -42,7 +42,7 @@ CG_Flex_Cycle::CG_Flex_Cycle(CycleType next_cycle, int num_iters cusp::blas::axpy(y, r, -alpha); ValueType normr = cusp::blas::nrm2(r); if (verbose) - cout << "normr=" << scientific << normr << " niter=" << niter << endl; + std::cout << "normr=" << std::scientific << normr << " niter=" << niter << std::endl; if( (normr / bnorm) <= tol) break; @@ -57,8 +57,8 @@ CG_Flex_Cycle::CG_Flex_Cycle(CycleType next_cycle, int num_iters cudaThreadSynchronize(); iter_stop = CLOCK(); if (verbose) { - cout << "average time per iteration: " << (iter_stop-iter_start) / niter << endl; - cout << "total solve time: " << (iter_stop-iter_start) << endl; + std::cout << "average time per iteration: " << (iter_stop-iter_start) / niter << std::endl; + std::cout << "total solve time: " << (iter_stop-iter_start) << std::endl; } y.clear(); diff --git a/src/core/cuda/cutil.cu b/src/core/cuda/cutil.cu index a8f7ac8..0b71b7a 100644 --- a/src/core/cuda/cutil.cu +++ b/src/core/cuda/cutil.cu @@ -147,7 +147,7 @@ void __global__ compute_ele_indices_kernel(IndexType* tri0, IndexType* tri1, Ind // compute_ele_indices_kernel << > >(d_tri0, d_tri1, d_tri2, ne, d_rowoffsets, thrust::raw_pointer_cast(&d_ele_indices[0])); // cudaCheckError(); // -// IndexType* tmpvector = thrust::raw_pointer_cast(&d_ele_indices[0]); +// IndexType* tmpstd::vector = thrust::raw_pointer_cast(&d_ele_indices[0]); // // IndexType maxnumnb = thrust::reduce(d_nbcount, d_nbcount + nv, -1, thrust::maximum ()) * 2; // @@ -256,8 +256,8 @@ void trimesh2csr(TriMesh* meshPtr, Matrix_d_CG &A_d) num_entries = num_entries / 2 + nv; maxsize += 1; // should include itself - vector rowoffsets; - vector idxj; + std::vector rowoffsets; + std::vector idxj; rowoffsets.reserve(nv + 1); idxj.reserve(num_entries); @@ -280,7 +280,7 @@ void trimesh2csr(TriMesh* meshPtr, Matrix_d_CG &A_d) } int realsz = idxj.size(); - vector values(realsz, 0.0); + std::vector values(realsz, 0.0); Matrix_h_CG A(nv, nv, realsz); @@ -411,5 +411,9 @@ void computeResidual(const Matrix& A, const Vector& x, const Vector& b, Vector& //template void trimesh2csr(const TriMesh* meshPtr, struct cudaCSRGraph& csrgraph); //template void tetmesh2csr(const TetMesh* meshPtr, struct cudaCSRGraph& csrgraph); -template void computeResidual(const Matrix_ell_h& A, const Vector_h& x, const Vector_h& b, Vector_h& r); -template void computeResidual(const Matrix_hyb_d& A, const Vector_d& x, const Vector_d& b, Vector_d& r); +template void computeResidual( + const Matrix_ell_h& A, const Vector_h& x, + const Vector_h& b, Vector_h& r); +template void computeResidual( + const Matrix_hyb_d& A, const Vector_d& x, + const Vector_d& b, Vector_d& r); diff --git a/src/core/cuda/mis.cu b/src/core/cuda/mis.cu index d3c444d..23e81f0 100644 --- a/src/core/cuda/mis.cu +++ b/src/core/cuda/mis.cu @@ -1,8 +1,6 @@ #include #include #include -using namespace std; - template void MIS_Aggregator::computePermutation(TetMesh* meshPtr, IdxVector_h &permutation, IdxVector_h &ipermutation, IdxVector_h &aggregateIdx, IdxVector_h &partitionIdx, int* partitionlabel, int* nnout, int* &xadjout, int* &adjncyout, int metissize) @@ -108,16 +106,16 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* METIS_PartGraphKway(&nn, xadj, adjncy, NULL, NULL, &wgtflag, &pnumflag, &nparts, options, &edgecut, npart); // Finding partitions that have vertices assigned: - vector realParts; + std::vector realParts; realParts.resize(nn); for (int i=0; i empties; + // Scanning for gaps in the std::sorted array + std::vector empties; if (realParts[0] > 0) for (int i = 0; i < realParts[0]; i++) empties.push_back(i); @@ -152,7 +150,7 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* int partCount = *(realParts.end() - 1) - empties.size() + 1; //Building a structure of sub-graphs to aggregate: - vector< vector > blocks; + std::vector< std::vector > blocks; blocks.resize(partCount); for (int i = 0; i < nn; i++) blocks[npart[i]].push_back(i); @@ -160,7 +158,7 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* // Creating the sub graphs for each block // subgraphs[n][0] = pointer to xadj, [1] = pointer to adjncy [2]= pointer to npart [3]= number of aggregates int aggregateCount = 0; - vector< vector > subGraphs(partCount); + std::vector< std::vector > subGraphs(partCount); for (int bIt = 0; bIt < blocks.size(); bIt++) { // Resizing to hold all the pointers @@ -170,7 +168,7 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* int adjacencySize = 0; // Temporary vector to hold adjacency; - vector< vector > adjacency(blocks[bIt].size()); + std::vector< std::vector > adjacency(blocks[bIt].size()); // For every vertex add it's in-block neighbors to the adjacency list: for (int vIt = 0; vIt < blocks[bIt].size(); vIt++) @@ -224,8 +222,8 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* } // Checking if the block's subgraph is connected: - queue toCheck; - vector visited(blocks[bIt].size()); + std::queue toCheck; + std::vector visited(blocks[bIt].size()); for (int i=0; i < blocks[bIt].size(); i++) visited[i] = -1; int nextRoot = 0; @@ -263,10 +261,10 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* } if (!connected) { - cout << "Block: " << bIt << " is an unconnected graph:\n"; + std::cout << "Block: " << bIt << " is an unconnected graph:\n"; for (int i = 0; i < blocks[bIt].size(); i++) - cout << visited[i] << ", "; - cout << "\n"; + std::cout << visited[i] << ", "; + std::cout << "\n"; } // Calling the mis_subroutine to partition @@ -280,7 +278,7 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* for (int vIt=0; vIt < blocks[bIt].size(); vIt++) { if (subGraphs[bIt][2][vIt] < 0) - cout << "There is a problem with block: " << bIt << " of " << blocks.size() << " vertex: " << vIt << " in partition: " << subGraphs[bIt][2][vIt] << "?\n"; + std::cout << "There is a problem with block: " << bIt << " of " << blocks.size() << " vertex: " << vIt << " in partition: " << subGraphs[bIt][2][vIt] << "?\n"; } } @@ -320,11 +318,11 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* partitionIdx[blocks.size()] = aggregateCount; // Finding the adjacency for the graph of aggregates: - vector< vector > aggregateAdjacency(aggregateCount); + std::vector< std::vector > aggregateAdjacency(aggregateCount); int edgeCount = 0; for (int aIt = 0; aIt < aggregateCount; aIt++) { - set partEdges; + std::set partEdges; int begin = aggregateIdx[aIt]; int end = aggregateIdx[aIt + 1]; for (int vIt = begin; vIt < end; vIt++) @@ -339,7 +337,7 @@ void MIS_Aggregator::computePermutation(int nn, int* xadj, int* partEdges.insert(aggregatelabel[ adjncy[nIt] ]); } } - for (set::iterator i=partEdges.begin(); i != partEdges.end(); i++) + for ( std::set::iterator i=partEdges.begin(); i != partEdges.end(); i++) { aggregateAdjacency[aIt].push_back(*i); edgeCount++; @@ -378,7 +376,7 @@ template void MIS_Aggregator::aggregateGraphMIS(int n, int *adjIndexes, int *adjacency, int *partition, int *partCount) { // Creating a graph with edges for every 2-path in original: - vector< vector > inducedAdj(n); + std::vector< std::vector > inducedAdj(n); // Every Vertex for (int i=0; i::aggregateGraphMIS(int n, int *adjIndexes, i } // Picking a better maximal independent set: - vector mis(n, -1); - vector rootDistance(n, -1); + std::vector mis(n, -1); + std::vector rootDistance(n, -1); bool incomplete = true; int nextVertex = 0; int curPart = 0; @@ -443,7 +441,7 @@ void MIS_Aggregator::aggregateGraphMIS(int n, int *adjIndexes, i curPart++; // Getting a list of potential next nodes: - vector potentialNodes; + std::vector potentialNodes; for (int i = 0; i < n; i++) { // For every node known to be outside MIS: if (mis[i] == 0) { @@ -460,7 +458,7 @@ void MIS_Aggregator::aggregateGraphMIS(int n, int *adjIndexes, i if (potentialNodes.size() > 0) { incomplete = true; - sort(potentialNodes.begin(), potentialNodes.end()); + std::sort(potentialNodes.begin(), potentialNodes.end()); int occurs = 0; int maxOccur = 0; int curNode = potentialNodes[0]; diff --git a/src/core/cuda/misHelpers.cu b/src/core/cuda/misHelpers.cu index 264c3d1..5d5768b 100644 --- a/src/core/cuda/misHelpers.cu +++ b/src/core/cuda/misHelpers.cu @@ -1145,7 +1145,7 @@ void misHelpers::checkPartConnectivity(int partCount, IdxVector_d partition, Idx { // Debugging check on part connectivity: std::cout << message << "\n"; - vector nodesToExplore, exploredNodes; + std::vector nodesToExplore, exploredNodes; for(int i = 0; i < partCount; i++) { nodesToExplore.clear(); diff --git a/src/core/cuda/randMIS.cu b/src/core/cuda/randMIS.cu index 88a2119..3490dcc 100644 --- a/src/core/cuda/randMIS.cu +++ b/src/core/cuda/randMIS.cu @@ -6,1012 +6,1001 @@ #include #include #include -using namespace std; template void RandMIS_Aggregator::computePermutation(TetMesh* meshPtr, IdxVector_h &permutation, IdxVector_h &ipermutation, IdxVector_h &aggregateIdx, IdxVector_h &partitionIdx, int* partitionlabel, int* nnout, int* &xadjout, int* &adjncyout, int metissize) { - // Getting the neighbors for the mesh - meshPtr->need_neighbors(); - - // Vertex count: - int nn = meshPtr->vertices.size(); - - // Counting up edges for adjacency: - int edgeCount = 0; - for(int vIt = 0; vIt < nn; vIt++) - { - edgeCount += meshPtr->neighbors[vIt].size(); - } - - //Allocating storage for array values of adjacency - int* xadj = new int[nn + 1]; - int* adjncy = new int[edgeCount]; - - // filling the arrays: - xadj[0] = 0; - int idx = 0; - - // Populating the arrays: - for(int i = 1; i < nn + 1; i++) - { - xadj[i] = xadj[i - 1] + meshPtr->neighbors[i - 1].size(); - for(int j = 0; j < meshPtr->neighbors[i - 1].size(); j++) - { - adjncy[idx++] = meshPtr->neighbors[i - 1][j]; - } - } - - // Calling the other override to finish: - computePermutation(nn, xadj, adjncy, permutation, ipermutation, aggregateIdx, partitionIdx, partitionlabel, nnout, xadjout, adjncyout, metissize); - - // Freeing up memories: - delete [] xadj; - delete [] adjncy; + // Getting the neighbors for the mesh + meshPtr->need_neighbors(); + + // Vertex count: + int nn = meshPtr->vertices.size(); + + // Counting up edges for adjacency: + int edgeCount = 0; + for (int vIt = 0; vIt < nn; vIt++) + { + edgeCount += meshPtr->neighbors[vIt].size(); + } + + //Allocating storage for array values of adjacency + int* xadj = new int[nn + 1]; + int* adjncy = new int[edgeCount]; + + // filling the arrays: + xadj[0] = 0; + int idx = 0; + + // Populating the arrays: + for (int i = 1; i < nn + 1; i++) + { + xadj[i] = xadj[i - 1] + meshPtr->neighbors[i - 1].size(); + for (int j = 0; j < meshPtr->neighbors[i - 1].size(); j++) + { + adjncy[idx++] = meshPtr->neighbors[i - 1][j]; + } + } + + // Calling the other override to finish: + computePermutation(nn, xadj, adjncy, permutation, ipermutation, aggregateIdx, partitionIdx, partitionlabel, nnout, xadjout, adjncyout, metissize); + + // Freeing up memories: + delete[] xadj; + delete[] adjncy; } template void RandMIS_Aggregator::computePermutation(TriMesh* meshPtr, IdxVector_h &permutation, IdxVector_h &ipermutation, IdxVector_h &aggregateIdx, IdxVector_h &partitionIdx, int* partitionlabel, int* nnout, int* &xadjout, int* &adjncyout, int metissize) { - // Getting the neighbors for the mesh - meshPtr->need_neighbors(); + // Getting the neighbors for the mesh + meshPtr->need_neighbors(); - // Vertex count: - int nn = meshPtr->vertices.size(); + // Vertex count: + int nn = meshPtr->vertices.size(); - // Counting up edges for adjacency: - int edgeCount = 0; - for(int vIt = 0; vIt < nn; vIt++) - { - edgeCount += meshPtr->neighbors[vIt].size(); - } + // Counting up edges for adjacency: + int edgeCount = 0; + for (int vIt = 0; vIt < nn; vIt++) + { + edgeCount += meshPtr->neighbors[vIt].size(); + } - //Allocating storage for array values of adjacency - int* xadj = new int[nn + 1]; - int* adjncy = new int[edgeCount]; + //Allocating storage for array values of adjacency + int* xadj = new int[nn + 1]; + int* adjncy = new int[edgeCount]; - // filling the arrays: - xadj[0] = 0; - int idx = 0; + // filling the arrays: + xadj[0] = 0; + int idx = 0; - // Populating the arrays: - for(int i = 1; i < nn + 1; i++) - { - xadj[i] = xadj[i - 1] + meshPtr->neighbors[i - 1].size(); - for(int j = 0; j < meshPtr->neighbors[i - 1].size(); j++) - { - adjncy[idx++] = meshPtr->neighbors[i - 1][j]; - } - } + // Populating the arrays: + for (int i = 1; i < nn + 1; i++) + { + xadj[i] = xadj[i - 1] + meshPtr->neighbors[i - 1].size(); + for (int j = 0; j < meshPtr->neighbors[i - 1].size(); j++) + { + adjncy[idx++] = meshPtr->neighbors[i - 1][j]; + } + } - // Calling the other override to finish: - computePermutation(nn, xadj, adjncy, permutation, ipermutation, aggregateIdx, partitionIdx, partitionlabel, nnout, xadjout, adjncyout, metissize); + // Calling the other override to finish: + computePermutation(nn, xadj, adjncy, permutation, ipermutation, aggregateIdx, partitionIdx, partitionlabel, nnout, xadjout, adjncyout, metissize); - // Freeing up memories: - delete [] xadj; - delete [] adjncy; + // Freeing up memories: + delete[] xadj; + delete[] adjncy; } template void RandMIS_Aggregator::computePermutation(int nn, int* xadj, int* adjncy, IdxVector_h &permutation, IdxVector_h &ipermutation, IdxVector_h &aggregateIdx, IdxVector_h &partitionIdx, int* partitionlabel, int* nnout, int* &xadjout, int* &adjncyout, int metissize) { - // Starting off by finding a fine aggregation of the mesh - int *fineAggregate = new int[nn]; - // get the initial depth from parameter - int depth = metissize / 10; - int finePartCount; - extendedMIS(nn, depth, xadj, adjncy, fineAggregate, &finePartCount); - - // Building the next level graph - int notNeighbor = finePartCount + 1; - int *permutedFullAdjacency = new int[xadj[nn]]; - int *initialPermutationOldToNew = new int[nn]; - int *initialPermutationNewToOld = new int[nn]; - int *permutationCheck = new int[nn]; - - int *nextAggregateOffset = new int[finePartCount + 1]; - int *tempAggregateOffset = new int[finePartCount + 1]; - int *aggregateVertexCounts = new int[finePartCount]; - int *vertexNeighborCounts = new int[nn]; - int *aggregateNeighborCounts = new int[finePartCount]; - int *vertexAdjacencyOffsets = new int[nn + 1]; - int *aggregateAdjacency = new int[finePartCount]; - int *newAdjacencyIndexes = new int[finePartCount + 1]; - int *newAdjacency; - - // Clearing aggregate counts - for(int i = 0; i < finePartCount; i++) - { - aggregateVertexCounts[i] = 0; - aggregateNeighborCounts[i] = 0; - } - - // Counting vertices in each aggregate, and total neighbors - for(int vIt = 0; vIt < nn; vIt++) - { - aggregateVertexCounts[fineAggregate[vIt]]++; - aggregateNeighborCounts[fineAggregate[vIt]] += xadj[vIt + 1] - xadj[vIt]; - } - - // Finding min/max aggregates: - int min = aggregateVertexCounts[0]; - int max = aggregateVertexCounts[0]; - for(int i = 0; i < finePartCount; i++) - { - if(aggregateVertexCounts[i] > max) - max = aggregateVertexCounts[i]; - if(aggregateVertexCounts[i] < min) - min = aggregateVertexCounts[i]; - } - //printf("There are: %d aggregates, minimum size: %d maximum size: %d\n", finePartCount, min, max); - - // Calculating the new offsets of each aggregate - nextAggregateOffset[0] = 0; - tempAggregateOffset[0] = 0; - for(int aIt = 1; aIt < finePartCount + 1; aIt++) - { - // Doing a prefix sum: - nextAggregateOffset[aIt] = nextAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; - tempAggregateOffset[aIt] = nextAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; - } - - // Filling in the initialPermutation array: - for(int vIt = 0; vIt < nn; vIt++) - { - int aggID = fineAggregate[vIt]; - initialPermutationOldToNew[vIt] = tempAggregateOffset[aggID]; - initialPermutationNewToOld[tempAggregateOffset[aggID]] = vIt; - tempAggregateOffset[aggID]++; - } - - // For testing check the permutation array for consistency - for(int vIt = 0; vIt < nn; vIt++) - { - permutationCheck[vIt] = initialPermutationOldToNew[initialPermutationNewToOld[vIt]]; - } - - - // Counting neighbors of each (permuted) node - for(int vIt = 0; vIt < nn; vIt++) - { - int oldNodeID = initialPermutationNewToOld[vIt]; - vertexNeighborCounts[vIt] = xadj[oldNodeID + 1] - xadj[oldNodeID]; - } - - // Calculating the new vertex offsets: - vertexAdjacencyOffsets[0] = 0; - for(int vIt = 1; vIt < nn + 1; vIt++) - { - vertexAdjacencyOffsets[vIt] = vertexAdjacencyOffsets[vIt - 1] + vertexNeighborCounts[vIt - 1]; - } - - // Filling in the permutedFullAdjacency - for(int vIt = 0; vIt < nn; vIt++) - { - int permIdx = initialPermutationOldToNew[vIt]; - int currentPart = fineAggregate[vIt]; - - int newOffset = vertexAdjacencyOffsets[permIdx]; - int oldOffset = xadj[vIt]; - for(int nIt = 0; nIt < vertexNeighborCounts[permIdx]; nIt++) - { - int partID = fineAggregate[adjncy[oldOffset + nIt]]; - - if(partID == currentPart) - permutedFullAdjacency[newOffset + nIt] = notNeighbor; - else - permutedFullAdjacency[newOffset + nIt] = partID; - //permutedFullAdjacency[newOffset + nIt] = adjacency[oldOffset + nIt]; - } - } - - // Sorting each aggregates neighbors (with duplicates) - for(int aIt = 0; aIt < finePartCount; aIt++) - { - int beginAddr = vertexAdjacencyOffsets[ nextAggregateOffset[aIt] ]; - int endAddr = vertexAdjacencyOffsets[ nextAggregateOffset[aIt + 1] ]; - sort(permutedFullAdjacency + beginAddr, permutedFullAdjacency + endAddr); - } - - // Setting counts to zero - for(int aIt = 0; aIt < finePartCount; aIt++) - { - aggregateAdjacency[aIt] = 1; - } - - // Counting the distinct neighbors of each aggregate: - for(int aIt = 0; aIt < finePartCount; aIt++) - { - int begin = vertexAdjacencyOffsets[ nextAggregateOffset[aIt] ]; - int end = vertexAdjacencyOffsets[ nextAggregateOffset[aIt + 1] ]; - for(int i = begin + 1; i < end; i++) - { - if(permutedFullAdjacency[i] < notNeighbor && permutedFullAdjacency[i - 1] != permutedFullAdjacency[i]) - { - permutedFullAdjacency[begin + aggregateAdjacency[aIt]] = permutedFullAdjacency[i]; - aggregateAdjacency[aIt]++; - } - } - } - - // Finding the offsets for the aggregate adjacency - newAdjacencyIndexes[0] = 0; - for(int aIt = 1; aIt < finePartCount + 1; aIt++) - { - newAdjacencyIndexes[aIt] = newAdjacencyIndexes[aIt - 1] + aggregateAdjacency[aIt - 1]; - } - - // Allocating the adjacency array - newAdjacency = new int[newAdjacencyIndexes[finePartCount]]; - - // Writing the new adjacency to the list: - for(int aIt = 0; aIt < finePartCount; aIt++) - { - int oldOffset = vertexAdjacencyOffsets[ nextAggregateOffset[aIt] ]; - int newOffset = newAdjacencyIndexes[aIt]; - for(int i = 0; i < aggregateAdjacency[aIt]; i++) + // Starting off by finding a fine aggregation of the mesh + int *fineAggregate = new int[nn]; + // get the initial depth from parameter + int depth = metissize / 10; + int finePartCount; + extendedMIS(nn, depth, xadj, adjncy, fineAggregate, &finePartCount); + + // Building the next level graph + int notNeighbor = finePartCount + 1; + int *permutedFullAdjacency = new int[xadj[nn]]; + int *initialPermutationOldToNew = new int[nn]; + int *initialPermutationNewToOld = new int[nn]; + int *permutationCheck = new int[nn]; + + int *nextAggregateOffset = new int[finePartCount + 1]; + int *tempAggregateOffset = new int[finePartCount + 1]; + int *aggregateVertexCounts = new int[finePartCount]; + int *vertexNeighborCounts = new int[nn]; + int *aggregateNeighborCounts = new int[finePartCount]; + int *vertexAdjacencyOffsets = new int[nn + 1]; + int *aggregateAdjacency = new int[finePartCount]; + int *newAdjacencyIndexes = new int[finePartCount + 1]; + int *newAdjacency; + + // Clearing aggregate counts + for (int i = 0; i < finePartCount; i++) + { + aggregateVertexCounts[i] = 0; + aggregateNeighborCounts[i] = 0; + } + + // Counting vertices in each aggregate, and total neighbors + for (int vIt = 0; vIt < nn; vIt++) + { + aggregateVertexCounts[fineAggregate[vIt]]++; + aggregateNeighborCounts[fineAggregate[vIt]] += xadj[vIt + 1] - xadj[vIt]; + } + + // Finding min/max aggregates: + int min = aggregateVertexCounts[0]; + int max = aggregateVertexCounts[0]; + for (int i = 0; i < finePartCount; i++) + { + if (aggregateVertexCounts[i] > max) + max = aggregateVertexCounts[i]; + if (aggregateVertexCounts[i] < min) + min = aggregateVertexCounts[i]; + } + //printf("There are: %d aggregates, minimum size: %d maximum size: %d\n", finePartCount, min, max); + + // Calculating the new offsets of each aggregate + nextAggregateOffset[0] = 0; + tempAggregateOffset[0] = 0; + for (int aIt = 1; aIt < finePartCount + 1; aIt++) + { + // Doing a prefix sum: + nextAggregateOffset[aIt] = nextAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; + tempAggregateOffset[aIt] = nextAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; + } + + // Filling in the initialPermutation array: + for (int vIt = 0; vIt < nn; vIt++) + { + int aggID = fineAggregate[vIt]; + initialPermutationOldToNew[vIt] = tempAggregateOffset[aggID]; + initialPermutationNewToOld[tempAggregateOffset[aggID]] = vIt; + tempAggregateOffset[aggID]++; + } + + // For testing check the permutation array for consistency + for (int vIt = 0; vIt < nn; vIt++) + { + permutationCheck[vIt] = initialPermutationOldToNew[initialPermutationNewToOld[vIt]]; + } + + + // Counting neighbors of each (permuted) node + for (int vIt = 0; vIt < nn; vIt++) + { + int oldNodeID = initialPermutationNewToOld[vIt]; + vertexNeighborCounts[vIt] = xadj[oldNodeID + 1] - xadj[oldNodeID]; + } + + // Calculating the new vertex offsets: + vertexAdjacencyOffsets[0] = 0; + for (int vIt = 1; vIt < nn + 1; vIt++) + { + vertexAdjacencyOffsets[vIt] = vertexAdjacencyOffsets[vIt - 1] + vertexNeighborCounts[vIt - 1]; + } + + // Filling in the permutedFullAdjacency + for (int vIt = 0; vIt < nn; vIt++) + { + int permIdx = initialPermutationOldToNew[vIt]; + int currentPart = fineAggregate[vIt]; + + int newOffset = vertexAdjacencyOffsets[permIdx]; + int oldOffset = xadj[vIt]; + for (int nIt = 0; nIt < vertexNeighborCounts[permIdx]; nIt++) + { + int partID = fineAggregate[adjncy[oldOffset + nIt]]; + + if (partID == currentPart) + permutedFullAdjacency[newOffset + nIt] = notNeighbor; + else + permutedFullAdjacency[newOffset + nIt] = partID; + //permutedFullAdjacency[newOffset + nIt] = adjacency[oldOffset + nIt]; + } + } + + // Sorting each aggregates neighbors (with duplicates) + for (int aIt = 0; aIt < finePartCount; aIt++) + { + int beginAddr = vertexAdjacencyOffsets[nextAggregateOffset[aIt]]; + int endAddr = vertexAdjacencyOffsets[nextAggregateOffset[aIt + 1]]; + std::sort(permutedFullAdjacency + beginAddr, permutedFullAdjacency + endAddr); + } + + // Setting counts to zero + for (int aIt = 0; aIt < finePartCount; aIt++) + { + aggregateAdjacency[aIt] = 1; + } + + // Counting the distinct neighbors of each aggregate: + for (int aIt = 0; aIt < finePartCount; aIt++) + { + int begin = vertexAdjacencyOffsets[nextAggregateOffset[aIt]]; + int end = vertexAdjacencyOffsets[nextAggregateOffset[aIt + 1]]; + for (int i = begin + 1; i < end; i++) + { + if (permutedFullAdjacency[i] < notNeighbor && permutedFullAdjacency[i - 1] != permutedFullAdjacency[i]) { - newAdjacency[newOffset + i] = permutedFullAdjacency[oldOffset + i]; + permutedFullAdjacency[begin + aggregateAdjacency[aIt]] = permutedFullAdjacency[i]; + aggregateAdjacency[aIt]++; } - } - - // Allocating an array for the block partition: - int *blockPartition = new int[finePartCount]; - int blockCount; - - // Setting the depth from parameter: - depth = metissize % 10; - - // Calling extendedMIS to get the block partition: - extendedMIS(finePartCount, depth, newAdjacencyIndexes, newAdjacency, blockPartition, &blockCount); - - // Allocating block level arrays: - int *blockAggregateCounts = new int[blockCount]; - int *blockNeighborCounts = new int[blockCount]; - int *nextBlockOffset = new int[blockCount + 1]; - int *tempBlockOffset = new int[blockCount + 1]; - int *blockPermutationOldToNew = new int[finePartCount]; - int *blockPermutationNewToOld = new int[finePartCount]; - int *permutedBlockAdjacency = new int[newAdjacencyIndexes[finePartCount]]; - int *newAggregateNeighborCounts = new int [finePartCount]; - int *aggregateAdjacencyOffsets = new int[finePartCount + 1]; - partitionIdx.resize(blockCount + 1); - - // Clearing block counts - for(int i = 0; i < blockCount; i++) - { - blockAggregateCounts[i] = 0; - blockNeighborCounts[i] = 0; - } - - // Counting aggregates in each block, and total neighbors - for(int aIt = 0; aIt < finePartCount; aIt++) - { - blockAggregateCounts[blockPartition[aIt]]++; - blockNeighborCounts[blockPartition[aIt]] += newAdjacencyIndexes[aIt + 1] - newAdjacencyIndexes[aIt]; - } - - // Calculating the new offsets of each block - nextBlockOffset[0] = 0; - tempBlockOffset[0] = 0; - for(int bIt = 1; bIt < blockCount + 1; bIt++) - { - // Doing a prefix sum: - nextBlockOffset[bIt] = nextBlockOffset[bIt - 1] + blockAggregateCounts[bIt - 1]; - tempBlockOffset[bIt] = nextBlockOffset[bIt - 1] + blockAggregateCounts[bIt - 1]; - partitionIdx[bIt] = nextBlockOffset[bIt - 1] + blockAggregateCounts[bIt - 1]; - } - - // Filling in the blockPermutation array: - for(int aIt = 0; aIt < finePartCount; aIt++) - { - int blockID = blockPartition[aIt]; - blockPermutationOldToNew[aIt] = tempBlockOffset[blockID]; - blockPermutationNewToOld[tempBlockOffset[blockID]] = aIt; - tempBlockOffset[blockID]++; - } - - // Counting neighbors of each (permuted) aggregate - for(int aIt = 0; aIt < finePartCount; aIt++) - { - int oldNodeID = blockPermutationNewToOld[aIt]; - newAggregateNeighborCounts[aIt] = newAdjacencyIndexes[oldNodeID + 1] - newAdjacencyIndexes[oldNodeID]; - } - - // Calculating the new aggregate offsets: - aggregateAdjacencyOffsets[0] = 0; - for(int aIt = 1; aIt < finePartCount + 1; aIt++) - { - aggregateAdjacencyOffsets[aIt] = aggregateAdjacencyOffsets[aIt - 1] + newAggregateNeighborCounts[aIt - 1]; - } - - // Filling in the permutedBlockAdjacency - for(int aIt = 0; aIt < finePartCount; aIt++) - { - int permIdx = blockPermutationOldToNew[aIt]; - int newOffset = aggregateAdjacencyOffsets[permIdx]; - int oldOffset = newAdjacencyIndexes[aIt]; - for(int nIt = 0; nIt < newAggregateNeighborCounts[permIdx]; nIt++) - { - // Permute the neighbor's index and write to new location in array. - permutedBlockAdjacency[newOffset + nIt] = blockPermutationOldToNew[newAdjacency[oldOffset + nIt]]; - } - } - // Finding the new permutation on the original vertices - // Reusing the original arrays as they are no longer needed. - permutation.resize(nn); - ipermutation.resize(nn); - int *permutedFineAggregate = new int[nn]; - aggregateIdx.resize(finePartCount + 1); - - // filling the permutedFineAggregate array: - for(int vIt = 0; vIt < nn; vIt++) - { - permutedFineAggregate[vIt] = blockPermutationOldToNew[ fineAggregate[vIt] ]; - } - - // Clearing aggregate counts - for(int i = 0; i < finePartCount; i++) - { - aggregateVertexCounts[i] = 0; - aggregateNeighborCounts[i] = 0; - } - - // Counting vertices in each aggregate, and total neighbors - for(int vIt = 0; vIt < nn; vIt++) - { - aggregateVertexCounts[permutedFineAggregate[vIt]]++; - } - - // Calculating the new offsets of each aggregate - tempAggregateOffset[0] = 0; - aggregateIdx[0] = 0; - for(int aIt = 1; aIt < finePartCount + 1; aIt++) - { - // Doing a prefix sum: - tempAggregateOffset[aIt] = tempAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; - aggregateIdx[aIt] = tempAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; - } - - // Filling in the finalPermutation array: - for(int vIt = 0; vIt < nn; vIt++) - { - int aggID = permutedFineAggregate[vIt]; - permutation[vIt] = tempAggregateOffset[aggID]; - ipermutation[tempAggregateOffset[aggID]] = vIt; - tempAggregateOffset[aggID]++; - } - - - // Setting values for return: - *nnout = finePartCount; - xadjout = aggregateAdjacencyOffsets; - adjncyout = permutedBlockAdjacency; - - // Setting the partitionlabel: - for(int i = 0; i < blockCount; i++) - { - int startAt = aggregateIdx[partitionIdx[i]]; - int nextBlockAt = aggregateIdx[partitionIdx[i + 1]]; - for(int j = startAt; j < nextBlockAt; j++) - partitionlabel[j] = i; - } - // Deleting the temporary arrays: - delete[] fineAggregate; - delete[] permutedFineAggregate; - delete[] blockAggregateCounts; - delete[] blockNeighborCounts; - delete[] nextBlockOffset; - delete[] tempBlockOffset; - delete[] blockPermutationOldToNew; - delete[] blockPermutationNewToOld; - delete[] newAggregateNeighborCounts; - delete[] permutedFullAdjacency; - delete[] initialPermutationOldToNew; - delete[] initialPermutationNewToOld; - delete[] permutationCheck; - delete[] nextAggregateOffset; - delete[] tempAggregateOffset; - delete[] aggregateVertexCounts; - delete[] vertexNeighborCounts; - delete[] aggregateNeighborCounts; - delete[] vertexAdjacencyOffsets; - delete[] aggregateAdjacency; - delete[] newAdjacencyIndexes; - delete[] newAdjacency; - - // And Done. - return; + } + } + + // Finding the offsets for the aggregate adjacency + newAdjacencyIndexes[0] = 0; + for (int aIt = 1; aIt < finePartCount + 1; aIt++) + { + newAdjacencyIndexes[aIt] = newAdjacencyIndexes[aIt - 1] + aggregateAdjacency[aIt - 1]; + } + + // Allocating the adjacency array + newAdjacency = new int[newAdjacencyIndexes[finePartCount]]; + + // Writing the new adjacency to the list: + for (int aIt = 0; aIt < finePartCount; aIt++) + { + int oldOffset = vertexAdjacencyOffsets[nextAggregateOffset[aIt]]; + int newOffset = newAdjacencyIndexes[aIt]; + for (int i = 0; i < aggregateAdjacency[aIt]; i++) + { + newAdjacency[newOffset + i] = permutedFullAdjacency[oldOffset + i]; + } + } + + // Allocating an array for the block partition: + int *blockPartition = new int[finePartCount]; + int blockCount; + + // Setting the depth from parameter: + depth = metissize % 10; + + // Calling extendedMIS to get the block partition: + extendedMIS(finePartCount, depth, newAdjacencyIndexes, newAdjacency, blockPartition, &blockCount); + + // Allocating block level arrays: + int *blockAggregateCounts = new int[blockCount]; + int *blockNeighborCounts = new int[blockCount]; + int *nextBlockOffset = new int[blockCount + 1]; + int *tempBlockOffset = new int[blockCount + 1]; + int *blockPermutationOldToNew = new int[finePartCount]; + int *blockPermutationNewToOld = new int[finePartCount]; + int *permutedBlockAdjacency = new int[newAdjacencyIndexes[finePartCount]]; + int *newAggregateNeighborCounts = new int[finePartCount]; + int *aggregateAdjacencyOffsets = new int[finePartCount + 1]; + partitionIdx.resize(blockCount + 1); + + // Clearing block counts + for (int i = 0; i < blockCount; i++) + { + blockAggregateCounts[i] = 0; + blockNeighborCounts[i] = 0; + } + + // Counting aggregates in each block, and total neighbors + for (int aIt = 0; aIt < finePartCount; aIt++) + { + blockAggregateCounts[blockPartition[aIt]]++; + blockNeighborCounts[blockPartition[aIt]] += newAdjacencyIndexes[aIt + 1] - newAdjacencyIndexes[aIt]; + } + + // Calculating the new offsets of each block + nextBlockOffset[0] = 0; + tempBlockOffset[0] = 0; + for (int bIt = 1; bIt < blockCount + 1; bIt++) + { + // Doing a prefix sum: + nextBlockOffset[bIt] = nextBlockOffset[bIt - 1] + blockAggregateCounts[bIt - 1]; + tempBlockOffset[bIt] = nextBlockOffset[bIt - 1] + blockAggregateCounts[bIt - 1]; + partitionIdx[bIt] = nextBlockOffset[bIt - 1] + blockAggregateCounts[bIt - 1]; + } + + // Filling in the blockPermutation array: + for (int aIt = 0; aIt < finePartCount; aIt++) + { + int blockID = blockPartition[aIt]; + blockPermutationOldToNew[aIt] = tempBlockOffset[blockID]; + blockPermutationNewToOld[tempBlockOffset[blockID]] = aIt; + tempBlockOffset[blockID]++; + } + + // Counting neighbors of each (permuted) aggregate + for (int aIt = 0; aIt < finePartCount; aIt++) + { + int oldNodeID = blockPermutationNewToOld[aIt]; + newAggregateNeighborCounts[aIt] = newAdjacencyIndexes[oldNodeID + 1] - newAdjacencyIndexes[oldNodeID]; + } + + // Calculating the new aggregate offsets: + aggregateAdjacencyOffsets[0] = 0; + for (int aIt = 1; aIt < finePartCount + 1; aIt++) + { + aggregateAdjacencyOffsets[aIt] = aggregateAdjacencyOffsets[aIt - 1] + newAggregateNeighborCounts[aIt - 1]; + } + + // Filling in the permutedBlockAdjacency + for (int aIt = 0; aIt < finePartCount; aIt++) + { + int permIdx = blockPermutationOldToNew[aIt]; + int newOffset = aggregateAdjacencyOffsets[permIdx]; + int oldOffset = newAdjacencyIndexes[aIt]; + for (int nIt = 0; nIt < newAggregateNeighborCounts[permIdx]; nIt++) + { + // Permute the neighbor's index and write to new location in array. + permutedBlockAdjacency[newOffset + nIt] = blockPermutationOldToNew[newAdjacency[oldOffset + nIt]]; + } + } + // Finding the new permutation on the original vertices + // Reusing the original arrays as they are no longer needed. + permutation.resize(nn); + ipermutation.resize(nn); + int *permutedFineAggregate = new int[nn]; + aggregateIdx.resize(finePartCount + 1); + + // filling the permutedFineAggregate array: + for (int vIt = 0; vIt < nn; vIt++) + { + permutedFineAggregate[vIt] = blockPermutationOldToNew[fineAggregate[vIt]]; + } + + // Clearing aggregate counts + for (int i = 0; i < finePartCount; i++) + { + aggregateVertexCounts[i] = 0; + aggregateNeighborCounts[i] = 0; + } + + // Counting vertices in each aggregate, and total neighbors + for (int vIt = 0; vIt < nn; vIt++) + { + aggregateVertexCounts[permutedFineAggregate[vIt]]++; + } + + // Calculating the new offsets of each aggregate + tempAggregateOffset[0] = 0; + aggregateIdx[0] = 0; + for (int aIt = 1; aIt < finePartCount + 1; aIt++) + { + // Doing a prefix sum: + tempAggregateOffset[aIt] = tempAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; + aggregateIdx[aIt] = tempAggregateOffset[aIt - 1] + aggregateVertexCounts[aIt - 1]; + } + + // Filling in the finalPermutation array: + for (int vIt = 0; vIt < nn; vIt++) + { + int aggID = permutedFineAggregate[vIt]; + permutation[vIt] = tempAggregateOffset[aggID]; + ipermutation[tempAggregateOffset[aggID]] = vIt; + tempAggregateOffset[aggID]++; + } + + + // Setting values for return: + *nnout = finePartCount; + xadjout = aggregateAdjacencyOffsets; + adjncyout = permutedBlockAdjacency; + + // Setting the partitionlabel: + for (int i = 0; i < blockCount; i++) + { + int startAt = aggregateIdx[partitionIdx[i]]; + int nextBlockAt = aggregateIdx[partitionIdx[i + 1]]; + for (int j = startAt; j < nextBlockAt; j++) + partitionlabel[j] = i; + } + // Deleting the temporary arrays: + delete[] fineAggregate; + delete[] permutedFineAggregate; + delete[] blockAggregateCounts; + delete[] blockNeighborCounts; + delete[] nextBlockOffset; + delete[] tempBlockOffset; + delete[] blockPermutationOldToNew; + delete[] blockPermutationNewToOld; + delete[] newAggregateNeighborCounts; + delete[] permutedFullAdjacency; + delete[] initialPermutationOldToNew; + delete[] initialPermutationNewToOld; + delete[] permutationCheck; + delete[] nextAggregateOffset; + delete[] tempAggregateOffset; + delete[] aggregateVertexCounts; + delete[] vertexNeighborCounts; + delete[] aggregateNeighborCounts; + delete[] vertexAdjacencyOffsets; + delete[] aggregateAdjacency; + delete[] newAdjacencyIndexes; + delete[] newAdjacency; + + // And Done. + return; } template void RandMIS_Aggregator::computePermutation_d(IdxVector_d &adjIndexesIn, - IdxVector_d &adjacencyIn, - IdxVector_d &permutation, - IdxVector_d &ipermutation, - IdxVector_d &aggregateIdx, - IdxVector_d &partitionIdx, - IdxVector_d &partitionLabel, - IdxVector_d &adjIndexesOut, - IdxVector_d &adjacencyOut, - int agg_type, - int parameters, - int part_max_size, - bool verbose) { + IdxVector_d &adjacencyIn, + IdxVector_d &permutation, + IdxVector_d &ipermutation, + IdxVector_d &aggregateIdx, + IdxVector_d &partitionIdx, + IdxVector_d &partitionLabel, + IdxVector_d &adjIndexesOut, + IdxVector_d &adjacencyOut, + int agg_type, + int parameters, + int part_max_size, + bool verbose) { if (agg_type == 0) - { - if (verbose) - printf("Calling Old MIS Aggregation method.\n"); - misHelpers::CP::OldMIS(adjIndexesIn, - adjacencyIn, - permutation, - ipermutation, - aggregateIdx, - partitionIdx, - partitionLabel, - adjIndexesOut, - adjacencyOut, - parameters, - part_max_size, - verbose); - } - else if (agg_type == 1) - { - if (verbose) - printf("Calling Metis bottom up method\n"); - misHelpers::CP::MetisBottomUp(adjIndexesIn, - adjacencyIn, - permutation, - ipermutation, - aggregateIdx, - partitionIdx, - partitionLabel, - adjIndexesOut, - adjacencyOut, - parameters, - part_max_size, - verbose); - } - else if (agg_type == 2) - { - if (verbose) - printf("Calling Metis top down method\n"); - misHelpers::CP::MetisTopDown(adjIndexesIn, - adjacencyIn, - permutation, - ipermutation, - aggregateIdx, - partitionIdx, - partitionLabel, - adjIndexesOut, - adjacencyOut, - parameters, - part_max_size, - verbose); - } - else if (agg_type == 3) - { - if (verbose) - printf("Calling AggMIS GPU method\n"); - misHelpers::CP::NewMIS(adjIndexesIn, - adjacencyIn, - permutation, - ipermutation, - aggregateIdx, - partitionIdx, - partitionLabel, - adjIndexesOut, - adjacencyOut, - parameters, - part_max_size, - verbose); - } - else if (agg_type == 4) - { - if (verbose) - printf("Calling AggMIS CPU method\n"); - misHelpers::CP::NewMIS_CPU(adjIndexesIn, - adjacencyIn, - permutation, - ipermutation, - aggregateIdx, - partitionIdx, - partitionLabel, - adjIndexesOut, - adjacencyOut, - parameters, - part_max_size, - verbose); - } - else if (agg_type == 5) - { - if (verbose) - printf("Calling AggMIS Light CPU method\n"); - misHelpers::CP::LightMIS_CPU(adjIndexesIn, - adjacencyIn, - permutation, - ipermutation, - aggregateIdx, - partitionIdx, - partitionLabel, - adjIndexesOut, - adjacencyOut, - parameters, - part_max_size, - verbose); - } - else if (verbose) - printf("Aggregation method %d not recognized!\n", agg_type); - - if (verbose) - std::cout << "Finished with RandMIS_Aggregator::computePermutation_d" << std::endl; + { + if (verbose) + printf("Calling Old MIS Aggregation method.\n"); + misHelpers::CP::OldMIS(adjIndexesIn, + adjacencyIn, + permutation, + ipermutation, + aggregateIdx, + partitionIdx, + partitionLabel, + adjIndexesOut, + adjacencyOut, + parameters, + part_max_size, + verbose); + } else if (agg_type == 1) + { + if (verbose) + printf("Calling Metis bottom up method\n"); + misHelpers::CP::MetisBottomUp(adjIndexesIn, + adjacencyIn, + permutation, + ipermutation, + aggregateIdx, + partitionIdx, + partitionLabel, + adjIndexesOut, + adjacencyOut, + parameters, + part_max_size, + verbose); + } else if (agg_type == 2) + { + if (verbose) + printf("Calling Metis top down method\n"); + misHelpers::CP::MetisTopDown(adjIndexesIn, + adjacencyIn, + permutation, + ipermutation, + aggregateIdx, + partitionIdx, + partitionLabel, + adjIndexesOut, + adjacencyOut, + parameters, + part_max_size, + verbose); + } else if (agg_type == 3) + { + if (verbose) + printf("Calling AggMIS GPU method\n"); + misHelpers::CP::NewMIS(adjIndexesIn, + adjacencyIn, + permutation, + ipermutation, + aggregateIdx, + partitionIdx, + partitionLabel, + adjIndexesOut, + adjacencyOut, + parameters, + part_max_size, + verbose); + } else if (agg_type == 4) + { + if (verbose) + printf("Calling AggMIS CPU method\n"); + misHelpers::CP::NewMIS_CPU(adjIndexesIn, + adjacencyIn, + permutation, + ipermutation, + aggregateIdx, + partitionIdx, + partitionLabel, + adjIndexesOut, + adjacencyOut, + parameters, + part_max_size, + verbose); + } else if (agg_type == 5) + { + if (verbose) + printf("Calling AggMIS Light CPU method\n"); + misHelpers::CP::LightMIS_CPU(adjIndexesIn, + adjacencyIn, + permutation, + ipermutation, + aggregateIdx, + partitionIdx, + partitionLabel, + adjIndexesOut, + adjacencyOut, + parameters, + part_max_size, + verbose); + } else if (verbose) + printf("Aggregation method %d not recognized!\n", agg_type); + + if (verbose) + std::cout << "Finished with RandMIS_Aggregator::computePermutation_d" << std::endl; } template void RandMIS_Aggregator::computePermutation_d(TriMesh *meshPtr, IdxVector_d &permutation, IdxVector_d &ipermutation, IdxVector_d &aggregateIdx, - IdxVector_d &partitionIdx, IdxVector_d &partitionLabel, IdxVector_d &adjIndexesOut, + IdxVector_d &partitionIdx, IdxVector_d &partitionLabel, IdxVector_d &adjIndexesOut, IdxVector_d &adjacencyOut, int aggregation_type, int parameters, int part_max_size, bool verbose) { - IdxVector_d adjIndexesIn, adjacencyIn; - misHelpers::getAdjacency(meshPtr, adjIndexesIn, adjacencyIn); - computePermutation_d(adjIndexesIn, adjacencyIn, permutation, ipermutation, - aggregateIdx, partitionIdx, partitionLabel, adjIndexesOut, - adjacencyOut, aggregation_type, parameters, part_max_size, verbose); + IdxVector_d adjIndexesIn, adjacencyIn; + misHelpers::getAdjacency(meshPtr, adjIndexesIn, adjacencyIn); + computePermutation_d(adjIndexesIn, adjacencyIn, permutation, ipermutation, + aggregateIdx, partitionIdx, partitionLabel, adjIndexesOut, + adjacencyOut, aggregation_type, parameters, part_max_size, verbose); } template -void RandMIS_Aggregator::computePermutation_d(TetMesh *meshPtr, +void RandMIS_Aggregator::computePermutation_d(TetMesh *meshPtr, IdxVector_d &permutation, IdxVector_d &ipermutation, IdxVector_d &aggregateIdx, IdxVector_d &partitionIdx, IdxVector_d &partitionLabel, IdxVector_d &adjIndexesOut, IdxVector_d &adjacencyOut, int aggregation_type, int parameters, int part_max_size, bool verbose) { - IdxVector_d adjIndexesIn, adjacencyIn; - misHelpers::getAdjacency(meshPtr, adjIndexesIn, adjacencyIn); - computePermutation_d(adjIndexesIn, adjacencyIn, permutation, ipermutation, - aggregateIdx, partitionIdx, partitionLabel, adjIndexesOut, adjacencyOut, - aggregation_type, parameters, part_max_size, verbose); + IdxVector_d adjIndexesIn, adjacencyIn; + misHelpers::getAdjacency(meshPtr, adjIndexesIn, adjacencyIn); + computePermutation_d(adjIndexesIn, adjacencyIn, permutation, ipermutation, + aggregateIdx, partitionIdx, partitionLabel, adjIndexesOut, adjacencyOut, + aggregation_type, parameters, part_max_size, verbose); } template void RandMIS_Aggregator::extendedMIS(int n, int partSize, int *adjIndexes, int *adjacency, int *partition, int *partCount, bool verbose) { - // If the input is too small just return a single partition - if (n < 32) - { - for (int i = 0; i < n; i++) - partition[i] = 0; - *partCount = 1; - return; - } - clock_t starttime, endtime; - starttime = clock(); - if (verbose) - printf("Beginning extended MIS call %d nodes\n", n); - // Creating a graph with edges for every distinct path less than k - vector< vector > inducedAdj(n); - - - vector clusterCounts(n); - // Every vertex - for(int vIt = 0; vIt < n; vIt++) - { - vector< vector > nodeRings(partSize); - // Add neighbors to nodeRing 0 - for(int nIt = adjIndexes[vIt]; nIt < adjIndexes[vIt + 1]; nIt++) + // If the input is too small just return a single partition + if (n < 32) + { + for (int i = 0; i < n; i++) + partition[i] = 0; + *partCount = 1; + return; + } + clock_t starttime, endtime; + starttime = clock(); + if (verbose) + printf("Beginning extended MIS call %d nodes\n", n); + // Creating a graph with edges for every distinct path less than k + std::vector< std::vector > inducedAdj(n); + + + std::vector clusterCounts(n); + // Every vertex + for (int vIt = 0; vIt < n; vIt++) + { + std::vector< std::vector > nodeRings(partSize); + // Add neighbors to nodeRing 0 + for (int nIt = adjIndexes[vIt]; nIt < adjIndexes[vIt + 1]; nIt++) + { + nodeRings[0].push_back(adjacency[nIt]); + } + + // For every level of nodeRings + for (int level = 1; level < nodeRings.size(); level++) + { + // Every node at the previous level: + for (int lowerNode = 0; lowerNode < nodeRings[level - 1].size(); lowerNode++) { - nodeRings[0].push_back(adjacency[nIt]); - } + // Every neighbor of lower nodes + int currentNode = nodeRings[level - 1][lowerNode]; + for (int nIt = adjIndexes[currentNode]; nIt < adjIndexes[currentNode + 1]; nIt++) + { + int candidate = adjacency[nIt]; + + // Checking the candidate is not the root... + if (candidate != vIt) + { + // If the node is not present in nodeRings add to current level + for (int i = 0; i <= level && candidate != -1; i++) + { + if (nodeRings[i].size() == 0) + nodeRings[i].push_back(candidate); - // For every level of nodeRings - for(int level = 1; level < nodeRings.size(); level++) - { - // Every node at the previous level: - for(int lowerNode = 0; lowerNode < nodeRings[level - 1].size(); lowerNode++) - { - // Every neighbor of lower nodes - int currentNode = nodeRings[level - 1][lowerNode]; - for(int nIt = adjIndexes[currentNode]; nIt < adjIndexes[currentNode + 1]; nIt++) + for (int j = 0; j < nodeRings[i].size(); j++) + if (nodeRings[i][j] == candidate) + candidate = -1; + } + + if (candidate != -1) { - int candidate = adjacency[nIt]; - - // Checking the candidate is not the root... - if(candidate != vIt) - { - // If the node is not present in nodeRings add to current level - for(int i = 0; i <= level && candidate != -1; i++) - { - if(nodeRings[i].size() == 0) - nodeRings[i].push_back(candidate); - - for(int j = 0; j < nodeRings[i].size(); j++) - if(nodeRings[i][j] == candidate) - candidate = -1; - } - - if(candidate != -1) - { - nodeRings[level].push_back(candidate); - } - } + nodeRings[level].push_back(candidate); } - } + } + } } + } - // Now that nodeRings are populated add edges to all nodes in upper level (k-path's) - int clusterCount = 1; - for(int i = 0; i < nodeRings.size(); i++) + // Now that nodeRings are populated add edges to all nodes in upper level (k-path's) + int clusterCount = 1; + for (int i = 0; i < nodeRings.size(); i++) + { + for (int j = 0; j < nodeRings[i].size(); j++) { - for(int j = 0; j < nodeRings[i].size(); j++) - { - inducedAdj[vIt].push_back(nodeRings[i][j]); - clusterCount++; - } + inducedAdj[vIt].push_back(nodeRings[i][j]); + clusterCount++; } - clusterCounts[vIt] = clusterCount; - } - - if (verbose) - printf("Finished generating induced graph.\n"); - - // Calculating average cluster count to determine random weighting - int totalClusterCount = 0; - int maxDegree = clusterCounts[0]; - for(int i = 0; i < clusterCounts.size(); i++) - { - totalClusterCount += clusterCounts[i]; - if(maxDegree < clusterCounts[i]) - maxDegree = clusterCounts[i]; - } - double averageClusterSize = (double)totalClusterCount / (double)clusterCounts.size(); - double probPositive = (1.0 / (averageClusterSize + 1.0)); - - if (verbose) - printf("ProbPositive = %f\n", probPositive); - - //printf("Random Weight is: %f\n", randWeight); - - // Clearing partitions: - for(int i = 0; i < n; i++) - { - partition[i] = -1; - } - - // Finding a maximal independent set randomly: - vector MIS(n, -1); - vector RandValues(n); - vector randThreshold(n); - vector rootDistance(n, -1); - - // Setting probability thresholds for each node based on degree - for(int vIt = 0; vIt < n; vIt++) - { - // The degreeFactor is the percent difference between this degree and average - // double degreeFactor = clusterCounts[vIt] - averageClusterSize; - // if (degreeFactor < 0) - // degreeFactor *= - 1; - - double degreeFactor = (double)clusterCounts[vIt] / (double)maxDegree; - degreeFactor /= averageClusterSize; - degreeFactor = 1 - degreeFactor; - - if(degreeFactor < .1) - printf("Low degreeFactor: %f degree: %d average degree: %f\n", degreeFactor, clusterCounts[vIt], averageClusterSize); - - // The threshold value is the probPositive times the degreeFactor - randThreshold[vIt] = degreeFactor * probPositive; - - if(randThreshold[vIt] > 1 || randThreshold[vIt] < 0) - printf("Random threshold out of range: %f degreeFactor = %f probPositive = %f!\n", randThreshold[vIt], degreeFactor, probPositive); - } - - if (verbose) - printf("Finished generation of random thresholds.\n"); - - bool incomplete = true; - // srand(time(NULL)); - srand(0); - int iterations = 0; - while(incomplete) - { - iterations++; - if(iterations > 10000) + } + clusterCounts[vIt] = clusterCount; + } + + if (verbose) + printf("Finished generating induced graph.\n"); + + // Calculating average cluster count to determine random weighting + int totalClusterCount = 0; + int maxDegree = clusterCounts[0]; + for (int i = 0; i < clusterCounts.size(); i++) + { + totalClusterCount += clusterCounts[i]; + if (maxDegree < clusterCounts[i]) + maxDegree = clusterCounts[i]; + } + double averageClusterSize = (double)totalClusterCount / (double)clusterCounts.size(); + double probPositive = (1.0 / (averageClusterSize + 1.0)); + + if (verbose) + printf("ProbPositive = %f\n", probPositive); + + //printf("Random Weight is: %f\n", randWeight); + + // Clearing partitions: + for (int i = 0; i < n; i++) + { + partition[i] = -1; + } + + // Finding a maximal independent set randomly: + std::vector MIS(n, -1); + std::vector RandValues(n); + std::vector randThreshold(n); + std::vector rootDistance(n, -1); + + // Setting probability thresholds for each node based on degree + for (int vIt = 0; vIt < n; vIt++) + { + // The degreeFactor is the percent difference between this degree and average + // double degreeFactor = clusterCounts[vIt] - averageClusterSize; + // if (degreeFactor < 0) + // degreeFactor *= - 1; + + double degreeFactor = (double)clusterCounts[vIt] / (double)maxDegree; + degreeFactor /= averageClusterSize; + degreeFactor = 1 - degreeFactor; + + if (degreeFactor < .1) + printf("Low degreeFactor: %f degree: %d average degree: %f\n", degreeFactor, clusterCounts[vIt], averageClusterSize); + + // The threshold value is the probPositive times the degreeFactor + randThreshold[vIt] = degreeFactor * probPositive; + + if (randThreshold[vIt] > 1 || randThreshold[vIt] < 0) + printf("Random threshold out of range: %f degreeFactor = %f probPositive = %f!\n", randThreshold[vIt], degreeFactor, probPositive); + } + + if (verbose) + printf("Finished generation of random thresholds.\n"); + + bool incomplete = true; + // srand(time(NULL)); + srand(0); + int iterations = 0; + while (incomplete) + { + iterations++; + if (iterations > 10000) + { + printf("Something seems to be going wrong with the random assignments!\n"); + for (int i = 0; i < n; i++) + partition[i] = 0; + *partCount = 1; + return; + } + // Maybe we are done? + incomplete = false; + + // Independent for loop + for (int i = 0; i < n; i++) + { + if (MIS[i] == -1) { - printf("Something seems to be going wrong with the random assignments!\n"); - for(int i = 0; i < n; i++) - partition[i] = 0; - *partCount = 1; - return; + // This should assign to a random value between 0 and 1 + double randValue = (double)rand() / (double)(RAND_MAX); + + // If the value is below the randThreshold than 1 else -1 + if (randValue < randThreshold[i]) + RandValues[i] = 1; + else + RandValues[i] = -1; + + // There is still work to do + incomplete = true; + } else if (MIS[i] == 1) + { + RandValues[i] = 1; + } else + { + RandValues[i] = -1; } - // Maybe we are done? - incomplete = false; + } - // Independent for loop - for(int i = 0; i < n; i++) + // Independent for loop + for (int i = 0; i < n && incomplete; i++) + { + if (RandValues[i] > 0) { - if(MIS[i] == -1) - { - // This should assign to a random value between 0 and 1 - double randValue = (double)rand() / (double)(RAND_MAX); - - // If the value is below the randThreshold than 1 else -1 - if(randValue < randThreshold[i]) - RandValues[i] = 1; - else - RandValues[i] = -1; - - // There is still work to do - incomplete = true; - } - else if(MIS[i] == 1) - { - RandValues[i] = 1; - } - else - { - RandValues[i] = -1; - } + bool negativeNeighbors = true; + for (int j = 0; j < inducedAdj[i].size(); j++) + { + if (RandValues[inducedAdj[i][j]] > 0) + negativeNeighbors = false; + } + if (negativeNeighbors) + { + // Mark the node as in MIS + MIS[i] = 1; + rootDistance[i] = 0; + + // Mark all neighbors as out + for (int j = 0; j < inducedAdj[i].size(); j++) + { + MIS[inducedAdj[i][j]] = 0; + //rootDistance[i] = 1; + } + } } + } + } + + if (verbose) + printf("Found a MIS of the graph in %d iterations.\n", iterations); + + + // Setting each member of the independent set to be the root of a partition + std::vector rootNodes; + int curPart = 0; + for (int i = 0; i < n; i++) + { + if (MIS[i] == 1) + { + partition[i] = curPart; + rootNodes.push_back(i); + curPart++; + } + } + + // Setting the partCount + *partCount = curPart; + + // An array to hold partition assignments to apply + int *newPartition = new int[n]; + for (int i = 0; i < n; i++) + newPartition[i] = partition[i]; + std::vector partSizes(curPart, 1); + + // Adding unpartitioned nodes to best partition for them: + incomplete = true; + int its = 0; + + // new rootDistance array + int *newRootDist = new int[n]; + for (int i = 0; i < n; i++) + newRootDist[i] = rootDistance[i]; + + while (incomplete) + { + incomplete = false; + its++; + + // If this has been going on too long: + if (its > 2 * n) + { + printf("There was an error in the node allocation section: Too many iterations!\n"); + for (int i = 0; i < n; i++) + partition[i] = 0; + *partCount = 1; + return; + } - // Independent for loop - for(int i = 0; i < n && incomplete; i++) + for (int i = 0; i < n; i++) + { + if (partition[i] == -1) { - if(RandValues[i] > 0) - { - bool negativeNeighbors = true; - for(int j = 0; j < inducedAdj[i].size(); j++) + int adjSize = adjIndexes[i + 1] - adjIndexes[i]; + // printf("adjSize is: %d\n", adjSize); + int *adjParts = new int[adjSize]; + int *adjRootDist = new int[adjSize]; + int *adjSizes = new int[adjSize]; + int *adjCounts = new int[adjSize]; + int *adjScore = new int[adjSize]; + + // Getting adjacent partitions: + for (int j = 0; j < adjSize; j++) + { + int adjacentNodePart = partition[adjacency[adjIndexes[i] + j]]; + adjParts[j] = adjacentNodePart; + + // Getting the size of the aggregate + adjSizes[j] = partSizes[adjacentNodePart]; + + // Getting the distance of the adjacent node to the root of its partition: + if (adjacentNodePart == -1) + { + adjRootDist[j] = 1000; + } else + { + adjRootDist[j] = rootDistance[adjacency[adjIndexes[i] + j]]; + } + } + + // Finding the smallest partition distance: + int smallestDistance = 1000; + int largestDistance = 0; + int largestSize = adjSizes[0]; + int smallestSize = adjSizes[0]; + for (int j = 0; j < adjSize; j++) + adjCounts[j] = 1; + for (int j = 0; j < adjSize; j++) + { + if (adjParts[j] != -1) + { + if (smallestDistance > adjRootDist[j]) { - if(RandValues[inducedAdj[i][j]] > 0) - negativeNeighbors = false; + smallestDistance = adjRootDist[j]; } - if(negativeNeighbors) + if (smallestSize > adjSizes[j]) { - // Mark the node as in MIS - MIS[i] = 1; - rootDistance[i] = 0; - - // Mark all neighbors as out - for(int j = 0; j < inducedAdj[i].size(); j++) - { - MIS[inducedAdj[i][j]] = 0; - //rootDistance[i] = 1; - } + smallestSize = adjSizes[j]; } - } - } - } - - if (verbose) - printf("Found a MIS of the graph in %d iterations.\n", iterations); - - - // Setting each member of the independent set to be the root of a partition - vector rootNodes; - int curPart = 0; - for(int i = 0; i < n; i++) - { - if(MIS[i] == 1) - { - partition[i] = curPart; - rootNodes.push_back(i); - curPart++; - } - } - - // Setting the partCount - *partCount = curPart; - - // An array to hold partition assignments to apply - int *newPartition = new int[n]; - for(int i = 0; i < n; i++) - newPartition[i] = partition[i]; - vector partSizes(curPart, 1); - - // Adding unpartitioned nodes to best partition for them: - incomplete = true; - int its = 0; - - // new rootDistance array - int *newRootDist = new int[n]; - for(int i = 0; i < n; i++) - newRootDist[i] = rootDistance[i]; - - while(incomplete) - { - incomplete = false; - its++; - - // If this has been going on too long: - if (its > 2 * n) - { - printf("There was an error in the node allocation section: Too many iterations!\n"); - for (int i = 0; i < n; i++) - partition[i] = 0; - *partCount = 1; - return; - } - - for(int i = 0; i < n; i++) - { - if(partition[i] == -1) - { - int adjSize = adjIndexes[i + 1] - adjIndexes[i]; - // printf("adjSize is: %d\n", adjSize); - int *adjParts = new int[adjSize]; - int *adjRootDist = new int[adjSize]; - int *adjSizes = new int[adjSize]; - int *adjCounts = new int[adjSize]; - int *adjScore = new int[adjSize]; - - // Getting adjacent partitions: - for(int j = 0; j < adjSize; j++) + if (adjRootDist[j] < 1000 && largestDistance < adjRootDist[j]) { - int adjacentNodePart = partition[ adjacency[adjIndexes[i] + j] ]; - adjParts[j] = adjacentNodePart; - - // Getting the size of the aggregate - adjSizes[j] = partSizes[adjacentNodePart]; - - // Getting the distance of the adjacent node to the root of its partition: - if(adjacentNodePart == -1) - { - adjRootDist[j] = 1000; - } - else - { - adjRootDist[j] = rootDistance[adjacency[adjIndexes[i] + j] ]; - } + largestDistance = adjRootDist[j]; } - - // Finding the smallest partition distance: - int smallestDistance = 1000; - int largestDistance = 0; - int largestSize = adjSizes[0]; - int smallestSize = adjSizes[0]; - for(int j = 0; j < adjSize; j++) - adjCounts[j] = 1; - for(int j = 0; j < adjSize; j++) + if (largestSize > adjSizes[j]) { - if(adjParts[j] != -1) - { - if(smallestDistance > adjRootDist[j]) - { - smallestDistance = adjRootDist[j]; - } - if(smallestSize > adjSizes[j]) - { - smallestSize = adjSizes[j]; - } - if(adjRootDist[j] < 1000 && largestDistance < adjRootDist[j]) - { - largestDistance = adjRootDist[j]; - } - if(largestSize > adjSizes[j]) - { - largestSize = adjSizes[j]; - } - - for(int jj = j + 1; jj < adjSize; jj++) - { - if(adjParts[j] == adjParts[jj] && adjCounts[j] < 3) - { - adjCounts[j]++; - adjCounts[jj]++; - } - } - } + largestSize = adjSizes[j]; } - // Calculating score factor for each entry: - double highestScore = -1; - int scoringPart = -1; - for(int j = 0; j < adjSize; j++) + for (int jj = j + 1; jj < adjSize; jj++) { - if(adjParts[j] != -1) - { - double sizeScore = 1.0 / (adjSizes[j] - smallestSize + 1); - double distScore = ((double)smallestDistance + 1) / (adjRootDist[j] + 1); - double adjScore = std::pow(0.75, 4. - static_cast(adjCounts[j])); - double totalScore = (sizeScore + distScore) * adjScore; - if(totalScore > highestScore) - { - highestScore = totalScore; - scoringPart = adjParts[j]; - } - } + if (adjParts[j] == adjParts[jj] && adjCounts[j] < 3) + { + adjCounts[j]++; + adjCounts[jj]++; + } } - - // Adding the node to best part found: - newPartition[i] = scoringPart; - if(scoringPart >= 0) + } + } + + // Calculating score factor for each entry: + double highestScore = -1; + int scoringPart = -1; + for (int j = 0; j < adjSize; j++) + { + if (adjParts[j] != -1) + { + double sizeScore = 1.0 / (adjSizes[j] - smallestSize + 1); + double distScore = ((double)smallestDistance + 1) / (adjRootDist[j] + 1); + double adjScore = std::pow(0.75, 4. - static_cast(adjCounts[j])); + double totalScore = (sizeScore + distScore) * adjScore; + if (totalScore > highestScore) { - partSizes[scoringPart]++; - newRootDist[i] = smallestDistance + 1; + highestScore = totalScore; + scoringPart = adjParts[j]; } - else - incomplete = true; - - - delete [] adjParts; - delete [] adjRootDist; - delete [] adjSizes; - delete [] adjCounts; - delete [] adjScore; - } + } + } + + // Adding the node to best part found: + newPartition[i] = scoringPart; + if (scoringPart >= 0) + { + partSizes[scoringPart]++; + newRootDist[i] = smallestDistance + 1; + } else + incomplete = true; + + + delete[] adjParts; + delete[] adjRootDist; + delete[] adjSizes; + delete[] adjCounts; + delete[] adjScore; } - - // Write changes to partition: - for(int i = 0; i < n; i++) + } + + // Write changes to partition: + for (int i = 0; i < n; i++) + { + partition[i] = newPartition[i]; + rootDistance[i] = newRootDist[i]; + } + + if (!incomplete) + { + // To store the parts that are too small: + std::vector partsToRemove; + + // Check for too small partitions + for (int i = 0; i < partSizes.size(); i++) { - partition[i] = newPartition[i]; - rootDistance[i] = newRootDist[i]; + if (partSizes[i] < 6) + { + partsToRemove.push_back(i); + incomplete = true; + } } - if(!incomplete) + if (partsToRemove.size() != partSizes.size()) { - // To store the parts that are too small: - vector partsToRemove; - - // Check for too small partitions - for(int i = 0; i < partSizes.size(); i++) - { - if(partSizes[i] < 6) + if (verbose) + printf("Starting removal of runty parts.\n"); + int originalPartCount = *partCount; + // Removing runty aggregates: + for (int i = partsToRemove.size() - 1; i > -1; i--) + { + // Unmark the partition label and rootnode dist + for (int j = 0; j < n; j++) + { + if (partition[j] == partsToRemove[i]) { - partsToRemove.push_back(i); - incomplete = true; + partition[j] = -1; + newPartition[j] = -1; + rootDistance[j] = -1; + newRootDist[j] = -1; } - } - - if (partsToRemove.size() != partSizes.size()) - { - if (verbose) - printf("Starting removal of runty parts.\n"); - int originalPartCount = *partCount; - // Removing runty aggregates: - for(int i = partsToRemove.size() - 1; i > -1; i--) + if (partition[j] > partsToRemove[i]) { - // Unmark the partition label and rootnode dist - for(int j = 0; j < n; j++) - { - if(partition[j] == partsToRemove[i]) - { - partition[j] = -1; - newPartition[j] = -1; - rootDistance[j] = -1; - newRootDist[j] = -1; - } - if(partition[j] > partsToRemove[i]) - { - partition[j] = partition[j] - 1; - newPartition[j] = newPartition[j] - 1; - } - - } - - // Remove the entry from the partSizes array - *partCount = *partCount - 1; - partSizes.erase(partSizes.begin() + partsToRemove[i]); + partition[j] = partition[j] - 1; + newPartition[j] = newPartition[j] - 1; } - if (verbose) - printf("Removed %lu undersized aggregates out of %d total. Leaving %d\n", partsToRemove.size(), originalPartCount, *partCount); - } - } + } - if(!incomplete && verbose) - { - endtime = clock(); - double duration = (double)(endtime - starttime) * 1000 / CLOCKS_PER_SEC; - printf("Finished with a call to extendedMIS in %f ms\n", duration); - printf("\t%d nodes aggregated to depth: %d \n\n", n, partSize); + // Remove the entry from the partSizes array + *partCount = *partCount - 1; + partSizes.erase(partSizes.begin() + partsToRemove[i]); + } + if (verbose) + printf("Removed %lu undersized aggregates out of %d total. Leaving %d\n", partsToRemove.size(), originalPartCount, *partCount); } - } + } + + + if (!incomplete && verbose) + { + endtime = clock(); + double duration = (double)(endtime - starttime) * 1000 / CLOCKS_PER_SEC; + printf("Finished with a call to extendedMIS in %f ms\n", duration); + printf("\t%d nodes aggregated to depth: %d \n\n", n, partSize); + } + } - delete [] newRootDist; - if (verbose) printf("GoodBye.\n"); + delete[] newRootDist; + if (verbose) printf("GoodBye.\n"); } diff --git a/src/core/cuda/smoothedMG_amg_level.cu b/src/core/cuda/smoothedMG_amg_level.cu index 279a730..1946f83 100644 --- a/src/core/cuda/smoothedMG_amg_level.cu +++ b/src/core/cuda/smoothedMG_amg_level.cu @@ -9,9 +9,6 @@ #include #include #include - -using namespace std; - template SmoothedMG_AMG_Level::SmoothedMG_AMG_Level(AMG *amg) : AMG_Level(amg) diff --git a/src/core/cuda/tetmesh.cu b/src/core/cuda/tetmesh.cu index e423935..fe53dfd 100644 --- a/src/core/cuda/tetmesh.cu +++ b/src/core/cuda/tetmesh.cu @@ -118,7 +118,7 @@ void TetMesh::need_neighbors() std::cout << "Finding vertex neighbors... " << std::endl; int nv = vertices.size(), nt = tets.size(); - vector numneighbors(nv, 0); + std::vector numneighbors(nv, 0); for(int i = 0; i < nt; i++) { numneighbors[tets[i][0]]++; @@ -152,16 +152,16 @@ void TetMesh::need_neighbors() { for(int j = 0; j < 4; j++) { - vector &me = neighbors[tets[i][j]]; + std::vector &me = neighbors[tets[i][j]]; int n1 = tets[i][(j + 1) % 4]; int n2 = tets[i][(j + 2) % 4]; int n3 = tets[i][(j + 3) % 4]; - if(find(me.begin(), me.end(), n1) == me.end()) + if( std::find(me.begin(), me.end(), n1) == me.end()) me.push_back(n1); - if(find(me.begin(), me.end(), n2) == me.end()) + if( std::find(me.begin(), me.end(), n2) == me.end()) me.push_back(n2); - if(find(me.begin(), me.end(), n3) == me.end()) + if( std::find(me.begin(), me.end(), n3) == me.end()) me.push_back(n3); } } @@ -219,19 +219,19 @@ void TetMesh::need_across_face() int v1 = tets[i][(j + 1) % 4]; int v2 = tets[i][(j + 2) % 4]; int v3 = tets[i][(j + 3) % 4]; - const vector &a1 = adjacenttets[v1]; - const vector &a2 = adjacenttets[v2]; - const vector &a3 = adjacenttets[v3]; + const std::vector &a1 = adjacenttets[v1]; + const std::vector &a2 = adjacenttets[v2]; + const std::vector &a3 = adjacenttets[v3]; for(int k1 = 0; k1 < a1.size(); k1++) { int other = a1[k1]; if(other == i) continue; - vector::const_iterator it = - find(a2.begin(), a2.end(), other); + std::vector::const_iterator it = + std::find(a2.begin(), a2.end(), other); - vector::const_iterator it2 = - find(a3.begin(), a3.end(), other); + std::vector::const_iterator it2 = + std::find(a3.begin(), a3.end(), other); if(it == a2.end() || it2 == a3.end()) continue; @@ -249,7 +249,7 @@ void TetMesh::need_across_face() } TetMesh *TetMesh::read(const char *nodefilename, - const char* elefilename, const bool zero_based, const bool verb) { + const char* elefilename, const bool verb) { TetMesh *mesh = new TetMesh(); mesh->set_verbose(verb); std::ifstream nodefile(nodefilename); @@ -273,11 +273,6 @@ TetMesh *TetMesh::read(const char *nodefilename, break; } mesh->vertices.resize(nv); - int invalidNodeReferenceValue; - if( zero_based ) - invalidNodeReferenceValue = nv; - else - invalidNodeReferenceValue = 0; //get the nodes size_t i = 0; @@ -315,6 +310,7 @@ TetMesh *TetMesh::read(const char *nodefilename, mesh->matlabels.resize(ne, 0); i = 0; + bool zero_based = false; //get the elements while (elefile.good()) { @@ -343,11 +339,9 @@ TetMesh *TetMesh::read(const char *nodefilename, for (j = 0; j < 4; ++j) { - if( tval[j] == invalidNodeReferenceValue ) + if( tval[j] == 0 ) { - std::cerr << "Node reference error in elements file at element # " << i; - std::cerr << ". Check if file is zero or one-based." << std::endl; - exit(0); + zero_based = true; } } diff --git a/src/core/include/Color.h b/src/core/include/Color.h index 57d5e58..9860cc2 100644 --- a/src/core/include/Color.h +++ b/src/core/include/Color.h @@ -11,10 +11,6 @@ Random class for encapsulating colors... #include "Vec.h" #include #include -using std::fmod; -using std::floor; -using std::min; -using std::max; #ifndef M_PI # define M_PI 3.14159265358979323846 #endif @@ -88,7 +84,7 @@ class Color : public Vec<3,double> { if (h < 0.0) h += (float)(2.0 * M_PI); h /= (float)(M_PI / 3.0); - int i = int(floor(h)); + int i = int(std::floor(h)); float f = h - i; float p = v * (1.0f - s); float q = v * (1.0f - (s*f)); diff --git a/src/core/include/TriMesh.h b/src/core/include/TriMesh.h index 649ee59..96a5c07 100644 --- a/src/core/include/TriMesh.h +++ b/src/core/include/TriMesh.h @@ -23,7 +23,6 @@ Class for triangle meshes. #include #include #include -using std::vector; #define PI 3.1415927 @@ -141,60 +140,60 @@ class TriMesh char* filenamepre; // The basics: vertices and faces - vector vertices; - vector faces; + std::vector vertices; + std::vector faces; // Triangle strips - vector tstrips; + std::vector tstrips; // Grid, if present - vector grid; + std::vector grid; int grid_width, grid_height; // Other per-vertex properties - vector colors; - vector confidences; - vector flags; + std::vector colors; + std::vector confidences; + std::vector flags; unsigned flag_curr; // Computed per-vertex properties - vector normals; - vector pdir1, pdir2; - vector curv1, curv2; - vector< Vec < 4, double> > dcurv; - vector cornerareas; - vector pointareas; - vector vertT; + std::vector normals; + std::vector pdir1, pdir2; + std::vector curv1, curv2; + std::vector< Vec < 4, double> > dcurv; + std::vector cornerareas; + std::vector pointareas; + std::vector vertT; // Bounding structures BBox bbox; BSphere bsphere; - vector< vector > faceVirtualFaces; + std::vector< std::vector > faceVirtualFaces; // Connectivity structures: // For each vertex, all neighboring vertices - vector< vector > neighbors; + std::vector< std::vector > neighbors; - vector< vector > NonObtuseNeighborFaces; + std::vector< std::vector > NonObtuseNeighborFaces; // For each vertex, all neighboring faces - vector< vector > adjacentfaces; + std::vector< std::vector > adjacentfaces; // For each face, the three faces attached to its edges // (for example, across_edge[3][2] is the number of the face // that's touching the edge opposite vertex 2 of face 3) - vector across_edge; + std::vector across_edge; - vector< vector > stiffMat; - vector< vector > massMat; - vector< vector > forceMat; - vector< vector > FEMMat; - vector< double > GlobalForce; - vector< vector > linearBaseCoeff; - vector< vector > GlobalFEMMat; //stored in COO format!! - vector< double > eleMaterial; + std::vector< std::vector > stiffMat; + std::vector< std::vector > massMat; + std::vector< std::vector > forceMat; + std::vector< std::vector > FEMMat; + std::vector< double > GlobalForce; + std::vector< std::vector > linearBaseCoeff; + std::vector< std::vector > GlobalFEMMat; //stored in COO format!! + std::vector< double > eleMaterial; // Compute all this stuff... void need_tstrips(); @@ -284,7 +283,7 @@ class TriMesh // FIM: given a vertex, find an all-acute neighborhood of faces - void SplitFace(vector &acFaces, int v, Face cf, int nfAdj) + void SplitFace(std::vector &acFaces, int v, Face cf, int nfAdj) { // get all the four vertices in order /* v1 v4 @@ -393,15 +392,15 @@ class TriMesh // FIM: one ring function - vector GetOneRing(int v) + std::vector GetOneRing(int v) { // make sure we have the across-edge map if (this->across_edge.empty()) this->need_across_edge(); // variables required - vector oneRingFaces; - vector t_faces; + std::vector oneRingFaces; + std::vector t_faces; // get adjacent faces size_t naf = this->adjacentfaces[v].size(); @@ -450,7 +449,7 @@ class TriMesh this->vertT.push_back(LARGENUM); //modified from this->vertT[v] = 1000000.0) } - //vector nb; + //std::vector nb; // initialize seed points if present... if (!seeds.empty()) diff --git a/src/core/include/Vec.h b/src/core/include/Vec.h index 006a1b7..9842faa 100644 --- a/src/core/include/Vec.h +++ b/src/core/include/Vec.h @@ -49,11 +49,6 @@ fract, clamp, mix, step, smoothstep, and trinorm #include #include #include -using std::min; -using std::max; -using std::swap; -using std::sqrt; - // Let gcc optimize conditional branches a bit better... #ifndef likely @@ -403,7 +398,7 @@ static inline const T len2(const Vec &v) template static inline const T len(const Vec &v) { - return sqrt(len2(v)); + return std::sqrt(len2(v)); } template @@ -418,7 +413,7 @@ static inline const T dist2(const Vec &v1, const Vec &v2) template static inline const T dist(const Vec &v1, const Vec &v2) { - return sqrt(dist2(v1,v2)); + return std::sqrt(dist2(v1,v2)); } template @@ -443,7 +438,7 @@ template static inline void swap(const Vec &v1, const Vec &v2) { for (int i = 0; i < D; i++) - swap(v1[i], v2[i]); + std::swap(v1[i], v2[i]); } template diff --git a/src/core/include/my_timer.h b/src/core/include/my_timer.h index 2aba38f..f4a7031 100644 --- a/src/core/include/my_timer.h +++ b/src/core/include/my_timer.h @@ -50,10 +50,6 @@ double inline CLOCK() { typedef std::map Event; typedef std::map::iterator Eiter; -using std::cout; -using std::endl; -using std::setw; - class levelProfile { private: #ifdef PROFILE diff --git a/src/core/include/smoothedMG/smoothedMG_amg_level.h b/src/core/include/smoothedMG/smoothedMG_amg_level.h index 71e2ae7..65a3f00 100644 --- a/src/core/include/smoothedMG/smoothedMG_amg_level.h +++ b/src/core/include/smoothedMG/smoothedMG_amg_level.h @@ -9,8 +9,6 @@ template class SmoothedMG_AMG_Level; #include #include -using namespace std; - /*************************************************** * Classical AMG Base Class * Defines the AMG solve algorithm, decendents must diff --git a/src/core/include/tetmesh.h b/src/core/include/tetmesh.h index c028ef5..3b4d4cc 100644 --- a/src/core/include/tetmesh.h +++ b/src/core/include/tetmesh.h @@ -23,8 +23,6 @@ #include #include #include -using std::vector; - class TetMesh { @@ -91,17 +89,17 @@ class TetMesh }; // The basics: vertices and faces - vector vertices; - vector tets; - vector matlabels; + std::vector vertices; + std::vector tets; + std::vector matlabels; // Connectivity structures: // For each vertex, all neighboring vertices - vector< vector > neighbors; + std::vector< std::vector > neighbors; // For each vertex, all neighboring faces - vector< vector > adjacenttets; - vector across_face; + std::vector< std::vector > adjacenttets; + std::vector across_face; - vector radiusInscribe; + std::vector radiusInscribe; void need_meshquality(); @@ -130,8 +128,7 @@ class TetMesh // zero_based: set to true if the element numbers in the file are zero- // based (defaults to false). // verbose: set to true for verbose output - static TetMesh *read(const char *nodefilename, const char* elefilename, - const bool zero_based = false, const bool verbose = false); + static TetMesh *read(const char *nodefilename, const char* elefilename, const bool verbose = false); //void write(const char *filename); // Debugging printout, controllable by a "verbose"ness parameter diff --git a/src/examples/example1.cu b/src/examples/example1.cu index d9bd184..5aa8c18 100644 --- a/src/examples/example1.cu +++ b/src/examples/example1.cu @@ -19,7 +19,6 @@ int main(int argc, char** argv) //Our main configuration object. We will set aspects where the // default values are not what we desire. FEMSolver cfg; - bool zero_based = false; std::string Aname = "", bName; cfg.filename_ = "../src/test/test_data/CubeMesh_size256step16"; for (int i = 0; i < argc; i++) { @@ -37,8 +36,6 @@ int main(int argc, char** argv) if (i + 1 >= argc) break; Aname = std::string(argv[i + 1]); i++; - } else if (strcmp(argv[i], "-z") == 0) { - zero_based = true; } } //assuming our device is zero... @@ -63,7 +60,7 @@ int main(int argc, char** argv) //read in the Tetmesh cfg.tetMesh_ = TetMesh::read( (cfg.filename_ + ".node").c_str(), - (cfg.filename_ + ".ele").c_str(), zero_based, cfg.verbose_); + (cfg.filename_ + ".ele").c_str(), cfg.verbose_); //The stiffness matrix A Matrix_ell_h A_h; if (Aname.empty()) { diff --git a/src/test/sanity.cc b/src/test/sanity.cc index 2a6c092..94b4a99 100644 --- a/src/test/sanity.cc +++ b/src/test/sanity.cc @@ -10,7 +10,7 @@ TEST(SanityTests, EggCarton) { cfg.verbose_ = true; cfg.tetMesh_ = TetMesh::read( (cfg.filename_ + ".node").c_str(), - (cfg.filename_ + ".ele").c_str(), true, cfg.verbose_); + (cfg.filename_ + ".ele").c_str(), cfg.verbose_); cfg.maxLevels_ = 100; cfg.maxIters_ = 100; cfg.preInnerIters_ = 5;