Remove CombinedVector. Update ContourTreeMesh::MergeWith accordingly.

This commit is contained in:
Oliver Ruebel 2020-11-15 00:18:20 -08:00 committed by Gunther H. Weber
parent 2fa6855222
commit 41006405b3
5 changed files with 130 additions and 200 deletions

@ -79,7 +79,6 @@
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/ArcComparator.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/CombinedOtherStartIndexNNeighboursWorklet.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/CombinedSimulatedSimplicityIndexComparator.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/CombinedVector.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/CombinedVectorDifferentFromNext.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/CompressNeighboursWorklet.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/ComputeMaxNeighboursWorklet.h>
@ -536,15 +535,6 @@ inline void ContourTreeMesh<FieldType>::MergeWith(ContourTreeMesh<FieldType>& ot
other.DebugPrint("OTHER ContourTreeMesh", __FILE__, __LINE__);
#endif
vtkm::cont::Token allToken;
mesh_dem_contourtree_mesh_inc::CombinedVectorExecObj<vtkm::Id> allGlobalIndicesExecObj(
this->GlobalMeshIndex, other.GlobalMeshIndex);
auto allGlobalIndices = allGlobalIndicesExecObj.PrepareForExecution(DeviceTag(), allToken);
mesh_dem_contourtree_mesh_inc::CombinedVectorExecObj<FieldType> allSortedValuesExecObj(
this->SortedValues, other.SortedValues);
auto allSortedValues = allSortedValuesExecObj.PrepareForExecution(DeviceTag(), allToken);
//auto allGlobalIndices = CombinedVector<FieldType(this->thisGlobalMeshIndex, other.GlobalMeshIndex);
// Create combined sort order
// TODO This vector could potentially be implemented purely as a smart array handle to reduce memory usage
IdArrayType overallSortOrder;
@ -555,8 +545,15 @@ inline void ContourTreeMesh<FieldType>::MergeWith(ContourTreeMesh<FieldType>& ot
MarkOther markOtherFunctor;
auto otherIndices = vtkm::cont::make_ArrayHandleTransform(
vtkm::cont::ArrayHandleIndex(other.NumVertices), markOtherFunctor);
contourtree_mesh_inc_ns::CombinedSimulatedSimplicityIndexComparator<FieldType, DeviceTag>
cssicFunctor(allSortedValues, allGlobalIndices);
contourtree_mesh_inc_ns::CombinedSimulatedSimplicityIndexComparator<FieldType>
cssicFunctorExecObj(
this->GlobalMeshIndex, other.GlobalMeshIndex, this->SortedValues, other.SortedValues);
// TODO FIXME We here need to force the arrays for the comparator onto the CPU by using DeviceAdapterTagSerial
// Instead we should implement the merge of the arrays on the device and not use std::merge
vtkm::cont::Token tempToken;
auto cssicFunctor =
cssicFunctorExecObj.PrepareForExecution(vtkm::cont::DeviceAdapterTagSerial(), tempToken);
// Merge the arrays
std::merge(vtkm::cont::ArrayPortalToIteratorBegin(thisIndices.ReadPortal()),
vtkm::cont::ArrayPortalToIteratorEnd(thisIndices.ReadPortal()),
vtkm::cont::ArrayPortalToIteratorBegin(otherIndices.ReadPortal()),
@ -574,10 +571,12 @@ inline void ContourTreeMesh<FieldType>::MergeWith(ContourTreeMesh<FieldType>& ot
IdArrayType overallSortIndex;
overallSortIndex.Allocate(overallSortOrder.GetNumberOfValues());
{
vtkm::cont::Token token;
// Functor return 0,1 for each element of a CombinedVector depending on whethern the current value is different from the next
mesh_dem_contourtree_mesh_inc::CombinedVectorDifferentFromNext<vtkm::Id, DeviceTag>
differentFromNextFunctor(&allGlobalIndices, overallSortOrder, token);
// Functor return 0,1 for each element depending on whethern the current value is different from the next
vtkm::cont::Token tempToken;
mesh_dem_contourtree_mesh_inc::CombinedVectorDifferentFromNext<DeviceTag>
differentFromNextFunctor(
this->GlobalMeshIndex, other.GlobalMeshIndex, overallSortOrder, tempToken);
// Array based on the functor
auto differentFromNextArr = vtkm::cont::make_ArrayHandleTransform(
vtkm::cont::ArrayHandleIndex(overallSortIndex.GetNumberOfValues() - 1),
differentFromNextFunctor);
@ -585,12 +584,15 @@ inline void ContourTreeMesh<FieldType>::MergeWith(ContourTreeMesh<FieldType>& ot
// Compute the exclusive scan of our transformed combined vector
overallSortIndex.WritePortal().Set(0, 0);
IdArrayType tempArr;
vtkm::cont::Algorithm::ScanInclusive(differentFromNextArr, tempArr);
// Here we pass in the DeviceTag to make sure the device we used for CombinedVectorDifferentFromNext
// is the same as what we use for the algorithms
vtkm::cont::Algorithm::ScanInclusive(DeviceTag(), differentFromNextArr, tempArr);
vtkm::cont::Algorithm::CopySubRange(
tempArr, 0, tempArr.GetNumberOfValues(), overallSortIndex, 1);
DeviceTag(), tempArr, 0, tempArr.GetNumberOfValues(), overallSortIndex, 1);
}
vtkm::Id numVerticesCombined =
overallSortIndex.ReadPortal().Get(overallSortIndex.GetNumberOfValues() - 1) + 1;
#ifdef DEBUG_PRINT
std::cout << "OverallSortIndex.size " << overallSortIndex.GetNumberOfValues() << std::endl;
PrintIndices("overallSortIndex", overallSortIndex);

@ -67,7 +67,6 @@ set(headers
ComputeMaxNeighboursWorklet.h
FindStartIndexWorklet.h
ReplaceArcNumWithToVertexWorklet.h
CombinedVector.h
CombinedSimulatedSimplicityIndexComparator.h
InitToCombinedSortOrderArraysWorklet.h
CombinedOtherStartIndexNNeighboursWorklet.h

@ -65,7 +65,6 @@
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/worklet/contourtree_augmented/Types.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/CombinedVector.h>
namespace vtkm
{
@ -77,43 +76,74 @@ namespace mesh_dem_contourtree_mesh_inc
{
// comparator used for initial sort of data values
/// Implementation of the comparator used initial sort of data values in ContourTreeMesh<FieldType>::MergeWith
template <typename FieldType, typename DeviceAdapter>
class CombinedSimulatedSimplicityIndexComparator
class CombinedSimulatedSimplicityIndexComparatorImpl
{
public:
typedef CombinedVector<FieldType, DeviceAdapter> CombinedDataVector;
typedef CombinedVector<vtkm::Id, DeviceAdapter> CombinedIndexVector;
using IdPortalType =
typename vtkm::cont::ArrayHandle<vtkm::Id>::template ExecutionTypes<DeviceAdapter>::PortalConst;
using ValuePortalType = typename vtkm::cont::ArrayHandle<FieldType>::template ExecutionTypes<
DeviceAdapter>::PortalConst;
VTKM_CONT
CombinedSimulatedSimplicityIndexComparator(const CombinedDataVector& val,
const CombinedIndexVector& idx)
: Values(val)
, Indices(idx)
CombinedSimulatedSimplicityIndexComparatorImpl(
const IdArrayType& thisGlobalMeshIndex,
const IdArrayType& otherGlobalMeshIndex,
const vtkm::cont::ArrayHandle<FieldType>& thisSortedValues,
const vtkm::cont::ArrayHandle<FieldType>& otherSortedValues,
vtkm::cont::Token& token)
{
this->ThisGlobalMeshIndex = thisGlobalMeshIndex.PrepareForInput(DeviceAdapter(), token);
this->OtherGlobalMeshIndex = otherGlobalMeshIndex.PrepareForInput(DeviceAdapter(), token);
;
this->ThisSortedValues = thisSortedValues.PrepareForInput(DeviceAdapter(), token);
this->OtherSortedValues = otherSortedValues.PrepareForInput(DeviceAdapter(), token);
}
VTKM_EXEC_CONT
inline vtkm::Id GetGlobalMeshIndex(vtkm::Id idx) const
{
return IsThis(idx) ? this->ThisGlobalMeshIndex.Get(MaskedIndex(idx))
: this->OtherGlobalMeshIndex.Get(MaskedIndex(idx));
}
VTKM_EXEC_CONT
inline FieldType GetSortedValue(vtkm::Id idx) const
{
return IsThis(idx) ? this->ThisSortedValues.Get(MaskedIndex(idx))
: this->OtherSortedValues.Get(MaskedIndex(idx));
}
VTKM_EXEC_CONT
bool operator()(vtkm::Id i, vtkm::Id j) const
{ // operator()
// get values
FieldType val_i = this->Values[i];
FieldType val_j = this->Values[j];
FieldType val_i = this->GetSortedValue(i);
FieldType val_j = this->GetSortedValue(j);
// value comparison
if (val_i < val_j)
{
return true;
}
if (val_j < val_i)
{
return false;
}
// get indices
vtkm::Id idx_i = this->Indices[i];
vtkm::Id idx_j = this->Indices[j];
vtkm::Id idx_i = this->GetGlobalMeshIndex(i);
vtkm::Id idx_j = this->GetGlobalMeshIndex(j);
// index comparison for simulated simplicity
if (idx_i < idx_j)
{
return true;
}
if (idx_j < idx_i)
{
return false;
}
// fallback - always false
return false;
@ -149,10 +179,52 @@ public:
} // operator()
private:
const CombinedDataVector& Values;
const CombinedIndexVector& Indices;
IdPortalType ThisGlobalMeshIndex;
IdPortalType OtherGlobalMeshIndex;
ValuePortalType ThisSortedValues;
ValuePortalType OtherSortedValues;
};
/// Execution object for the comparator used initial sort of data values in ContourTreeMesh<FieldType>::MergeWith
template <typename FieldType>
class CombinedSimulatedSimplicityIndexComparator : public vtkm::cont::ExecutionObjectBase
{
public:
// constructor
VTKM_CONT
CombinedSimulatedSimplicityIndexComparator(
const IdArrayType& thisGlobalMeshIndex,
const IdArrayType& otherGlobalMeshIndex,
const vtkm::cont::ArrayHandle<FieldType>& thisSortedValues,
const vtkm::cont::ArrayHandle<FieldType>& otherSortedValues)
: ThisGlobalMeshIndex(thisGlobalMeshIndex)
, OtherGlobalMeshIndex(otherGlobalMeshIndex)
, ThisSortedValues(thisSortedValues)
, OtherSortedValues(otherSortedValues)
{
}
template <typename DeviceAdapter>
VTKM_CONT CombinedSimulatedSimplicityIndexComparatorImpl<FieldType, DeviceAdapter>
PrepareForExecution(DeviceAdapter, vtkm::cont::Token& token)
{
return CombinedSimulatedSimplicityIndexComparatorImpl<FieldType, DeviceAdapter>(
this->ThisGlobalMeshIndex,
this->OtherGlobalMeshIndex,
this->ThisSortedValues,
this->OtherSortedValues,
token);
}
private:
IdArrayType ThisGlobalMeshIndex;
IdArrayType OtherGlobalMeshIndex;
vtkm::cont::ArrayHandle<FieldType> ThisSortedValues;
vtkm::cont::ArrayHandle<FieldType> OtherSortedValues;
}; // CombinedSimulatedSimplicityIndexComparator
} // namespace mesh_dem_contourtree_mesh_inc
} // namespace contourtree_augmented
} // namespace worklet

@ -1,149 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
// Copyright (c) 2018, The Regents of the University of California, through
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
// from the U.S. Dept. of Energy). All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// (1) Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// (2) Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// (3) Neither the name of the University of California, Lawrence Berkeley National
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//=============================================================================
//
// This code is an extension of the algorithm presented in the paper:
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
// (LDAV), October 2016, Baltimore, Maryland.
//
// The PPP2 algorithm and software were jointly developed by
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
// Oliver Ruebel (LBNL)
//==============================================================================
#ifndef vtk_m_worklet_contourtree_augmented_contourtree_mesh_inc_combined_vector_h
#define vtk_m_worklet_contourtree_augmented_contourtree_mesh_inc_combined_vector_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ExecutionObjectBase.h>
#include <vtkm/worklet/contourtree_augmented/Types.h>
namespace vtkm
{
namespace worklet
{
namespace contourtree_augmented
{
namespace mesh_dem_contourtree_mesh_inc
{
template <typename T, typename DeviceAdapter>
class CombinedVector
{
public:
typedef typename vtkm::cont::ArrayHandle<T>::template ExecutionTypes<DeviceAdapter>::PortalConst
TArrayPortalType;
VTKM_CONT
CombinedVector(const vtkm::cont::ArrayHandle<T>& ThisVector,
const vtkm::cont::ArrayHandle<T>& OtherVector,
vtkm::cont::Token& token)
{
this->ThisVectorPortal = ThisVector.PrepareForInput(DeviceAdapter(), token);
this->OtherVectorPortal = OtherVector.PrepareForInput(DeviceAdapter(), token);
}
// See contourtree_augmented/Types.h for definitions of IsThis() and CV_OTHER_FLAG
VTKM_EXEC_CONT
T operator[](vtkm::Id idx) const
{
return IsThis(idx) ? this->ThisVectorPortal.Get(MaskedIndex(idx))
: this->OtherVectorPortal.Get(MaskedIndex(idx));
}
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const
{
return ThisVectorPortal.GetNumberOfValues() + OtherVectorPortal.GetNumberOfValues();
}
private:
TArrayPortalType ThisVectorPortal;
TArrayPortalType OtherVectorPortal;
}; // class CombinedVector
template <typename T>
class CombinedVectorExecObj : public vtkm::cont::ExecutionObjectBase
{
public:
CombinedVectorExecObj(const vtkm::cont::ArrayHandle<T>& tV, const vtkm::cont::ArrayHandle<T>& oV)
: ThisVector(tV)
, OtherVector(oV)
{
}
template <typename DeviceTag>
CombinedVector<T, DeviceTag> PrepareForExecution(DeviceTag, vtkm::cont::Token& token) const
{
return CombinedVector<T, DeviceTag>(this->ThisVector, this->OtherVector, token);
}
vtkm::Id GetNumberOfValues() const
{
return ThisVector.GetNumberOfValues() + OtherVector.GetNumberOfValues();
}
private:
const vtkm::cont::ArrayHandle<T>& ThisVector;
const vtkm::cont::ArrayHandle<T>& OtherVector;
}; // class CombinedVectorExecObj
} // namespace mesh_dem_contourtree_mesh_inc
} // namespace contourtree_augmented
} // namespace worklet
} // namespace vtkm
#endif

@ -64,9 +64,8 @@
#define vtk_m_worklet_contourtree_augmented_contourtree_mesh_inc_combined_vector_different_from_next_h
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ExecutionObjectBase.h>
#include <vtkm/cont/ExecutionAndControlObjectBase.h>
#include <vtkm/worklet/contourtree_augmented/Types.h>
#include <vtkm/worklet/contourtree_augmented/meshtypes/contourtreemesh/CombinedVector.h>
namespace vtkm
{
@ -77,41 +76,48 @@ namespace contourtree_augmented
namespace mesh_dem_contourtree_mesh_inc
{
// transform functor to compute if element i is different from element i+1 in an arrays. The resulting array should hence
// be 1 element shorter than the input arrays
template <typename T, typename DeviceAdapter>
/// transform functor to compute if element i is different from element i+1 in an arrays. The resulting array should hence
/// be 1 element shorter than the input arrays
template <typename DeviceAdapter>
class CombinedVectorDifferentFromNext
{
public:
typedef typename vtkm::worklet::contourtree_augmented::IdArrayType::template ExecutionTypes<
DeviceAdapter>::PortalConst SortOrderPortalType;
using IdPortalType =
typename vtkm::cont::ArrayHandle<vtkm::Id>::template ExecutionTypes<DeviceAdapter>::PortalConst;
VTKM_EXEC_CONT
CombinedVectorDifferentFromNext()
: DataArray()
{
}
CombinedVectorDifferentFromNext() {}
VTKM_CONT
CombinedVectorDifferentFromNext(CombinedVector<T, DeviceAdapter>* inDataArray,
CombinedVectorDifferentFromNext(const IdArrayType& thisGlobalMeshIndex,
const IdArrayType& otherGlobalMeshIndex,
const IdArrayType& sortOrder,
vtkm::cont::Token& token)
: DataArray(inDataArray)
{
this->OverallSortOrderPortal = sortOrder.PrepareForInput(DeviceAdapter(), token);
this->ThisGlobalMeshIndex = thisGlobalMeshIndex.PrepareForInput(DeviceAdapter(), token);
this->OtherGlobalMeshIndex = otherGlobalMeshIndex.PrepareForInput(DeviceAdapter(), token);
}
VTKM_EXEC_CONT
inline vtkm::Id GetGlobalMeshIndex(vtkm::Id idx) const
{
return IsThis(idx) ? this->ThisGlobalMeshIndex.Get(MaskedIndex(idx))
: this->OtherGlobalMeshIndex.Get(MaskedIndex(idx));
}
VTKM_EXEC_CONT
vtkm::Id operator()(vtkm::Id i) const
{
vtkm::Id currGlobalIdx = (*this->DataArray)[this->OverallSortOrderPortal.Get(i)];
vtkm::Id nextGlobalIdx = (*this->DataArray)[this->OverallSortOrderPortal.Get(i + 1)];
vtkm::Id currGlobalIdx = this->GetGlobalMeshIndex(this->OverallSortOrderPortal.Get(i));
vtkm::Id nextGlobalIdx = this->GetGlobalMeshIndex(this->OverallSortOrderPortal.Get(i + 1));
return (currGlobalIdx != nextGlobalIdx) ? 1 : 0;
}
private:
SortOrderPortalType OverallSortOrderPortal;
const CombinedVector<T, DeviceAdapter>* DataArray;
IdPortalType OverallSortOrderPortal;
IdPortalType ThisGlobalMeshIndex;
IdPortalType OtherGlobalMeshIndex;
};