From 58fc99c2f87d9c184ce86d08cc9b8b97eafcd73f Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Mon, 6 Mar 2023 12:35:38 -0700 Subject: [PATCH] Fix fast paths for ArrayRangeCompute The precompiled `ArrayRangeCompute` function was not following proper fast paths for special arrays. For example, when computing the range of an `ArrayHandleUniformPointCoordinates`, the ranges should be taken from the origin and spacing of the special array. However, the precompiled version was calling the generic range computation, which was doing an unnecessary reduction over the entire array. These fast paths have been fixed. These mistakes in the code were caused by quirks in how templated method overloading works. To prevent this mistake from happening again in the precompiled `ArrayRangeCompute` function and elsewhere, all templated forms of `ArrayRangeCompute` have been deprecated. Most will call `ArrayRangeCompute` with no issues. For those that need the templated version, `ArrayRangeComputeTemplate` replaces the old templated `ArrayRangeCompute`. There is exactly one templated declaration of `ArrayRangeComputeTemplate` that uses a class, `ArrayRangeComputeImpl`, with partial specialization to ensure the correct form is used. --- docs/changelog/array-range-fast-paths.md | 18 ++ vtkm/cont/ArrayHandleCartesianProduct.h | 73 +++++++ vtkm/cont/ArrayHandleConstant.h | 33 ++++ vtkm/cont/ArrayHandleCounting.h | 47 +++++ vtkm/cont/ArrayHandleIndex.h | 24 +++ .../ArrayHandleUniformPointCoordinates.cxx | 22 +++ .../cont/ArrayHandleUniformPointCoordinates.h | 12 ++ vtkm/cont/ArrayRangeCompute.cxx | 145 +++----------- vtkm/cont/ArrayRangeCompute.h | 179 ++---------------- vtkm/cont/ArrayRangeComputeTemplate.h | 37 +++- .../testing/UnitTestArrayRangeCompute.cxx | 1 - .../meshtypes/ContourTreeMesh.h | 3 +- .../worklet/OrientCellNormals.h | 1 - 13 files changed, 305 insertions(+), 290 deletions(-) create mode 100644 docs/changelog/array-range-fast-paths.md diff --git a/docs/changelog/array-range-fast-paths.md b/docs/changelog/array-range-fast-paths.md new file mode 100644 index 000000000..7c2c47eae --- /dev/null +++ b/docs/changelog/array-range-fast-paths.md @@ -0,0 +1,18 @@ +# Fast paths for `ArrayRangeCompute` fixed + +The precompiled `ArrayRangeCompute` function was not following proper fast +paths for special arrays. For example, when computing the range of an +`ArrayHandleUniformPointCoordinates`, the ranges should be taken from the +origin and spacing of the special array. However, the precompiled version +was calling the generic range computation, which was doing an unnecessary +reduction over the entire array. These fast paths have been fixed. + +These mistakes in the code were caused by quirks in how templated method +overloading works. To prevent this mistake from happening again in the +precompiled `ArrayRangeCompute` function and elsewhere, all templated forms +of `ArrayRangeCompute` have been deprecated. Most will call +`ArrayRangeCompute` with no issues. For those that need the templated +version, `ArrayRangeComputeTemplate` replaces the old templated +`ArrayRangeCompute`. There is exactly one templated declaration of +`ArrayRangeComputeTemplate` that uses a class, `ArrayRangeComputeImpl`, +with partial specialization to ensure the correct form is used. diff --git a/vtkm/cont/ArrayHandleCartesianProduct.h b/vtkm/cont/ArrayHandleCartesianProduct.h index 649f770ea..037f9ee03 100644 --- a/vtkm/cont/ArrayHandleCartesianProduct.h +++ b/vtkm/cont/ArrayHandleCartesianProduct.h @@ -11,6 +11,8 @@ #define vtk_m_cont_ArrayHandleCartesianProduct_h #include +#include +#include #include #include @@ -486,6 +488,77 @@ struct ArrayExtractComponentImpl> } }; +template +struct ArrayRangeComputeImpl; + +template +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl> +{ + template + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle, + vtkm::cont::StorageTagCartesianProduct>& input_, + vtkm::cont::DeviceAdapterId device) const + { + vtkm::cont::ArrayHandle result; + result.Allocate(3); + auto resultPortal = result.WritePortal(); + + const vtkm::cont::ArrayHandleCartesianProduct, + vtkm::cont::ArrayHandle, + vtkm::cont::ArrayHandle>& input = input_; + vtkm::cont::ArrayHandle componentRangeArray; + + vtkm::IdComponent index = 0; + vtkm::cont::ArrayHandle firstArray = input.GetFirstArray(); + componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl{}(firstArray, device); + vtkm::Id numSubComponents = componentRangeArray.GetNumberOfValues(); + if (numSubComponents > 1) + { + result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On); + resultPortal = result.WritePortal(); + } + auto componentRangePortal = componentRangeArray.ReadPortal(); + for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent) + { + resultPortal.Set(index, componentRangePortal.Get(subComponent)); + ++index; + } + + vtkm::cont::ArrayHandle secondArray = input.GetSecondArray(); + componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl{}(secondArray, device); + numSubComponents = componentRangeArray.GetNumberOfValues(); + if (numSubComponents > 1) + { + result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On); + resultPortal = result.WritePortal(); + } + componentRangePortal = componentRangeArray.ReadPortal(); + for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent) + { + resultPortal.Set(index, componentRangePortal.Get(subComponent)); + ++index; + } + + vtkm::cont::ArrayHandle thirdArray = input.GetThirdArray(); + componentRangeArray = vtkm::cont::internal::ArrayRangeComputeImpl{}(thirdArray, device); + numSubComponents = componentRangeArray.GetNumberOfValues(); + if (numSubComponents > 1) + { + result.Allocate(result.GetNumberOfValues() + numSubComponents - 1, vtkm::CopyFlag::On); + resultPortal = result.WritePortal(); + } + componentRangePortal = componentRangeArray.ReadPortal(); + for (vtkm::IdComponent subComponent = 0; subComponent < numSubComponents; ++subComponent) + { + resultPortal.Set(index, componentRangePortal.Get(subComponent)); + ++index; + } + + return result; + } +}; + } // namespace internal } diff --git a/vtkm/cont/ArrayHandleConstant.h b/vtkm/cont/ArrayHandleConstant.h index 106f4354e..45d67e198 100644 --- a/vtkm/cont/ArrayHandleConstant.h +++ b/vtkm/cont/ArrayHandleConstant.h @@ -12,6 +12,9 @@ #include +#include +#include + namespace vtkm { namespace cont @@ -90,6 +93,36 @@ vtkm::cont::ArrayHandleConstant make_ArrayHandleConstant(T value, vtkm::Id nu { return vtkm::cont::ArrayHandleConstant(value, numberOfValues); } + +namespace internal +{ + +template +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + template + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId) const + { + auto value = vtkm::make_VecFlat(input.ReadPortal().Get(0)); + + vtkm::cont::ArrayHandle result; + result.Allocate(value.GetNumberOfComponents()); + auto resultPortal = result.WritePortal(); + for (vtkm::IdComponent index = 0; index < value.GetNumberOfComponents(); ++index) + { + resultPortal.Set(index, vtkm::Range{ value[index], value[index] }); + } + return result; + } +}; + +} // namespace internal + } } // vtkm::cont diff --git a/vtkm/cont/ArrayHandleCounting.h b/vtkm/cont/ArrayHandleCounting.h index 7f6f08e0d..2840eeaeb 100644 --- a/vtkm/cont/ArrayHandleCounting.h +++ b/vtkm/cont/ArrayHandleCounting.h @@ -12,6 +12,7 @@ #include +#include #include #include @@ -152,6 +153,52 @@ make_ArrayHandleCounting(CountingValueType start, CountingValueType step, vtkm:: { return vtkm::cont::ArrayHandleCounting(start, step, length); } + +namespace internal +{ + +template +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + template + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId) const + { + using Traits = vtkm::VecTraits; + vtkm::cont::ArrayHandle result; + result.Allocate(Traits::NUM_COMPONENTS); + auto portal = result.WritePortal(); + if (portal.GetNumberOfValues() > 0) + { + T first = input.ReadPortal().Get(0); + T last = input.ReadPortal().Get(input.GetNumberOfValues() - 1); + for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex) + { + auto firstComponent = Traits::GetComponent(first, cIndex); + auto lastComponent = Traits::GetComponent(last, cIndex); + portal.Set(cIndex, + vtkm::Range(vtkm::Min(firstComponent, lastComponent), + vtkm::Max(firstComponent, lastComponent))); + } + } + else + { + // Array is empty + for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex) + { + portal.Set(cIndex, vtkm::Range{}); + } + } + return result; + } +}; + +} // namespace internal + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayHandleIndex.h b/vtkm/cont/ArrayHandleIndex.h index d5dcc0fc9..7bccba25b 100644 --- a/vtkm/cont/ArrayHandleIndex.h +++ b/vtkm/cont/ArrayHandleIndex.h @@ -10,6 +10,7 @@ #ifndef vtk_m_cont_ArrayHandleIndex_h #define vtk_m_cont_ArrayHandleIndex_h +#include #include namespace vtkm @@ -71,6 +72,29 @@ VTKM_CONT inline vtkm::cont::ArrayHandleIndex make_ArrayHandleIndex(vtkm::Id len { return vtkm::cont::ArrayHandleIndex(length); } + +namespace internal +{ + +template +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId) const + { + vtkm::cont::ArrayHandle result; + result.Allocate(1); + result.WritePortal().Set(0, vtkm::Range(0, input.GetNumberOfValues() - 1)); + return result; + } +}; + +} // namespace internal + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx b/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx index d12e79b6a..a4b5f5668 100644 --- a/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx +++ b/vtkm/cont/ArrayHandleUniformPointCoordinates.cxx @@ -86,6 +86,28 @@ ArrayExtractComponentImpl::operator()( } } +VTKM_CONT vtkm::cont::ArrayHandle +ArrayRangeComputeImpl::operator()( + const vtkm::cont::ArrayHandleUniformPointCoordinates& input, + vtkm::cont::DeviceAdapterId vtkmNotUsed(device)) const +{ + vtkm::internal::ArrayPortalUniformPointCoordinates portal = input.ReadPortal(); + + // In this portal we know that the min value is the first entry and the + // max value is the last entry. + vtkm::Vec3f minimum = portal.Get(0); + vtkm::Vec3f maximum = portal.Get(portal.GetNumberOfValues() - 1); + + vtkm::cont::ArrayHandle rangeArray; + rangeArray.Allocate(3); + vtkm::cont::ArrayHandle::WritePortalType outPortal = rangeArray.WritePortal(); + outPortal.Set(0, vtkm::Range(minimum[0], maximum[0])); + outPortal.Set(1, vtkm::Range(minimum[1], maximum[1])); + outPortal.Set(2, vtkm::Range(minimum[2], maximum[2])); + + return rangeArray; +} + } // namespace internal } diff --git a/vtkm/cont/ArrayHandleUniformPointCoordinates.h b/vtkm/cont/ArrayHandleUniformPointCoordinates.h index ebbf18975..a0f425d27 100644 --- a/vtkm/cont/ArrayHandleUniformPointCoordinates.h +++ b/vtkm/cont/ArrayHandleUniformPointCoordinates.h @@ -10,6 +10,7 @@ #ifndef vtk_m_cont_ArrayHandleUniformPointCoordinates_h #define vtk_m_cont_ArrayHandleUniformPointCoordinates_h +#include #include #include #include @@ -83,6 +84,17 @@ struct VTKM_CONT_EXPORT ArrayExtractComponentImpl +struct ArrayRangeComputeImpl; + +template <> +struct VTKM_CONT_EXPORT ArrayRangeComputeImpl +{ + VTKM_CONT vtkm::cont::ArrayHandle operator()( + const vtkm::cont::ArrayHandleUniformPointCoordinates& input, + vtkm::cont::DeviceAdapterId device) const; +}; + } // namespace internal } diff --git a/vtkm/cont/ArrayRangeCompute.cxx b/vtkm/cont/ArrayRangeCompute.cxx index 8ff99fdd2..f2e1a0f31 100644 --- a/vtkm/cont/ArrayRangeCompute.cxx +++ b/vtkm/cont/ArrayRangeCompute.cxx @@ -12,118 +12,16 @@ #include -namespace vtkm -{ -namespace cont -{ - -void ThrowArrayRangeComputeFailed() -{ - throw vtkm::cont::ErrorExecution("Failed to run ArrayRangeComputation on any device."); -} - -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(T, Storage) \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle& input, vtkm::cont::DeviceAdapterId device) \ - { \ - return detail::ArrayRangeComputeImpl(input, device); \ - } \ - struct SwallowSemicolon -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(T, N, Storage) \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle, Storage>& input, \ - vtkm::cont::DeviceAdapterId device) \ - { \ - return detail::ArrayRangeComputeImpl(input, device); \ - } \ - struct SwallowSemicolon - -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(Storage) \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int8, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt8, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int16, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt16, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int32, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt32, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Int64, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::UInt64, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Float32, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(vtkm::Float64, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(char, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(signed VTKM_UNUSED_INT_TYPE, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_T(unsigned VTKM_UNUSED_INT_TYPE, Storage) - -#define VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(N, Storage) \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int8, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt8, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int16, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt16, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int32, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt32, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Int64, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::UInt64, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float32, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float64, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(char, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(signed VTKM_UNUSED_INT_TYPE, N, Storage); \ - VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(unsigned VTKM_UNUSED_INT_TYPE, N, Storage) - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(vtkm::cont::StorageTagBasic); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(2, vtkm::cont::StorageTagBasic); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(3, vtkm::cont::StorageTagBasic); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(4, vtkm::cont::StorageTagBasic); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(2, vtkm::cont::StorageTagSOA); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(3, vtkm::cont::StorageTagSOA); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC(4, vtkm::cont::StorageTagSOA); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T(vtkm::cont::StorageTagStride); - -VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagXGCCoordinates); -VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagXGCCoordinates); - -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_T -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_VEC -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_SCALAR_T -#undef VTKM_ARRAY_RANGE_COMPUTE_IMPL_ALL_VEC - -// Special implementation for regular point coordinates, which are easy -// to determine. -VTKM_CONT -vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& array, - vtkm::cont::DeviceAdapterId) -{ - vtkm::internal::ArrayPortalUniformPointCoordinates portal = array.ReadPortal(); - - // In this portal we know that the min value is the first entry and the - // max value is the last entry. - vtkm::Vec3f minimum = portal.Get(0); - vtkm::Vec3f maximum = portal.Get(portal.GetNumberOfValues() - 1); - - vtkm::cont::ArrayHandle rangeArray; - rangeArray.Allocate(3); - vtkm::cont::ArrayHandle::WritePortalType outPortal = rangeArray.WritePortal(); - outPortal.Set(0, vtkm::Range(minimum[0], maximum[0])); - outPortal.Set(1, vtkm::Range(minimum[1], maximum[1])); - outPortal.Set(2, vtkm::Range(minimum[2], maximum[2])); - - return rangeArray; -} - -vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId) -{ - vtkm::cont::ArrayHandle result; - result.Allocate(1); - result.WritePortal().Set(0, vtkm::Range(0, input.GetNumberOfValues() - 1)); - return result; -} +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace { @@ -152,7 +50,7 @@ struct ComputeRangeFunctor vtkm::cont::DeviceAdapterId device, vtkm::cont::ArrayHandle& ranges) const { - ranges = vtkm::cont::ArrayRangeCompute(array, device); + ranges = vtkm::cont::ArrayRangeComputeTemplate(array, device); } // Used with vtkm::ListForEach to get components @@ -172,7 +70,7 @@ struct ComputeRangeFunctor { vtkm::cont::ArrayHandleStride componentArray = array.ExtractComponent(componentI); vtkm::cont::ArrayHandle componentRange = - vtkm::cont::ArrayRangeCompute(componentArray, device); + vtkm::cont::ArrayRangeComputeTemplate(componentArray, device); rangePortal.Set(componentI, componentRange.ReadPortal().Get(0)); } success = true; @@ -191,6 +89,21 @@ vtkm::cont::ArrayHandle ComputeForStorage(const vtkm::cont::Unknown } // anonymous namespace +namespace vtkm +{ +namespace cont +{ + +namespace internal +{ + +void ThrowArrayRangeComputeFailed() +{ + throw vtkm::cont::ErrorExecution("Failed to run ArrayRangeComputation on any device."); +} + +} // namespace internal + vtkm::cont::ArrayHandle ArrayRangeCompute(const vtkm::cont::UnknownArrayHandle& array, vtkm::cont::DeviceAdapterId device) { @@ -214,7 +127,7 @@ vtkm::cont::ArrayHandle ArrayRangeCompute(const vtkm::cont::Unknown { vtkm::cont::ArrayHandleUniformPointCoordinates uniformPoints; array.AsArrayHandle(uniformPoints); - return vtkm::cont::ArrayRangeCompute(uniformPoints, device); + return vtkm::cont::ArrayRangeComputeTemplate(uniformPoints, device); } using CartesianProductStorage = vtkm::cont::StorageTagCartesianProduct ArrayRangeCompute(const vtkm::cont::Unknown } if (array.IsStorageType()) { - return ArrayRangeCompute(array.AsArrayHandle(), device); + return ArrayRangeComputeTemplate(array.AsArrayHandle(), device); } } catch (vtkm::cont::ErrorBadType&) diff --git a/vtkm/cont/ArrayRangeCompute.h b/vtkm/cont/ArrayRangeCompute.h index dfbc01f80..e87b612ea 100644 --- a/vtkm/cont/ArrayRangeCompute.h +++ b/vtkm/cont/ArrayRangeCompute.h @@ -31,7 +31,6 @@ namespace vtkm namespace cont { -///@{ /// \brief Compute the range of the data in an array handle. /// /// Given an `ArrayHandle`, this function computes the range (min and max) of @@ -48,179 +47,27 @@ namespace cont /// Note that the ArrayRangeCompute.h header file contains only precompiled overloads /// of ArrayRangeCompute. This is so that ArrayRangeCompute.h can be included in /// code that does not use a device compiler. If you need to compute array ranges -/// for arbitrary `ArrayHandle`s not in this precompiled list, you need to include -/// ArrayRangeComputeTemplate.h. This contains a templated version of ArrayRangeCompute -/// that will compile for any `ArrayHandle` type not already handled. +/// for arbitrary `ArrayHandle`s not in this precompiled list, you need to use +/// `ArrayRangeComputeTemplate` (declared in `ArrayRangeComputeTemplate`), which +/// will compile for any `ArrayHandle` type not already handled. /// - VTKM_CONT_EXPORT vtkm::cont::ArrayHandle ArrayRangeCompute( const vtkm::cont::UnknownArrayHandle& array, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(T, Storage) \ - VTKM_CONT_EXPORT \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle& input, \ - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()) -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(T, N, Storage) \ - VTKM_CONT_EXPORT \ - VTKM_CONT \ - vtkm::cont::ArrayHandle ArrayRangeCompute( \ - const vtkm::cont::ArrayHandle, Storage>& input, \ - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()) - -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(Storage) \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int8, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt8, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int16, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt16, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int32, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt32, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Int64, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::UInt64, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float32, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(vtkm::Float64, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(char, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(signed VTKM_UNUSED_INT_TYPE, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T(unsigned VTKM_UNUSED_INT_TYPE, Storage) - -#define VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(N, Storage) \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int8, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt8, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int16, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt16, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int32, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt32, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Int64, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::UInt64, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(char, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(signed VTKM_UNUSED_INT_TYPE, N, Storage); \ - VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(unsigned VTKM_UNUSED_INT_TYPE, N, Storage) - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(vtkm::cont::StorageTagBasic); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(2, vtkm::cont::StorageTagBasic); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(3, vtkm::cont::StorageTagBasic); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(4, vtkm::cont::StorageTagBasic); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(2, vtkm::cont::StorageTagSOA); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(3, vtkm::cont::StorageTagSOA); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC(4, vtkm::cont::StorageTagSOA); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T(vtkm::cont::StorageTagStride); - -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float32, 3, vtkm::cont::StorageTagXGCCoordinates); -VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC(vtkm::Float64, 3, vtkm::cont::StorageTagXGCCoordinates); - -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_T -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_VEC -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_SCALAR_T -#undef VTK_M_ARRAY_RANGE_COMPUTE_EXPORT_ALL_VEC - -VTKM_CONT_EXPORT VTKM_CONT vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& array, - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()); - -// Implementation of cartesian products -template -VTKM_CONT inline vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle, - vtkm::cont::StorageTagCartesianProduct>& input_, - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny()) +namespace internal { - vtkm::cont::ArrayHandle result; - result.Allocate(3); - - vtkm::cont::ArrayHandle componentRangeArray; - vtkm::Range componentRange; - - vtkm::cont::ArrayHandleCartesianProduct, - vtkm::cont::ArrayHandle, - vtkm::cont::ArrayHandle> - input = input_; - vtkm::cont::ArrayHandle firstArray = input.GetFirstArray(); - componentRangeArray = vtkm::cont::ArrayRangeCompute(firstArray, device); - componentRange = componentRangeArray.ReadPortal().Get(0); - result.WritePortal().Set(0, componentRange); - - vtkm::cont::ArrayHandle secondArray = input.GetSecondArray(); - componentRangeArray = vtkm::cont::ArrayRangeCompute(secondArray, device); - componentRange = componentRangeArray.ReadPortal().Get(0); - result.WritePortal().Set(1, componentRange); - - vtkm::cont::ArrayHandle thirdArray = input.GetThirdArray(); - componentRangeArray = vtkm::cont::ArrayRangeCompute(thirdArray, device); - componentRange = componentRangeArray.ReadPortal().Get(0); - result.WritePortal().Set(2, componentRange); - - return result; -} - -// Implementation of constant arrays -template -VTKM_CONT inline vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId vtkmNotUsed(device) = vtkm::cont::DeviceAdapterTagAny{}) -{ - using Traits = vtkm::VecTraits; - const T value = vtkm::cont::ArrayHandleConstant(input).GetValue(); - vtkm::IdComponent numComponents = Traits::GetNumberOfComponents(value); - vtkm::cont::ArrayHandle result; - result.Allocate(numComponents); - auto portal = result.WritePortal(); - for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex) - { - auto component = Traits::GetComponent(value, cIndex); - portal.Set(cIndex, vtkm::Range(component, component)); - } - return result; -} - -// Implementation of counting arrays -template -VTKM_CONT inline vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId vtkmNotUsed(device) = vtkm::cont::DeviceAdapterTagAny{}) -{ - using Traits = vtkm::VecTraits; - vtkm::cont::ArrayHandle result; - result.Allocate(Traits::NUM_COMPONENTS); - auto portal = result.WritePortal(); - if (portal.GetNumberOfValues() > 0) - { - T first = input.ReadPortal().Get(0); - T last = input.ReadPortal().Get(input.GetNumberOfValues() - 1); - for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex) - { - auto firstComponent = Traits::GetComponent(first, cIndex); - auto lastComponent = Traits::GetComponent(last, cIndex); - portal.Set(cIndex, - vtkm::Range(vtkm::Min(firstComponent, lastComponent), - vtkm::Max(firstComponent, lastComponent))); - } - } - else - { - // Array is empty - for (vtkm::IdComponent cIndex = 0; cIndex < Traits::NUM_COMPONENTS; ++cIndex) - { - portal.Set(cIndex, vtkm::Range{}); - } - } - return result; -} - -// Implementation of index arrays -VTKM_CONT_EXPORT vtkm::cont::ArrayHandle ArrayRangeCompute( - const vtkm::cont::ArrayHandle& input, - vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}); -///@} VTKM_CONT_EXPORT void ThrowArrayRangeComputeFailed(); + +} // namespace internal + +VTKM_DEPRECATED(2.1, "Moved to vtkm::cont::internal.") +inline void ThrowArrayRangeComputeFailed() +{ + internal::ThrowArrayRangeComputeFailed(); +} + } } // namespace vtkm::cont diff --git a/vtkm/cont/ArrayRangeComputeTemplate.h b/vtkm/cont/ArrayRangeComputeTemplate.h index 2e593e1aa..aeab8c3c5 100644 --- a/vtkm/cont/ArrayRangeComputeTemplate.h +++ b/vtkm/cont/ArrayRangeComputeTemplate.h @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -42,8 +43,13 @@ struct ArrayRangeComputeFunctor } }; +} // namespace detail + +namespace internal +{ + template -inline vtkm::cont::ArrayHandle ArrayRangeComputeImpl( +inline vtkm::cont::ArrayHandle ArrayRangeComputeGeneric( const vtkm::cont::ArrayHandle& input, vtkm::cont::DeviceAdapterId device) { @@ -74,7 +80,7 @@ inline vtkm::cont::ArrayHandle ArrayRangeComputeImpl( initial[1] = T(std::numeric_limits::lowest()); const bool rangeComputed = vtkm::cont::TryExecuteOnDevice( - device, detail::ArrayRangeComputeFunctor{}, input, initial, result); + device, vtkm::cont::detail::ArrayRangeComputeFunctor{}, input, initial, result); if (!rangeComputed) { ThrowArrayRangeComputeFailed(); @@ -93,17 +99,38 @@ inline vtkm::cont::ArrayHandle ArrayRangeComputeImpl( return range; } -} // namespace detail +template +struct ArrayRangeComputeImpl +{ + template + vtkm::cont::ArrayHandle operator()(const vtkm::cont::ArrayHandle& input, + vtkm::cont::DeviceAdapterId device) const + { + return vtkm::cont::internal::ArrayRangeComputeGeneric(input, device); + } +}; + +} // namespace internal template -inline vtkm::cont::ArrayHandle ArrayRangeCompute( +inline vtkm::cont::ArrayHandle ArrayRangeComputeTemplate( const ArrayHandleType& input, vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) { VTKM_IS_ARRAY_HANDLE(ArrayHandleType); - return detail::ArrayRangeComputeImpl(input, device); + return internal::ArrayRangeComputeImpl{}(input, device); } + +template +VTKM_DEPRECATED(2.1, "Use precompiled ArrayRangeCompute or ArrayRangeComputeTemplate.") +inline vtkm::cont::ArrayHandle ArrayRangeCompute( + const ArrayHandleType& input, + vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{}) +{ + return ArrayRangeComputeTemplate(input, device); +} + } } // namespace vtkm::cont diff --git a/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx b/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx index a5a2e245c..05f3b81f2 100644 --- a/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx +++ b/vtkm/cont/testing/UnitTestArrayRangeCompute.cxx @@ -65,7 +65,6 @@ template void CheckRange(const vtkm::cont::ArrayHandle& array) { VerifyRange(array, vtkm::cont::ArrayRangeCompute(array)); - VerifyRange(array, vtkm::cont::ArrayRangeCompute(vtkm::cont::UnknownArrayHandle{ array })); } template diff --git a/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h b/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h index 2971fb492..197f50f69 100644 --- a/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h +++ b/vtkm/filter/scalar_topology/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h @@ -576,7 +576,8 @@ template inline void ContourTreeMesh::ComputeMaxNeighbors() { auto neighborCounts = make_ArrayHandleOffsetsToNumComponents(this->NeighborOffsets); - vtkm::cont::ArrayHandle rangeArray = vtkm::cont::ArrayRangeCompute(neighborCounts); + vtkm::cont::ArrayHandle rangeArray = + vtkm::cont::ArrayRangeComputeTemplate(neighborCounts); this->MaxNeighbors = static_cast(rangeArray.ReadPortal().Get(0).Max); } diff --git a/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h b/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h index eb1702392..c76ee9f07 100644 --- a/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h +++ b/vtkm/filter/vector_analysis/worklet/OrientCellNormals.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include