mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-19 10:35:42 +00:00
58fc99c2f8
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.
138 lines
4.0 KiB
C++
138 lines
4.0 KiB
C++
//============================================================================
|
|
// 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.
|
|
//============================================================================
|
|
#ifndef vtk_m_cont_ArrayRangeComputeTemplate_h
|
|
#define vtk_m_cont_ArrayRangeComputeTemplate_h
|
|
|
|
#include <vtkm/cont/ArrayRangeCompute.h>
|
|
|
|
#include <vtkm/BinaryOperators.h>
|
|
#include <vtkm/Deprecated.h>
|
|
#include <vtkm/VecTraits.h>
|
|
|
|
#include <vtkm/cont/Algorithm.h>
|
|
|
|
#include <limits>
|
|
|
|
namespace vtkm
|
|
{
|
|
namespace cont
|
|
{
|
|
|
|
namespace detail
|
|
{
|
|
|
|
struct ArrayRangeComputeFunctor
|
|
{
|
|
template <typename Device, typename T, typename S>
|
|
VTKM_CONT bool operator()(Device,
|
|
const vtkm::cont::ArrayHandle<T, S>& handle,
|
|
const vtkm::Vec<T, 2>& initialValue,
|
|
vtkm::Vec<T, 2>& result) const
|
|
{
|
|
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
|
using Algorithm = vtkm::cont::DeviceAdapterAlgorithm<Device>;
|
|
result = Algorithm::Reduce(handle, initialValue, vtkm::MinAndMax<T>());
|
|
return true;
|
|
}
|
|
};
|
|
|
|
} // namespace detail
|
|
|
|
namespace internal
|
|
{
|
|
|
|
template <typename T, typename S>
|
|
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeGeneric(
|
|
const vtkm::cont::ArrayHandle<T, S>& input,
|
|
vtkm::cont::DeviceAdapterId device)
|
|
{
|
|
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf, "ArrayRangeCompute");
|
|
|
|
using VecTraits = vtkm::VecTraits<T>;
|
|
using CT = typename VecTraits::ComponentType;
|
|
//We want to minimize the amount of code that we do in try execute as
|
|
//it is repeated for each
|
|
vtkm::cont::ArrayHandle<vtkm::Range> range;
|
|
range.Allocate(VecTraits::NUM_COMPONENTS);
|
|
|
|
if (input.GetNumberOfValues() < 1)
|
|
{
|
|
auto portal = range.WritePortal();
|
|
for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i)
|
|
{
|
|
portal.Set(i, vtkm::Range());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//We used the limits, so that we don't need to sync the array handle
|
|
//
|
|
vtkm::Vec<T, 2> result;
|
|
vtkm::Vec<T, 2> initial;
|
|
initial[0] = T(std::numeric_limits<CT>::max());
|
|
initial[1] = T(std::numeric_limits<CT>::lowest());
|
|
|
|
const bool rangeComputed = vtkm::cont::TryExecuteOnDevice(
|
|
device, vtkm::cont::detail::ArrayRangeComputeFunctor{}, input, initial, result);
|
|
if (!rangeComputed)
|
|
{
|
|
ThrowArrayRangeComputeFailed();
|
|
}
|
|
else
|
|
{
|
|
auto portal = range.WritePortal();
|
|
for (vtkm::IdComponent i = 0; i < VecTraits::NUM_COMPONENTS; ++i)
|
|
{
|
|
portal.Set(i,
|
|
vtkm::Range(VecTraits::GetComponent(result[0], i),
|
|
VecTraits::GetComponent(result[1], i)));
|
|
}
|
|
}
|
|
}
|
|
return range;
|
|
}
|
|
|
|
template <typename S>
|
|
struct ArrayRangeComputeImpl
|
|
{
|
|
template <typename T>
|
|
vtkm::cont::ArrayHandle<vtkm::Range> operator()(const vtkm::cont::ArrayHandle<T, S>& input,
|
|
vtkm::cont::DeviceAdapterId device) const
|
|
{
|
|
return vtkm::cont::internal::ArrayRangeComputeGeneric(input, device);
|
|
}
|
|
};
|
|
|
|
} // namespace internal
|
|
|
|
|
|
template <typename ArrayHandleType>
|
|
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeComputeTemplate(
|
|
const ArrayHandleType& input,
|
|
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{})
|
|
{
|
|
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
|
|
return internal::ArrayRangeComputeImpl<typename ArrayHandleType::StorageTag>{}(input, device);
|
|
}
|
|
|
|
template <typename ArrayHandleType>
|
|
VTKM_DEPRECATED(2.1, "Use precompiled ArrayRangeCompute or ArrayRangeComputeTemplate.")
|
|
inline vtkm::cont::ArrayHandle<vtkm::Range> ArrayRangeCompute(
|
|
const ArrayHandleType& input,
|
|
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{})
|
|
{
|
|
return ArrayRangeComputeTemplate(input, device);
|
|
}
|
|
|
|
}
|
|
} // namespace vtkm::cont
|
|
|
|
#endif //vtk_m_cont_ArrayRangeComputeTemplate_h
|