Working volume parallel BD version.

This commit is contained in:
Petar Hritov 2020-07-03 11:40:47 +01:00
parent 40090351a7
commit 1ed02d151f
2 changed files with 223 additions and 438 deletions

@ -716,6 +716,7 @@ public:
supernodeSorter,
process_contourtree_inc_ns::SuperNodeBranchComparator(whichBranch, contourTree.Supernodes));
timer.Stop();
if (printTime >= 2)
{
@ -785,8 +786,8 @@ public:
PrintIndices("Branch Parent", branchParent);
#endif
timer.Reset();
timer.Start();
//timer.Reset();
//timer.Start();
vtkm::worklet::contourtree_augmented::process_contourtree_inc::BranchSaddleParentSet
branchSaddleParentSetWorklet;
@ -799,12 +800,15 @@ public:
branchSaddle,
branchParent);
timer.Stop();
if (printTime >= 2)
{
//std::cout << "----------------//---------------- Branch parents & Saddles setting " << timer.GetElapsedTime() << " seconds." << std::endl;
printf("%.6f for Branch parents & Saddles setting.\n", timer.GetElapsedTime());
}
//return ;
//timer.Stop();
//if (printTime >= 2)
//{
////std::cout << "----------------//---------------- Branch parents & Saddles setting " << timer.GetElapsedTime() << " seconds." << std::endl;
//printf("%.6f for Branch parents & Saddles setting.\n", timer.GetElapsedTime());
//}
#ifdef DEBUG_PRINT
std::cout << "VII. Branches Constructed" << std::endl;
@ -844,232 +848,157 @@ public:
dataFieldIsSorted);
}
void static findMinMaxParallel(const IdArrayType supernodes,
const cont::ArrayHandle<Vec<Id, 2>> tourEdges,
const bool isMin,
IdArrayType minMaxIndex,
IdArrayType parents)
{
//
// Set up some useful portals
//
auto parentsPortal = parents.WritePortal();
auto tourEdgesPortal = tourEdges.ReadPortal();
//
// Set initial values
//
Id root = tourEdgesPortal.Get(0)[0];
parentsPortal.Set(root, root);
//
// Find what the first and last occurence of a vertex is in the euler tour.
//
cont::ArrayHandle<vtkm::Pair<Id, Id>> firstLastVertex;
firstLastVertex.Allocate(supernodes.GetNumberOfValues());
for (int i = 0; i < firstLastVertex.GetNumberOfValues(); i++)
{
firstLastVertex.WritePortal().Set(i,
{ (vtkm::Id)NO_SUCH_ELEMENT, (vtkm::Id)NO_SUCH_ELEMENT });
}
auto firstLastVertexPortal = firstLastVertex.WritePortal();
for (int i = 0; i < tourEdges.GetNumberOfValues(); i++)
{
// Forward Edge
if (firstLastVertexPortal.Get(tourEdgesPortal.Get(i)[1]).first == NO_SUCH_ELEMENT)
{
//printf("The parent of %d is %d.\n", tourEdges[i][1], tourEdges[i][0]);
parentsPortal.Set(tourEdgesPortal.Get(i)[1], tourEdgesPortal.Get(i)[0]);
//firstLastVertex[tourEdges.Get(i)[1]].first = i;
firstLastVertexPortal.Set(
tourEdgesPortal.Get(i)[1],
{ i, firstLastVertexPortal.Get(tourEdgesPortal.Get(i)[1]).second });
}
//firstLastVertex[tourEdges.Get(i)[0]].second = i;
firstLastVertexPortal.Set(tourEdgesPortal.Get(i)[1],
{ firstLastVertexPortal.Get(tourEdgesPortal.Get(i)[1]).first, i });
}
firstLastVertexPortal.Set(root, { 0, supernodes.GetNumberOfValues() - 1 });
//
// For every vertex look at the subrray between the first and last occurence and find the min/max values in it
//
vtkm::worklet::contourtree_augmented::process_contourtree_inc::ComputeMinMaxValues
computeMinMax(isMin);
vtkm::cont::Invoker Invoke;
Invoke(computeMinMax, supernodes, firstLastVertex, tourEdges, minMaxIndex);
}
void static findMinMax(const IdArrayType::ReadPortalType supernodes,
const cont::ArrayHandle<Vec<Id, 2>>::ReadPortalType tourEdges,
const bool isMin,
IdArrayType::WritePortalType minMaxIndex,
IdArrayType::WritePortalType parents)
{
Id root = tourEdges.Get(0)[0];
struct VertexData
{
long long distance;
unsigned long index;
};
std::vector<VertexData> vertexData(static_cast<unsigned long>(supernodes.GetNumberOfValues()),
{ -1, 0 });
for (unsigned long i = 0; i < vertexData.size(); i++)
{
vertexData[i].index = i;
}
parents.Set(root, root);
vertexData[static_cast<unsigned long>(root)].distance = 0;
for (int i = 0; i < tourEdges.GetNumberOfValues(); i++)
{
const Vec<Id, 2> e = tourEdges.Get(i);
if (-1 == vertexData[static_cast<unsigned long>(e[1])].distance)
{
parents.Set(e[1], e[0]);
vertexData[static_cast<unsigned long>(e[1])].distance =
vertexData[static_cast<unsigned long>(e[0])].distance + 1;
}
}
std::sort(vertexData.begin(), vertexData.end(), [](const VertexData& a, const VertexData& b) {
return a.distance > b.distance;
});
for (int i = 0; i < minMaxIndex.GetNumberOfValues(); i++)
{
minMaxIndex.Set(i, i);
}
for (unsigned int i = 0; i < vertexData.size(); i++)
{
Id vertex = static_cast<Id>(vertexData[i].index);
Id parent = parents.Get(vertex);
Id vertexValue = MaskedIndex(supernodes.Get(minMaxIndex.Get(vertex)));
Id parentValue = MaskedIndex(supernodes.Get(minMaxIndex.Get(parent)));
if ((true == isMin && vertexValue < parentValue) ||
(false == isMin && vertexValue > parentValue))
{
minMaxIndex.Set(parent, minMaxIndex.Get(vertex));
}
}
}
// routine to compute the branch decomposition by volume
void static ComputeHeightBranchDecomposition(const ContourTree& contourTree,
const cont::ArrayHandle<Float64> fieldValues,
const IdArrayType& ctSortOrder,
const bool useParallelMinMaxSearch,
IdArrayType& whichBranch,
IdArrayType& branchMinimum,
IdArrayType& branchMaximum,
IdArrayType& branchSaddle,
IdArrayType& branchParent)
void static ComputeVolumeBranchDecompositionNew(const ContourTree& contourTree,
const cont::ArrayHandle<Float64> fieldValues,
const IdArrayType& ctSortOrder,
const int printTime,
const vtkm::Id nIterations,
IdArrayType& whichBranch,
IdArrayType& branchMinimum,
IdArrayType& branchMaximum,
IdArrayType& branchSaddle,
IdArrayType& branchParent)
{ // ComputeHeightBranchDecomposition()
// Cache the number of non-root supernodes & superarcs
// STEP 1. Compute the number of nodes in every superarc
IdArrayType superarcIntrinsicWeight;
superarcIntrinsicWeight.Allocate(contourTree.Superarcs.GetNumberOfValues());
IdArrayType firstVertexForSuperparent;
firstVertexForSuperparent.Allocate(contourTree.Superarcs.GetNumberOfValues());
auto nodesPortal = contourTree.Nodes.ReadPortal();
auto superparentsPortal = contourTree.Superparents.ReadPortal();
auto superarcIntrinsicWeightPortal = superarcIntrinsicWeight.WritePortal();
auto firstVertexForSuperparentPortal = firstVertexForSuperparent.WritePortal();
for (vtkm::Id sortedNode = 0; sortedNode < contourTree.Arcs.GetNumberOfValues(); sortedNode++)
{ // per node in sorted order
vtkm::Id sortID = nodesPortal.Get(sortedNode);
vtkm::Id superparent = superparentsPortal.Get(sortID);
if (sortedNode == 0)
{
firstVertexForSuperparentPortal.Set(superparent, sortedNode);
}
else if (superparent != superparentsPortal.Get(nodesPortal.Get(sortedNode - 1)))
{
firstVertexForSuperparentPortal.Set(superparent, sortedNode);
}
} // per node in sorted order
// Compute the number of regular nodes on every superarc
for (vtkm::Id superarc = 0; superarc < contourTree.Superarcs.GetNumberOfValues(); superarc++)
{
if (superarc == contourTree.Superarcs.GetNumberOfValues() - 1)
{
superarcIntrinsicWeightPortal.Set(superarc,
contourTree.Arcs.GetNumberOfValues() -
firstVertexForSuperparentPortal.Get(superarc));
}
else
{
superarcIntrinsicWeightPortal.Set(superarc,
firstVertexForSuperparentPortal.Get(superarc + 1) -
firstVertexForSuperparentPortal.Get(superarc));
}
}
//// Cache the number of non-root supernodes & superarcs
vtkm::Id nSupernodes = contourTree.Supernodes.GetNumberOfValues();
auto noSuchElementArray =
vtkm::cont::ArrayHandleConstant<vtkm::Id>((vtkm::Id)NO_SUCH_ELEMENT, nSupernodes);
// STAGE I: Find the upward and downwards weight for each superarc, and set up arrays
IdArrayType bestUpward;
IdArrayType bestDownward;
//// Set up bestUpward and bestDownward array, these are the things we want to compute in this routine.
IdArrayType bestUpward, bestDownward;
vtkm::cont::ArrayCopy(noSuchElementArray, bestUpward);
vtkm::cont::ArrayCopy(noSuchElementArray, bestDownward);
//
// Compute Euler Tours
//
cont::ArrayHandle<Vec<Id, 2>> minTourEdges, maxTourEdges;
//// We initiale with the weight of the superarcs, once we sum those up we'll get the hypersweep weight
IdArrayType sumValues;
vtkm::cont::ArrayCopy(superarcIntrinsicWeight, sumValues);
minTourEdges.Allocate(2 * (nSupernodes - 1));
maxTourEdges.Allocate(2 * (nSupernodes - 1));
// Compute the Euler Tour
process_contourtree_inc_ns::EulerTour tour;
tour.computeEulerTour(contourTree.Superarcs.ReadPortal());
//// This should be 0 here, because we're not changing the root
vtkm::cont::ArrayHandle<vtkm::Id> howManyUsed;
vtkm::cont::ArrayCopy(
vtkm::cont::ArrayHandleConstant<vtkm::Id>(0, contourTree.Hyperarcs.GetNumberOfValues()),
howManyUsed);
// Reroot the Euler Tour at the global min
tour.getTourAtRoot(MaskedIndex(contourTree.Superparents.ReadPortal().Get(0)),
minTourEdges.WritePortal());
////
//// Min Hypersweep
////
const auto sumOperator = vtkm::Sum();
// Reroot the Euler Tour at the global max
tour.getTourAtRoot(MaskedIndex(contourTree.Superparents.ReadPortal().Get(
contourTree.Nodes.GetNumberOfValues() - 1)),
maxTourEdges.WritePortal());
vtkm::cont::Timer hypersweepTimer;
hypersweepTimer.Start();
//
// Compute Min/Max per subtree
//
IdArrayType minValues, minParents, maxValues, maxParents;
vtkm::cont::ArrayCopy(noSuchElementArray, minValues);
vtkm::cont::ArrayCopy(noSuchElementArray, minParents);
vtkm::cont::ArrayCopy(noSuchElementArray, maxValues);
vtkm::cont::ArrayCopy(noSuchElementArray, maxParents);
hyperarcScan<decltype(vtkm::Sum())>(contourTree.Supernodes,
contourTree.Hypernodes,
contourTree.Hyperarcs,
contourTree.Hyperparents,
contourTree.Hyperparents,
contourTree.WhenTransferred,
howManyUsed,
nIterations,
vtkm::Sum(),
sumValues);
// Finding the min/max for every subtree can either be done in parallel or serial
// The parallel implementation is not work efficient and will not work well on a single/few cores
// This is why I have left the option to do a BFS style search in serial instead of doing an a prefix min/max for every subtree in the euler tour
if (false == useParallelMinMaxSearch)
vtkm::cont::ArrayHandle<vtkm::worklet::contourtree_augmented::EdgeDataVolume> arcs;
arcs.Allocate(contourTree.Superarcs.GetNumberOfValues() * 2 - 2);
vtkm::Id totalVolume = contourTree.Nodes.GetNumberOfValues();
for (int i = 0; i < contourTree.Supernodes.GetNumberOfValues(); i++)
{
ProcessContourTree::findMinMax(contourTree.Supernodes.ReadPortal(),
minTourEdges.ReadPortal(),
true,
minValues.WritePortal(),
minParents.WritePortal());
Id parent = MaskedIndex(contourTree.Superarcs.ReadPortal().Get(i));
ProcessContourTree::findMinMax(contourTree.Supernodes.ReadPortal(),
maxTourEdges.ReadPortal(),
false,
maxValues.WritePortal(),
maxParents.WritePortal());
}
else
{
ProcessContourTree::findMinMaxParallel(
contourTree.Supernodes, minTourEdges, true, minValues, minParents);
if (parent == 0)
continue;
ProcessContourTree::findMinMaxParallel(
contourTree.Supernodes, maxTourEdges, false, maxValues, maxParents);
EdgeDataVolume edge;
edge.i = i;
edge.j = parent;
edge.upEdge = IsAscending((contourTree.Superarcs.ReadPortal().Get(i)));
//edge.subtreeVolume = sumValues.ReadPortal().Get(i);
edge.subtreeVolume = (totalVolume - sumValues.ReadPortal().Get(i)) +
(superarcIntrinsicWeight.ReadPortal().Get(i) - 1);
EdgeDataVolume oppositeEdge;
oppositeEdge.i = parent;
oppositeEdge.j = i;
oppositeEdge.upEdge = !edge.upEdge;
//oppositeEdge.subtreeVolume = (totalVolume - sumValues.ReadPortal().Get(i)) + (superarcIntrinsicWeight.ReadPortal().Get(i) - 1);
oppositeEdge.subtreeVolume = sumValues.ReadPortal().Get(i);
//std::cout << "The edge " << edge.i << ", " << edge.j << " has sum value " << edge.subtreeVolume << std::endl;
//std::cout << "The edge " << oppositeEdge.i << ", " << oppositeEdge.j << " has sum value " << oppositeEdge.subtreeVolume << std::endl;
arcs.WritePortal().Set(i * 2, edge);
arcs.WritePortal().Set(i * 2 + 1, oppositeEdge);
}
//
// Compute bestUp and bestDown
//
vtkm::worklet::contourtree_augmented::process_contourtree_inc::ComputeBestUpDown
bestUpDownWorklet;
vtkm::cont::Algorithm::Sort(arcs, vtkm::SortLess());
vtkm::cont::Invoker Invoke;
Invoke(bestUpDownWorklet,
tour.first,
contourTree.Nodes,
contourTree.Supernodes,
minValues,
minParents,
maxValues,
maxParents,
ctSortOrder,
tour.edges,
fieldValues,
bestUpward, // output
bestDownward // output
);
vtkm::worklet::contourtree_augmented::process_contourtree_inc::SetBestUpDown setBestUpDown;
Invoke(setBestUpDown, bestUpward, bestDownward, arcs);
for (int i = 0; i < arcs.GetNumberOfValues(); i++)
{
//printf("Arc %d has i = %lld, j = %lld, upEdge = %d and subtreeVolume = %lld \n", i, arcs.ReadPortal().Get(i).i, arcs.ReadPortal().Get(i).j, arcs.ReadPortal().Get(i).upEdge, arcs.ReadPortal().Get(i).subtreeVolume);
//cout << "Arc " << i << ""
}
for (int i = 0; i < bestUpward.GetNumberOfValues(); i++)
{
//std::cout << i << " Up - " << bestUpward.ReadPortal().Get(i) << std::endl;
//std::cout << i << " Down - " << bestDownward.ReadPortal().Get(i) << std::endl;
}
ProcessContourTree::ComputeBranchData(contourTree,
false,
printTime,
whichBranch,
branchMinimum,
branchMaximum,
@ -1081,16 +1010,16 @@ public:
} // ComputeHeightBranchDecomposition()
// routine to compute the branch decomposition by volume
void static ComputeHeightBranchDecompositionNew(const ContourTree& contourTree,
const cont::ArrayHandle<Float64> fieldValues,
const IdArrayType& ctSortOrder,
const int printTime,
const vtkm::Id nIterations,
IdArrayType& whichBranch,
IdArrayType& branchMinimum,
IdArrayType& branchMaximum,
IdArrayType& branchSaddle,
IdArrayType& branchParent)
void static ComputeHeightBranchDecomposition(const ContourTree& contourTree,
const cont::ArrayHandle<Float64> fieldValues,
const IdArrayType& ctSortOrder,
const int printTime,
const vtkm::Id nIterations,
IdArrayType& whichBranch,
IdArrayType& branchMinimum,
IdArrayType& branchMaximum,
IdArrayType& branchSaddle,
IdArrayType& branchParent)
{ // ComputeHeightBranchDecomposition()
vtkm::cont::Timer timerTotal;
@ -1248,16 +1177,16 @@ public:
vtkm::cont::Timer hypersweepTimer;
hypersweepTimer.Start();
findMinMaxNewSimple<decltype(vtkm::Minimum())>(contourTree.Supernodes,
contourTree.Hypernodes,
minHyperarcs,
contourTree.Hyperparents,
minHyperparents,
contourTree.WhenTransferred,
minHowManyUsed,
nIterations,
vtkm::Minimum(),
minValues);
hyperarcScan<decltype(vtkm::Minimum())>(contourTree.Supernodes,
contourTree.Hypernodes,
minHyperarcs,
contourTree.Hyperparents,
minHyperparents,
contourTree.WhenTransferred,
minHowManyUsed,
nIterations,
vtkm::Minimum(),
minValues);
hypersweepTimer.Stop();
minHypersweepTime = hypersweepTimer.GetElapsedTime();
@ -1282,16 +1211,16 @@ public:
maxHyperarcs.WritePortal(),
maxHowManyUsed.WritePortal());
findMinMaxNewSimple<decltype(vtkm::Maximum())>(contourTree.Supernodes,
contourTree.Hypernodes,
maxHyperarcs,
contourTree.Hyperparents,
maxHyperparents,
contourTree.WhenTransferred,
maxHowManyUsed,
nIterations,
vtkm::Maximum(),
maxValues);
hyperarcScan<decltype(vtkm::Maximum())>(contourTree.Supernodes,
contourTree.Hypernodes,
maxHyperarcs,
contourTree.Hyperparents,
maxHyperparents,
contourTree.WhenTransferred,
maxHowManyUsed,
nIterations,
vtkm::Maximum(),
maxValues);
fixPath(vtkm::Maximum(), maxPath, maxValues.WritePortal());
@ -1384,22 +1313,6 @@ public:
printf("%.6f for Sorting.\n", timer.GetElapsedTime());
}
//const vtkm::Id E = 7439156;
////const vtkm::Id D = 6498111;
//for (int i = 0 ; i < arcs.GetNumberOfValues() ; i++)
//{
//const auto arc = arcs.ReadPortal().Get(i);
//if (arc.i == E || arc.j == E)
//{
//printf("\n[%lld, %lld], upEdge = %d, subtreeMin = %lld, subtreeMax = %lld, subtreeHeight = %f\n", arc.i, arc.j, arc.upEdge, arc.subtreeMin, arc.subtreeMax, arc.subtreeHeight);
//}
//}
//printf("WTF");
//
// Set bestUp and bestDown. Parallelisable
//
@ -1460,105 +1373,6 @@ public:
} // ComputeHeightBranchDecomposition()
void static findMinMaxNew(
const vtkm::cont::ArrayHandle<vtkm::Id>::ReadPortalType supernodesPortal,
const vtkm::cont::ArrayHandle<vtkm::Id>::ReadPortalType superarcsPortal,
const bool isMin,
const Id root,
vtkm::cont::ArrayHandle<vtkm::Id>::PortalControl minMaxIndex)
{
using vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT;
//
// Holds the index and distance of every supernode. Used to sort vertices by their distance for processing.
//
struct VertexData
{
Id distance;
Id index;
};
//
// Set the initial values. Parallelisable.
//
std::vector<VertexData> vertexData(
static_cast<unsigned long>(supernodesPortal.GetNumberOfValues()));
for (unsigned long i = 0; i < vertexData.size(); i++)
{
vertexData[i].index = i;
vertexData[i].distance = NO_SUCH_ELEMENT;
}
vertexData[root].distance = 0;
//
// Compute the distance to all vertices. With memorisation this is O(n). Not data parallelisable.
//
for (Id i = 0; i < superarcsPortal.GetNumberOfValues(); i++)
{
// If we have the distance skip this one
if (vertexData[i].distance != (vtkm::Id)NO_SUCH_ELEMENT)
continue;
// Find the distance to the root
vtkm::Id current = i;
Id distanceToRoot = 0;
while (vertexData[current].distance == (vtkm::Id)NO_SUCH_ELEMENT)
{
distanceToRoot++;
current = MaskedIndex(superarcsPortal.Get(current));
}
Id miniRoot = current;
// Set the distance to all nodes on the path to the root
current = i;
Id iteration = 0;
while (vertexData[current].distance == (vtkm::Id)NO_SUCH_ELEMENT)
{
Id distance = vertexData[miniRoot].distance + distanceToRoot - iteration;
vertexData[current].distance = distance;
iteration++;
current = MaskedIndex(superarcsPortal.Get(current));
}
}
//
// Sort all vertices based on distance. Parallelisable.
//
std::sort(vertexData.begin(), vertexData.end(), [](const VertexData& a, const VertexData& b) {
return a.distance > b.distance;
});
//
// Set an initial value, suppose every vertex is its own min/max. Parallelisable.
//
for (vtkm::Id i = 0; i < minMaxIndex.GetNumberOfValues(); i++)
{
minMaxIndex.Set(i, i);
}
//
// For every vertex see if it's bigger than its parent. At the end the minMaxIndex with contain the min/max child of every vertex. Not data parallelisable.
//
for (Id i = 0; i < vertexData.size(); i++)
{
Id vertex = vertexData[i].index;
Id parent = MaskedIndex(superarcsPortal.Get(vertex));
if (vertex == root)
continue;
Id vertexValue = MaskedIndex(supernodesPortal.Get(minMaxIndex.Get(vertex)));
Id parentValue = MaskedIndex(supernodesPortal.Get(minMaxIndex.Get(parent)));
if ((true == isMin && vertexValue < parentValue) ||
(false == isMin && vertexValue > parentValue))
{
minMaxIndex.Set(parent, minMaxIndex.Get(vertex));
}
}
}
std::vector<Id> static findSuperPathToRoot(
vtkm::cont::ArrayHandle<vtkm::Id>::ReadPortalType parentsPortal,
vtkm::Id vertex)
@ -1633,16 +1447,16 @@ public:
}
template <class BinaryFunctor>
void static findMinMaxNewSimple(const vtkm::cont::ArrayHandle<vtkm::Id> supernodes,
const vtkm::cont::ArrayHandle<vtkm::Id> hypernodes,
const vtkm::cont::ArrayHandle<vtkm::Id> hyperarcs,
const vtkm::cont::ArrayHandle<vtkm::Id> hyperparents,
const vtkm::cont::ArrayHandle<vtkm::Id> hyperparentKeys,
const vtkm::cont::ArrayHandle<vtkm::Id> whenTransferred,
const vtkm::cont::ArrayHandle<vtkm::Id> howManyUsed,
const vtkm::Id nIterations,
const BinaryFunctor operation,
vtkm::cont::ArrayHandle<vtkm::Id> minMaxIndex)
void static hyperarcScan(const vtkm::cont::ArrayHandle<vtkm::Id> supernodes,
const vtkm::cont::ArrayHandle<vtkm::Id> hypernodes,
const vtkm::cont::ArrayHandle<vtkm::Id> hyperarcs,
const vtkm::cont::ArrayHandle<vtkm::Id> hyperparents,
const vtkm::cont::ArrayHandle<vtkm::Id> hyperparentKeys,
const vtkm::cont::ArrayHandle<vtkm::Id> whenTransferred,
const vtkm::cont::ArrayHandle<vtkm::Id> howManyUsed,
const vtkm::Id nIterations,
const BinaryFunctor operation,
vtkm::cont::ArrayHandle<vtkm::Id> minMaxIndex)
{
using vtkm::worklet::contourtree_augmented::MaskedIndex;
@ -1746,82 +1560,8 @@ public:
hyperarcs,
howManyUsed,
minMaxIndex);
//
// Remnants of the serial version. Here for debugging.
//
//
// For every hyperarc in the current iteration. Parallel.
//
//for (Id i = firstHypernode; i < lastHypernode; i++)
//{
//// If it's the last hyperacs (there's nothing to do it's just the root)
//if (i >= hypernodesPortal.GetNumberOfValues() - 1) { continue; }
//vtkm::Id firstSupernode = MaskedIndex(hypernodesPortal.Get(i));
//vtkm::Id lastSupernode = MaskedIndex(hypernodesPortal.Get(i + 1)) - howManyUsedPortal.Get(i);
////
//// Prefix scan along the hyperarc chain. Parallel prefix scan.
////
//int threshold = 1000;
//if (lastSupernode - firstSupernode > threshold)
//{
//auto subarray = vtkm::cont::make_ArrayHandleView(minMaxIndex, firstSupernode, lastSupernode - firstSupernode);
//vtkm::cont::Algorithm::ScanInclusive(subarray, subarray, operation);
//}
//else
//{
//for (Id j = firstSupernode + 1; j < lastSupernode; j++)
//{
//Id vertex = j - 1;
//Id parent = j;
//Id vertexValue = minMaxIndex.ReadPortal().Get(vertex);
//Id parentValue = minMaxIndex.ReadPortal().Get(parent);
//minMaxIndex.WritePortal().Set(parent, operation(vertexValue, parentValue));
//}
//}
//}
//
// Serial, but can be made parallel if we sort the hypearcs by destination and do a prefix sum on the destination.
// The only problem is that figuring that out requries a serial pass anyway.
// So we might as well do all of it in serial.
// Furthermore the degree of the mesh is limiting this.
//
//for (Id i = firstHypernode; i < lastHypernode; i++)
//{
//// If it's the last hyperacs (there's nothing to do it's just the root)
//if (i >= hypernodesPortal.GetNumberOfValues() - 1) { continue; }
////
//// The value of the prefix scan is now accumulated in the last supernode of the hyperarc. Transfer is to the target
////
//vtkm::Id lastSupernode = MaskedIndex(hypernodesPortal.Get(i + 1)) - howManyUsedPortal.Get(i);
////
//// Transfer the accumulated value to the target supernode
////
//Id vertex = lastSupernode - 1;
//Id parent = MaskedIndex(hyperarcsPortal.Get(i));
//Id vertexValue = minMaxIndex.ReadPortal().Get(vertex);
//Id parentValue = minMaxIndex.ReadPortal().Get(parent);
//minMaxIndex.WritePortal().Set(parent, operation(vertexValue, parentValue));
//}
}
}
}; // class ProcessContourTree
} // namespace contourtree_augmented
} // worklet

@ -190,6 +190,51 @@ public:
}
};
class EdgeDataVolume
{
public:
// RegularNodeID (or sortIndex)
Id i;
// RegularNodeID (or sortIndex)
Id j;
bool upEdge;
Id subtreeVolume;
bool operator<(const EdgeDataVolume& b) const
{
if (this->i == b.i)
{
if (this->upEdge == b.upEdge)
{
if (this->subtreeVolume == b.subtreeVolume)
{
if (this->upEdge == true)
{
return this->j > b.j;
}
else
{
return this->j < b.j;
}
}
else
{
return this->subtreeVolume > b.subtreeVolume;
}
}
else
{
return this->upEdge < b.upEdge;
}
}
else
{
return this->i < b.i;
}
}
};
} // namespace contourtree_augmented
} // worklet