From 35a14f31292f689d00b1180f16cec01491f712b2 Mon Sep 17 00:00:00 2001 From: Oliver Ruebel Date: Mon, 24 May 2021 16:33:35 -0700 Subject: [PATCH] Fix errors in HierarchicalAugmenter Fix CreateSuperarcsWorklet. Use standard copy to reduce complexity of CreateSuperarcsWorklet. Fix compile errors in HierarchicalAugmenter. Some more clean-up and optimization for HierarchicalAugmenter.CreateSuperarcsWorklet. --- .../HierarchicalAugmenter.h | 245 ++++++++++++------ .../CreateSuperarcsWorklet.h | 227 +++++++--------- 2 files changed, 263 insertions(+), 209 deletions(-) diff --git a/vtkm/worklet/contourtree_distributed/HierarchicalAugmenter.h b/vtkm/worklet/contourtree_distributed/HierarchicalAugmenter.h index f2eae2acf..431285cc0 100644 --- a/vtkm/worklet/contourtree_distributed/HierarchicalAugmenter.h +++ b/vtkm/worklet/contourtree_distributed/HierarchicalAugmenter.h @@ -342,14 +342,18 @@ void HierarchicalAugmenter::PrepareOutAttachmentPoints(vtkm::Id round vtkm::worklet::contourtree_distributed::hierarchical_augmenter:: IsAttachementPointNeededPredicate isAttachementPointNeededPredicate( this->SuperparentRounds, this->WhichRounds, round); + auto tempAttachmentPointsIndex = + vtkm::cont::ArrayHandleIndex(this->GlobalRegularIds.GetNumberOfValues()); vtkm::cont::Algorithm::CopyIf( - // 1. generate a list of all of the attachment points - vtkm::cont::ArrayHandleIndex(this - GlobalRegularIds.GetNumberOfValues()), - // 2. then our stencil identifies all attachment points needed - isAttachementPointNeededPredicate, - // 3. And the CopyIf compress the supernodes array to eliminate the non-attachement points and - // save to this->AttachmentIds - this->AttachmentIds); + // 1. fancy array of all of the attachment points of which parts are copied to this->AttachmentIds + tempAttachmentPointsIndex, // input + // 2. stencil used with the predicate to decide which AttachementIds to keep + tempAttachmentPointsIndex, // stencil + // 3. CopyIf compress the supernodes array to eliminate the non-attachement + // points and save to this->AttachmentIds + this->AttachmentIds, + // 4. the unary predicate uses the stencil to identify all attachment points needed + isAttachementPointNeededPredicate); } // 4. resize the out array @@ -369,19 +373,19 @@ void HierarchicalAugmenter::PrepareOutAttachmentPoints(vtkm::Id round // outDataValues[outAttachmentPoint] = dataValues[attachmentPoint]; vtkm::cont::Algorithm::Copy( vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->DataValues), - this->outDataValues); + this->OutDataValues); // outSupernodeIDs[outAttachmentPoint] = supernodeIDs[attachmentPoint]; vtkm::cont::Algorithm::Copy( vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->SupernodeIds), this->OutSupernodeIds); // outSuperparents[outAttachmentPoint] = superparents[attachmentPoint]; vtkm::cont::Algorithm::Copy( - vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->superparents), - this->outSuperparents); + vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->Superparents), + this->OutSuperparents); // outSuperparentRounds[outAttachmentPoint] = superparentRounds[attachmentPoint]; vtkm::cont::Algorithm::Copy( vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->SuperparentRounds), - this->outSuperparentRounds); + this->OutSuperparentRounds); // outWhichRounds[outAttachmentPoint] = whichRounds[attachmentPoint]; vtkm::cont::Algorithm::Copy( vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->WhichRounds), @@ -405,9 +409,9 @@ void HierarchicalAugmenter::RetrieveInAttachmentPoints(HierarchicalAu vtkm::Id numTotalAttachments = numAttachmentsCurrently + numIncomingAttachments; // I. resize the existing arrays - this->GlobalRegularIDs.Allocate(numTotalAttachments); + this->GlobalRegularIds.Allocate(numTotalAttachments); this->DataValues.Allocate(numTotalAttachments); - this->SupernodeIDs.Allocate(numTotalAttachments); + this->SupernodeIds.Allocate(numTotalAttachments); this->Superparents.Allocate(numTotalAttachments); this->SuperparentRounds.Allocate(numTotalAttachments); this->WhichRounds.Allocate(numTotalAttachments); @@ -417,36 +421,31 @@ void HierarchicalAugmenter::RetrieveInAttachmentPoints(HierarchicalAu // The following sequence of copy operations implements the following for from the orginal code // for (vtkm::Id outAttachmentPoint = 0; outAttachmentPoint < partner.outGlobalRegularIDs.size(); outAttachmentPoint++) // globalRegularIDs[attachmentPoint] = partner.outGlobalRegularIDs[outAttachmentPoint]; - vtkm::cont::Algorithm::Copy(partner.OutGlobalRegularIds, - vtkm::cont::make_ArrayHandleView(this->GlobalRegularIds, - numAttachmentsCurrently, - numIncomingAttachments)); + auto tempGlobalRegularIdsView = vtkm::cont::make_ArrayHandleView( + this->GlobalRegularIds, numAttachmentsCurrently, numIncomingAttachments); + vtkm::cont::Algorithm::Copy(partner.OutGlobalRegularIds, tempGlobalRegularIdsView); // dataValues[attachmentPoint] = partner.outDataValues[outAttachmentPoint]; - vtkm::cont::Algorithm::Copy(partner.OutDataValues, - vtkm::cont::make_ArrayHandleView(this->DataValues, - numAttachmentsCurrently, - numIncomingAttachments)); + auto tempDataValuesView = vtkm::cont::make_ArrayHandleView( + this->DataValues, numAttachmentsCurrently, numIncomingAttachments); + vtkm::cont::Algorithm::Copy(partner.OutDataValues, tempDataValuesView); // supernodeIDs[attachmentPoint] = NO_SUCH_ELEMENT; - vtkm::cont::Algorithm::Copy( - vtkm::cont::make_ArrayHandleConstant(vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT, - numIncomingAttachments), - vtkm::cont::make_ArrayHandleView( - this->SupernodeIds, numAttachmentsCurrently, numIncomingAttachments)); + auto tempNoSuchElementArr = vtkm::cont::make_ArrayHandleConstant( + vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT, numIncomingAttachments); + auto tempSupernodeIdsView = vtkm::cont::make_ArrayHandleView( + this->SupernodeIds, numAttachmentsCurrently, numIncomingAttachments); + vtkm::cont::Algorithm::Copy(tempNoSuchElementArr, tempSupernodeIdsView); // superparents[attachmentPoint] = partner.outSuperparents[outAttachmentPoint]; - vtkm::cont::Algorithm::Copy(partner.outSuperparents, - vtkm::cont::make_ArrayHandleView(this->Superparents, - numAttachmentsCurrently, - numIncomingAttachments)); + auto tempSuperparentsView = vtkm::cont::make_ArrayHandleView( + this->Superparents, numAttachmentsCurrently, numIncomingAttachments); + vtkm::cont::Algorithm::Copy(partner.OutSuperparents, tempSuperparentsView); // superparentRounds[attachmentPoint] = partner.outSuperparentRounds[outAttachmentPoint]; - vtkm::cont::Algorithm::Copy(partner.outSuperparentRounds, - vtkm::cont::make_ArrayHandleView(this->SuperparentRounds, - numAttachmentsCurrently, - numIncomingAttachments)); + auto tempSuperparentRoundsView = vtkm::cont::make_ArrayHandleView( + this->SuperparentRounds, numAttachmentsCurrently, numIncomingAttachments); + vtkm::cont::Algorithm::Copy(partner.OutSuperparentRounds, tempSuperparentRoundsView); // whichRounds[attachmentPoint] = partner.outWhichRounds[outAttachmentPoint]; - vtkm::cont::Algorithm::Copy(partner.OutWhichRounds, - vtkm::cont::make_ArrayHandleView(this->WhichRounds, - numAttachmentsCurrently, - numIncomingAttachments)); + auto tempWhichRoundsView = vtkm::cont::make_ArrayHandleView( + this->WhichRounds, numAttachmentsCurrently, numIncomingAttachments); + vtkm::cont::Algorithm::Copy(partner.OutWhichRounds, tempWhichRoundsView); } } // RetrieveInAttachmentPoints() @@ -455,9 +454,9 @@ void HierarchicalAugmenter::RetrieveInAttachmentPoints(HierarchicalAu template void HierarchicalAugmenter::ReleaseOutArrays() { // ReleaseOutArrays() - this->OutGlobalRegularIDs.ReleaseResources(); + this->OutGlobalRegularIds.ReleaseResources(); this->OutDataValues.ReleaseResources(); - this->OutSupernodeIDs.ReleaseResources(); + this->OutSupernodeIds.ReleaseResources(); this->OutSuperparents.ReleaseResources(); this->OutSuperparentRounds.ReleaseResources(); this->OutWhichRounds.ReleaseResources(); @@ -1110,52 +1109,136 @@ void HierarchicalAugmenter::ResizeArrays(vtkm::Id roundNumber) template void HierarchicalAugmenter::CreateSuperarcs(vtkm::Id roundNumber) { // CreateSuperarcs() - // retrieve the ID number of the first supernode at this leverl + // retrieve the ID number of the first supernode at this level vtkm::Id numSupernodesAlready = vtkm::cont::ArrayGetValue(0, this->AugmentedTree->FirstSupernodePerIteration[roundNumber]); // e. Connect superarcs for the level & set hyperparents & superchildren count, whichRound, whichIteration, super2hypernode - { - // TODO: The CreateSuperarcsWorklet uses a lot of arrays and lots of WholeArrayTransfers. This could probably be further optimized. - // TODO: FIX invokation of this worklet - throw std::logic_error("Invocation of CreateSuperarcsWorklet currently broken"); - /* - vtkm::worklet::contourtree_distributed::hierarchical_augmenter::CreateSuperarcsWorklet - createSuperarcsWorklet( - numSupernodesAlready, - this->BaseTree->NumRounds, - vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations), - roundNumber); - this->Invoke( - createSuperarcsWorklet, // the worklet - this->SupernodeSorter, // input domain (we need access to InputIndex and InputIndex+1) - this->SuperparentSet, // input - this->BaseTree->Superarcs, // input - this->NewSupernodeIds, // input - this->BaseTree->Hyperparents, // input - this->BaseTree->Supernodes, // input - this->BaseTree->RegularNodeGlobalIds, // input - this->GlobalRegularIdSet, // input - this->BaseTree->Super2Hypernode, // input - this->BaseTree->WhichRound, // input - this->BaseTree->WhichIteration, // input - this->DataValueSet, // input - vtkm::cont::make_ArrayHandleView( - this->AugmentedTree->Superarcs, + { // START scope for e. to delete temporary variables + // Note: The original PPP algorithm performed all operations listed in this block + // in a single parralel for loop. Many of those operations were smart array + // copies. So to simplfy the worklet and to make more effective use of + // VTKm algorithm, a large number of copy operations have been extracted from + // the loop and are performed here via combinations of fancy array handles and + // vtkm::cont::Algorithm::Copy operations. + + // Define the new supernode and regular Id. Both are actually the same here since we are + // augmenting the tree here, but for clarity we define them as separate variables. + // At all levels above 0, we used to keep regular vertices in case + // they are attachment points. After augmentation, we don't need to. + // Instead, at all levels above 0, the regular nodes in each round + // are identical to the supernodes. In order to avoid confusion, + // we will copy the Id into a separate variable + vtkm::cont::ArrayHandleCounting newSupernodeId( + numSupernodesAlready, // start + static_cast(1), // step + this->SupernodeSorter.GetNumberOfValues() // number of values + ); + auto newRegularId = newSupernodeId; + // define the superparentOldSuperId + auto permutedSuperparentSet = + vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SuperparentSet); + auto superparentOldSuperId = vtkm::cont::make_ArrayHandleTransform( + permutedSuperparentSet, vtkm::worklet::contourtree_augmented::MaskedIndexFunctor()); + + // set the supernode's regular Id. Set: augmentedTree->supernodes[newSupernodeID] = newRegularID; + auto permutedAugmentedTreeSupernodes = + vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->Supernodes); + vtkm::cont::Algorithm::Copy(newRegularId, permutedAugmentedTreeSupernodes); + + // Run the worklet for more complex operations + { // START block for CreateSuperarcsWorklet + // create the worklet + vtkm::worklet::contourtree_distributed::hierarchical_augmenter::CreateSuperarcsWorklet + createSuperarcsWorklet( numSupernodesAlready, - this->SupernodeSorter.GetNumberOfValues()), // output - this->AugmentedTree->Hyperparents, // input/output - this->AugmentedTree->FirstSupernodePerIteration[roundNumber], // input/output - this->AugmentedTree->Supernodes, // input/output - this->AugmentedTree->Super2Hypernode, // input/ouput - this->AugmentedTree->WhichRound, // input/ouput - this->AugmentedTree->WhichIteration, // input/ouput - this->AugmentedTree->RegularNodeGlobalIds, //input/ ouput - this->AugmentedTree->DataValues, // input/ouput - this->AugmentedTree->Regular2Supernode, // input/ouput - this->AugmentedTree->Superparents // input/ouput - );*/ - } + this->BaseTree->NumRounds, + vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations), + roundNumber, + this->AugmentedTree->Supernodes.GetNumberOfValues()); + // create fancy arrays needed to allow use of FieldIn for worklet parameters + auto permutedGlobalRegularIdSet = + vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet); + auto augmentedTreeSuperarcsView = + vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Superarcs, + numSupernodesAlready, + this->SupernodeSorter.GetNumberOfValues()); + auto augmentedTreeSuper2HypernodeView = + vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Super2Hypernode, + numSupernodesAlready, + this->SupernodeSorter.GetNumberOfValues()); + // invoke the worklet + this->Invoke(createSuperarcsWorklet, // the worklet + this->SupernodeSorter, // input domain + this->SuperparentSet, // input + this->BaseTree->Superarcs, // input + this->NewSupernodeIds, // input + this->BaseTree->Supernodes, // input + this->BaseTree->RegularNodeGlobalIds, // input + permutedGlobalRegularIdSet, // input + this->BaseTree->Super2Hypernode, // input + this->BaseTree->WhichIteration, // input + augmentedTreeSuperarcsView, // output + this->AugmentedTree->FirstSupernodePerIteration[roundNumber], // input/output + augmentedTreeSuper2HypernodeView // output + ); + } // END block for CreateSuperarcsWorklet + + // setting the hyperparent is straightforward since the hyperstructure is preserved + // we take the superparent (which is guaranteed to be in the baseTree), find it's hyperparent and use that + // Set: augmentedTree->hyperparents[newSupernodeID] = baseTree->hyperparents[superparentOldSuperID]; + auto permutedAugmentedTreeHyperparents = + vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->Hyperparents); + auto permutedBaseTreeHyperparents = + vtkm::cont::make_ArrayHandlePermutation(superparentOldSuperId, this->BaseTree->Hyperparents); + vtkm::cont::Algorithm::Copy(permutedBaseTreeHyperparents, permutedAugmentedTreeHyperparents); + + // which round and iteration carry over + // Set: augmentedTree->whichRound[newSupernodeID] = baseTree->whichRound[superparentOldSuperID]; + auto permutedAugmentedTreeWhichRound = + vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->WhichRound); + auto permutedBaseTreeWhichRound = + vtkm::cont::make_ArrayHandlePermutation(superparentOldSuperId, this->BaseTree->WhichRound); + vtkm::cont::Algorithm::Copy(permutedBaseTreeWhichRound, permutedAugmentedTreeWhichRound); + + // Set: augmentedTree->whichIteration[newSupernodeID] = baseTree->whichIteration[superparentOldSuperID]; + auto permutedAugmentedTreeWhichIteration = + vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->WhichIteration); + auto permutedBaseTreeWhichIterationPortal = vtkm::cont::make_ArrayHandlePermutation( + superparentOldSuperId, this->BaseTree->WhichIteration); + vtkm::cont::Algorithm::Copy(permutedBaseTreeWhichIterationPortal, + permutedAugmentedTreeWhichIteration); + + // now we deal with the regular-sized arrays. In the following supernodeSetIndex is simply supernodeSorterPortal.Get(supernode); + // copy the global regular Id and data value + // Set: augmentedTree->regularNodeGlobalIDs[newRegularID] = globalRegularIDSet[supernodeSetIndex]; + auto permutedAugmentedTreeRegularNodeGlobalIds = vtkm::cont::make_ArrayHandlePermutation( + newRegularId, this->AugmentedTree->RegularNodeGlobalIds); + auto permutedGlobalRegularIdSet = + vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet); + vtkm::cont::Algorithm::Copy(permutedGlobalRegularIdSet, + permutedAugmentedTreeRegularNodeGlobalIds); + // SetL augmentedTree->dataValues[newRegularID] = dataValueSet[supernodeSetIndex]; + auto permutedAugmentedTreeDataValues = + vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->DataValues); + auto permutedDataValueSet = + vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->DataValueSet); + vtkm::cont::Algorithm::Copy(permutedDataValueSet, permutedAugmentedTreeDataValues); + + // the sort order will be dealt with later + // since all of these nodes are supernodes, they will be their own superparent, which means that: + // a. the regular2node can be set immediately + // Set: augmentedTree->regular2supernode[newRegularID] = newSupernodeID; + auto permutedAugmentedTreeRegular2Supernode = + vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->Regular2Supernode); + vtkm::cont::Algorithm::Copy(newSupernodeId, permutedAugmentedTreeRegular2Supernode); + + // b. as can the superparent + // Set: augmentedTree->superparents[newRegularID] = newSupernodeID; + auto permutedAugmentedTreeSuperparents = + vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->Superparents); + vtkm::cont::Algorithm::Copy(newSupernodeId, permutedAugmentedTreeSuperparents); + } // END scope for e. to delete temporary variables // We have one last bit of cleanup to do. If there were attachment points, then the round in which they transfer has been removed // While it is possible to turn this into a null round, it is better to reduce the iteration count by one and resize the arrays diff --git a/vtkm/worklet/contourtree_distributed/hierarchical_augmenter/CreateSuperarcsWorklet.h b/vtkm/worklet/contourtree_distributed/hierarchical_augmenter/CreateSuperarcsWorklet.h index cfaea8685..2243048b6 100644 --- a/vtkm/worklet/contourtree_distributed/hierarchical_augmenter/CreateSuperarcsWorklet.h +++ b/vtkm/worklet/contourtree_distributed/hierarchical_augmenter/CreateSuperarcsWorklet.h @@ -64,148 +64,115 @@ namespace hierarchical_augmenter class CreateSuperarcsWorklet : public vtkm::worklet::WorkletMapField { public: - // VTKm only defines 20 placeholders for the execution signature, but we need a few more here - using _21 = vtkm::placeholders::Arg<21>; - using _22 = vtkm::placeholders::Arg<22>; - using _23 = vtkm::placeholders::Arg<23>; + // TODO: Check if augmentedTreeFirstSupernodePerIteration could be changed to WholeArrayOut or if we need the In to preserve orignal values - // TODO: This worklet could probably be optimized further to reduce the use of WholeArray passing /// Control signature for the worklet + /// @param[in] supernodeSorter input domain. We need access to InputIndex and InputIndex+1, + /// therefore this is a WholeArrayIn transfer. + /// @param[in] superparentSet WholeArrayIn because we need access to superparentSet[supernodeSorter[InputIndex]] + /// and superparentSet[supernodeSorter[InputIndex+1]]. + /// @param[in] baseTreeSuperarcs WholeArrayIn because we need access to baseTreeSuperarcsPortal.Get(superparentOldSuperId) + /// While this could be done with fancy array magic, it would require a sequence of multiple + /// fancy arrays and would likely not be cheaper then computing things in the worklet. + /// @param[in] newSupernodeIds WholeArrayIn because we need to access newSupernodeIdsPortal.Get(oldTargetSuperId) + /// where oldTargetSuperId is the unmasked baseTreeSuperarcsPortal.Get(superparentOldSuperId) + /// @param[in] baseTreeSupernodes WholeArrayIn because we need to access baseTreeSupernodesPortal.Get(superparentOldSuperId); + /// @param[in] baseTreeRegularNodeGlobalIds WholeArrayIn because we need to access + /// baseTreeRegularNodeGlobalIdsPortal.Get(superparentOldSuperId); + /// @param[in] globalRegularIdSet FieldInd. Permute globalRegularIdSet with supernodeSorter in order to allow this to be a FieldIn. + /// @param[in] baseTreeSuper2Hypernode WholeArrayIn because we need to access + /// baseTreeSuper2HypernodePortal.Get(superparentOldSuperId) + /// @param[in] baseTreeWhichIteration WholeArrayIn because we need to access baseTreeWhichIterationPortal.Get(superparentOldSuperId) + /// and baseTreeWhichIterationPortal.Get(superparentOldSuperId+1) + /// @param[in] augmentedTreeSuperarcsView output view of this->AugmentedTree->Superarcs with + /// vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Superarcs, + /// numSupernodesAlready, this->SupernodeSorter.GetNumberOfValues()). + /// By using this view allows us to do this one as a FieldOut and it effectively the + /// same as accessing the array at the newSuppernodeId location. + /// @param[in] augmentedTreeFirstSupernodePerIteration WholeArrayInOut because we need to update multiple locations. + /// In is used to preseve original values. Set to augmentedTree->firstSupernodePerIteration[roundNumber]. + /// @param[in] augmentedTreeSuper2hypernode FieldOut. Output view of this->AugmentedTree->Super2Hypernode + /// vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Super2Hypernode, + /// numSupernodesAlready, this->SupernodeSorter.GetNumberOfValues()). + /// By using this view allows us to do this one as a FieldOut and it effectively the + /// same as accessing the array at the newSuppernodeId location. using ControlSignature = void( - WholeArrayIn supernodeSorter, // input domain (we need access to InputIndex and InputIndex+1) - WholeArrayIn superparentSet, // input - WholeArrayIn baseTreeSuperarcs, // input - WholeArrayIn newSupernodeIds, // input - WholeArrayIn - baseTreeHyperparents, // input TODO: could potentially be a FieldIn with some array shuffle magic - WholeArrayIn - baseTreeSupernodes, // input TODO: could potentially be a FieldIn with some array shuffle magic - WholeArrayIn - baseTreeRegularNodeGlobalIds, // input TODO: could potentially be a FieldIn with some array shuffle magic - WholeArrayIn - globalRegularIdSet, // input TODO: could potentially be a FieldIn with some array shuffle magic - WholeArrayIn baseTreeSuper2Hypernode, // input TODO: FieldIn possible with array shuffle? - WholeArrayIn baseTreeWhichRound, // input TODO: FieldIn possible with array shuffle? - WholeArrayIn baseTreeWhichIteration, // input TODO: FieldIn possible with array shuffle? - WholeArrayIn dataValueSet, // input TODO: FieldIn possible with array shuffle? - FieldOut - augmentedTreeSuperarcsView, // output view of ArrayHandleView(this->AugmentedTree->Superarcs[, this->NumSupernodesAlready, this->SupernodeSorter.GetNumberOfValues()) - WholeArrayInOut augmentedTreeHyperparents, // input/output - WholeArrayInOut - augmentedTreeFirstSupernodePerIteration, // input/output augmentedTree->firstSupernodePerIteration[roundNumber] - WholeArrayInOut - augmentedTreeSupernodes, // input/output TODO: Could potentially change to FieldIn/FieldInOut when permutting the array - WholeArrayInOut - augmentedTreeSuper2hypernode, // input/ouput TODO: Is FieldOut possible with array shuffle? - WholeArrayInOut - augmentedTreeWhichRound, // input/ouput TODO: Is FieldOut possible with array shuffle? - WholeArrayInOut - augmentedTreeWhichIteration, // input/ouput TODO: Is FieldOut possible with array shuffle? - WholeArrayInOut - augmentedTreeRegularNodeGlobalIds, // input/ouput TODO: Is FieldOut possible with array shuffle? - WholeArrayInOut - augmentedTreeDataValues, // input/ouput TODO: Is FieldOut possible with array shuffle? - WholeArrayInOut - augmentedTreeRegular2Supernode, // input/ouput TODO: Is FieldOut possible with array shuffle? - WholeArrayInOut - augmentedTreeSuperparents // input/ouput TODO: Is FieldOut possible with array shuffle? + WholeArrayIn supernodeSorter, + WholeArrayIn superparentSet, // input + WholeArrayIn baseTreeSuperarcs, // input + WholeArrayIn newSupernodeIds, // input + WholeArrayIn baseTreeSupernodes, // input + WholeArrayIn baseTreeRegularNodeGlobalIds, // input + FieldIn globalRegularIdSet, // input + WholeArrayIn baseTreeSuper2Hypernode, // input + WholeArrayIn baseTreeWhichIteration, // input + FieldOut augmentedTreeSuperarcsView, // output + WholeArrayInOut augmentedTreeFirstSupernodePerIteration, // input/output + FieldOut augmentedTreeSuper2hypernode // ouput ); - using ExecutionSignature = void(InputIndex, - _1, - _2, - _3, - _4, - _5, - _6, - _7, - _8, - _9, - _10, - _11, - _12, - _13, - _14, - _15, - _16, - _17, - _18, - _19, - _20, - _21, - _22, - _23); + using ExecutionSignature = void(InputIndex, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12); using InputDomain = _1; /// Default Constructor + /// @param[in] numSupernodesAlready Set to vtkm::cont::ArrayGetValue(0, this->AugmentedTree->FirstSupernodePerIteration[roundNumber]); + /// @param[in] baseTreeNumRounds Set to this->BaseTree->NumRounds + /// @param[in] augmentedTreeNumIterations Set to vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations); + /// @param[in] roundNumber Set the current round + /// @param[in] numAugmentedTreeSupernodes Set to augmentedTreeSupernodes this->AugmentedTree->Supernodes.GetNumberOfValues(); VTKM_EXEC_CONT - CreateSuperarcsWorklet( - const vtkm::Id& numSupernodesAlready, - const vtkm::Id& baseTreeNumRounds, - const vtkm::Id& - augmentedTreeNumIterations, // set to vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations) - const vtkm::Id& roundNumber) + CreateSuperarcsWorklet(const vtkm::Id& numSupernodesAlready, + const vtkm::Id& baseTreeNumRounds, + const vtkm::Id& augmentedTreeNumIterations, + const vtkm::Id& roundNumber, + const vtkm::Id& numAugmentedTreeSupernodes) : NumSupernodesAlready(numSupernodesAlready) , BaseTreeNumRounds(baseTreeNumRounds) , AugmentedTreeNumIterations(augmentedTreeNumIterations) , RoundNumber(roundNumber) - + , NumAugmentedTreeSupernodes(numAugmentedTreeSupernodes) { } /// operator() of the workelt - template + template VTKM_EXEC void operator()( const vtkm::Id& supernode, // InputIndex of supernodeSorter const InFieldPortalType& supernodeSorterPortal, const InFieldPortalType& superparentSetPortal, const InFieldPortalType& baseTreeSuperarcsPortal, const InFieldPortalType& newSupernodeIdsPortal, - const InFieldPortalType& baseTreeHyperparentsPortal, const InFieldPortalType& baseTreeSupernodesPortal, const InFieldPortalType& baseTreeRegularNodeGlobalIdsPortal, - const InFieldPortalType& globalRegularIdSetPortal, - const InFieldPortalType& baseTreeSuper2hypernodePortal, - const InFieldPortalType& baseTreeWhichRoundPortal, + const vtkm::Id& globalRegularIdSetValue, + const InFieldPortalType& baseTreeSuper2HypernodePortal, const InFieldPortalType& baseTreeWhichIterationPortal, - const InFieldPortalType2& dataValueSetPortal, vtkm::Id& augmentedTreeSuperarcsValue, // same as augmentedTree->superarcs[newSupernodeId] - const InOutFieldPortalType& augmentedTreeHyperparentsPortal, const InOutFieldPortalType& augmentedTreeFirstSupernodePerIterationPortal, // augmentedTree->firstSupernodePerIteration[roundNumber] - const InOutFieldPortalType& augmentedTreeSupernodesPortal, - const InOutFieldPortalType& augmentedTreeSuper2hypernodePortal, - const InOutFieldPortalType& augmentedTreeWhichRoundPortal, - const InOutFieldPortalType& augmentedTreeWhichIterationPortal, - const InOutFieldPortalType& augmentedTreeRegularNodeGlobalIdsPortal, - const InOutFieldPortalType2& augmentedTreeDataValuesPortal, - const InOutFieldPortalType& augmentedTreeRegular2SupernodePortal, - const InOutFieldPortalType& augmentedTreeSuperparentsPortal) const + vtkm::Id& augmentedTreeSuper2hypernodeValue) const { // per supernode in the set // retrieve the index from the sorting index array vtkm::Id supernodeSetIndex = supernodeSorterPortal.Get(supernode); - // work out the new supernode Id + // work out the new supernode Id. We have this defined on the outside as a fancy array handle, + // however, using the fancy handle here would not really make a performance differnce and + // computing it here is more readable vtkm::Id newSupernodeId = this->NumSupernodesAlready + supernode; - // At all levels above 0, we used to keep regular vertices in case - // they are attachment points. After augmentation, we don't need to. - // Instead, at all levels above 0, the regular nodes in each round - // are identical to the supernodes. In order to avoid confusion, - // we will copy the Id into a separate variable - vtkm::Id newRegularId = newSupernodeId; + // NOTE: The newRegularId is no longer needed here since all parts + // that used it in the worklet have been moved outside + // vtkm::Id newRegularId = newSupernodeId; - // setting the supernode's regular Id is now trivial - augmentedTreeSupernodesPortal.Set(newSupernodeId, newRegularId); + // NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs + // // setting the supernode's regular Id is now trivial + // augmentedTreeSupernodesPortal.Set(newSupernodeId, newRegularId); // retrieve the ascending flag from the superparent vtkm::Id superparentSetVal = superparentSetPortal.Get(supernodeSetIndex); + // get the ascending flag from the parent bool superarcAscends = vtkm::worklet::contourtree_augmented::IsAscending(superparentSetVal); - - // strip the ascending flag from the superparent + // strip the ascending flag from the superparent. vtkm::Id superparentOldSuperId = vtkm::worklet::contourtree_augmented::MaskedIndex(superparentSetVal); @@ -234,8 +201,8 @@ public: (superarcAscends ? vtkm::worklet::contourtree_augmented::IS_ASCENDING : 0x00); } // not the tree root // since there's an extra entry in the firstSupernode array as a sentinel, set it - augmentedTreeFirstSupernodePerIterationPortal.Set( - this->AugmentedTreeNumIterations, augmentedTreeSupernodesPortal.GetNumberOfValues()); + augmentedTreeFirstSupernodePerIterationPortal.Set(this->AugmentedTreeNumIterations, + NumAugmentedTreeSupernodes); } // last in the array else if (superparentOldSuperId != vtkm::worklet::contourtree_augmented::MaskedIndex( @@ -273,47 +240,50 @@ public: // set the first supernode in the first iteration to the beginning of the round augmentedTreeFirstSupernodePerIterationPortal.Set(0, this->NumSupernodesAlready); - // setting the hyperparent is straightforward since the hyperstructure is preserved - // we take the superparent (which is guaranteed to be in the baseTree), find it's hyperparent and use that - augmentedTreeHyperparentsPortal.Set(newSupernodeId, - baseTreeHyperparentsPortal.Get(superparentOldSuperId)); + // NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs + // // setting the hyperparent is straightforward since the hyperstructure is preserved + // // we take the superparent (which is guaranteed to be in the baseTree), find it's hyperparent and use that + // augmentedTreeHyperparentsPortal.Set(newSupernodeId, baseTreeHyperparentsPortal.Get(superparentOldSuperId)); + + // NOTE: This part could potentially be made a separate worklet but it does not seem necessary // similarly, the super2hypernode should carry over, but it's harder to test because of the attachment points which // do not have valid old supernode Ids. Instead, we check their superparent's regular global Id against them: if it // matches, then it must be the start of the superarc, in which case it does have an old Id, and we can then use the // existing hypernode Id vtkm::Id superparentOldRegularId = baseTreeSupernodesPortal.Get(superparentOldSuperId); vtkm::Id superparentGlobalId = baseTreeRegularNodeGlobalIdsPortal.Get(superparentOldRegularId); - if (superparentGlobalId == globalRegularIdSetPortal.Get(supernodeSetIndex)) + // Here: globalRegularIdSetValue is the same as globalRegularIdSetPortal.Get(supernodeSetIndex) + if (superparentGlobalId == globalRegularIdSetValue) { - augmentedTreeSuper2hypernodePortal.Set( - newSupernodeId, baseTreeSuper2hypernodePortal.Get(superparentOldSuperId)); + // augmentedTreeSuper2hypernodePortal.Set(newSupernodeId, baseTreeSuper2HypernodePortal.Get(superparentOldSuperId)); + augmentedTreeSuper2hypernodeValue = baseTreeSuper2HypernodePortal.Get(superparentOldSuperId); } else { - augmentedTreeSuper2hypernodePortal.Set(newSupernodeId, - vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT); + // augmentedTreeSuper2hypernodePortal.Set(newSupernodeId, vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT); + augmentedTreeSuper2hypernodeValue = vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT; } - // which round and iteration carry over - augmentedTreeWhichRoundPortal.Set(newSupernodeId, - baseTreeWhichRoundPortal.Get(superparentOldSuperId)); - augmentedTreeWhichIterationPortal.Set(newSupernodeId, - baseTreeWhichIterationPortal.Get(superparentOldSuperId)); + // NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs + // // which round and iteration carry over + // augmentedTreeWhichRoundPortal.Set(newSupernodeId, baseTreeWhichRoundPortal.Get(superparentOldSuperId)); + // augmentedTreeWhichIterationPortal.Set(newSupernodeId, baseTreeWhichIterationPortal.Get(superparentOldSuperId)); // now we deal with the regular-sized arrays - // copy the global regular Id and data value - augmentedTreeRegularNodeGlobalIdsPortal.Set(newRegularId, - globalRegularIdSetPortal.Get(supernodeSetIndex)); - augmentedTreeDataValuesPortal.Set(newRegularId, dataValueSetPortal.Get(supernodeSetIndex)); + // NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs + // // copy the global regular Id and data value + // augmentedTreeRegularNodeGlobalIdsPortal.Set(newRegularId, globalRegularIdSetPortal.Get(supernodeSetIndex)); + // augmentedTreeDataValuesPortal.Set(newRegularId, dataValueSetPortal.Get(supernodeSetIndex)); - // the sort order will be dealt with later - // since all of these nodes are supernodes, they will be their own superparent, which means that: - // a. the regular2node can be set immediately - augmentedTreeRegular2SupernodePortal.Set(newRegularId, newSupernodeId); - // b. as can the superparent - augmentedTreeSuperparentsPortal.Set(newRegularId, newSupernodeId); + // NOTE: This part has been moved out of the worklet and is performed using standard vtkm copy constructs + // // the sort order will be dealt with later + // // since all of these nodes are supernodes, they will be their own superparent, which means that: + // // a. the regular2node can be set immediately + // augmentedTreeRegular2SupernodePortal.Set(newRegularId, newSupernodeId); + // // b. as can the superparent + // augmentedTreeSuperparentsPortal.Set(newRegularId, newSupernodeId); // In serial this worklet implements the following operation /* @@ -434,6 +404,7 @@ private: const vtkm::Id BaseTreeNumRounds; const vtkm::Id AugmentedTreeNumIterations; const vtkm::Id RoundNumber; + const vtkm::Id NumAugmentedTreeSupernodes; }; // CreateSuperarcsWorklet