Precompile ConvertNumComponentsToOffsets

`ConvertNumComponentsToOffsets` has been changed to provide a pre-
compiled version for common arrays. This helps with the dual goals of
compiling less device code and allowing data set builders to not have to
use the device compiler. For cases where you need to compile
`ConvertNumComponentsToOffsets` for a different kind of array, you can
use the internal `ConvertNumComponentsToOffsetsTemplate`.
This commit is contained in:
Kenneth Moreland 2021-09-16 14:02:36 -06:00
parent b1343474c1
commit 4c6522de2b
8 changed files with 248 additions and 60 deletions

@ -16,6 +16,13 @@ device-specific code (e.g. `vtkm::cont::Algorithm`) from core classes like
`CellSetExplicit` so that less code needs to use the device compiler
(especially downstream code).
`ConvertNumComponentsToOffsets` has also been changed to provide a
pre-compiled version for common arrays. This helps with the dual goals of
compiling less device code and allowing data set builders to not have to
use the device compiler. For cases where you need to compile
`ConvertNumComponentsToOffsets` for a different kind of array, you can use
the internal `ConvertNumComponentsToOffsetsTemplate`.
Part of this change removed unnecessary includes of `Algorithm.h` in
`ArrayHandleGroupVecVariable.h` and `CellSetExplicit.h`. This header had to
be added to some classes that were not including it themselves.

@ -177,6 +177,7 @@ set(device_sources
CellSetExtrude.cxx
CellSetStructured.cxx
ColorTable.cxx
ConvertNumComponentsToOffsets.cxx
CoordinateSystem.cxx
DataSet.cxx
DataSetBuilderCurvilinear.cxx

@ -18,9 +18,9 @@
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/CellSet.h>
#include <vtkm/cont/CellSetExplicit.h>
#include <vtkm/cont/ConvertNumComponentsToOffsets.h>
#include <vtkm/cont/Invoker.h>
#include <vtkm/cont/internal/ConnectivityExplicitInternals.h>
#include <vtkm/cont/internal/ConvertNumComponentsToOffsetsTemplate.h>
#include <vtkm/internal/ConnectivityStructuredInternals.h>
#include <vtkm/worklet/WorkletMapTopology.h>
@ -93,7 +93,8 @@ public:
vtkm::Id& connectivityLength /* outparam */,
vtkm::cont::DeviceAdapterId)
{
return vtkm::cont::ConvertNumComponentsToOffsets(numIndices, connectivityLength);
return vtkm::cont::internal::ConvertNumComponentsToOffsetsTemplate(numIndices,
connectivityLength);
}
template <typename CellSetPermutationType, typename OffsetsStorageType>

@ -0,0 +1,103 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ConvertNumComponentsToOffsets.h>
#include <vtkm/cont/ErrorBadType.h>
#include <vtkm/cont/internal/ConvertNumComponentsToOffsetsTemplate.h>
#include <vtkm/List.h>
namespace
{
struct CallNumToOffsets
{
template <typename BaseType>
VTKM_CONT void operator()(BaseType,
const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id>& offsetsArray,
vtkm::cont::DeviceAdapterId device,
bool& converted)
{
if (!numComponentsArray.IsBaseComponentType<BaseType>())
{
// Not the right type.
return;
}
vtkm::cont::internal::ConvertNumComponentsToOffsetsTemplate(
numComponentsArray.ExtractComponent<BaseType>(0, vtkm::CopyFlag::Off), // TODO: Allow copy
offsetsArray,
device);
converted = true;
}
};
} // anonymous namespace
namespace vtkm
{
namespace cont
{
void ConvertNumComponentsToOffsets(const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id>& offsetsArray,
vtkm::Id& componentsArraySize,
vtkm::cont::DeviceAdapterId device)
{
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, offsetsArray, device);
componentsArraySize =
vtkm::cont::ArrayGetValue(offsetsArray.GetNumberOfValues() - 1, offsetsArray);
}
void ConvertNumComponentsToOffsets(const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id>& offsetsArray,
vtkm::cont::DeviceAdapterId device)
{
if (numComponentsArray.GetNumberOfComponentsFlat() > 1)
{
throw vtkm::cont::ErrorBadType(
"ConvertNumComponentsToOffsets only works with arrays of integers, not Vecs.");
}
using SupportedTypes = vtkm::List<vtkm::Int32, vtkm::Int64>;
bool converted = false;
vtkm::ListForEach(
CallNumToOffsets{}, SupportedTypes{}, numComponentsArray, offsetsArray, device, converted);
if (!converted)
{
internal::ThrowCastAndCallException(numComponentsArray, typeid(SupportedTypes));
}
}
vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsets(
const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::Id& componentsArraySize,
vtkm::cont::DeviceAdapterId device)
{
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray;
vtkm::cont::ConvertNumComponentsToOffsets(
numComponentsArray, offsetsArray, componentsArraySize, device);
return offsetsArray;
}
vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsets(
const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::cont::DeviceAdapterId device)
{
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray;
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, offsetsArray, device);
return offsetsArray;
}
} // namespace vtkm::cont
} // namespace vtkm

@ -10,8 +10,11 @@
#ifndef vtk_m_cont_ConvertNumComponentsToOffsets_h
#define vtk_m_cont_ConvertNumComponentsToOffsets_h
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DeviceAdapterTag.h>
#include <vtkm/cont/UnknownArrayHandle.h>
#include <vtkm/cont/vtkm_cont_export.h>
namespace vtkm
{
@ -19,9 +22,10 @@ namespace cont
{
/// \c ConvertNumComponentsToOffsets takes an array of Vec sizes (i.e. the number of components in
/// each Vec) and returns an array of offsets to a packed array of such Vecs. The resulting array
/// can be used with \c ArrayHandleGroupVecVariable.
/// @{
/// `ConvertNumComponentsToOffsets` takes an array of Vec sizes (i.e. the number of components in
/// each `Vec`) and returns an array of offsets to a packed array of such `Vec`s. The resulting
/// array can be used with `ArrayHandleGroupVecVariable`.
///
/// \param numComponentsArray the input array that specifies the number of components in each group
/// Vec.
@ -29,66 +33,36 @@ namespace cont
/// \param offsetsArray (optional) the output \c ArrayHandle, which must have a value type of \c
/// vtkm::Id. If the output \c ArrayHandle is not given, it is returned.
///
/// \param componentsArraySize (optional) a reference to a \c vtkm::Id and is filled with the expected
/// size of the component values array.
/// \param componentsArraySize (optional) a reference to a \c vtkm::Id and is filled with the
/// expected size of the component values array.
///
/// \param device (optional) specifies the device on which to run the conversion.
///
template <typename NumComponentsArrayType, typename OffsetsStorage>
VTKM_CONT void ConvertNumComponentsToOffsets(
const NumComponentsArrayType& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>& offsetsArray,
/// Note that this function is pre-compiled for some set of `ArrayHandle` types. If you get a
/// warning about an inefficient conversion (or the operation fails outright), you might need to
/// use `vtkm::cont::internal::ConvertNumComponentsToOffsetsTemplate`.
///
VTKM_CONT_EXPORT void ConvertNumComponentsToOffsets(
const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id>& offsetsArray,
vtkm::Id& componentsArraySize,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
using namespace vtkm::cont;
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{});
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
VTKM_CONT_EXPORT void ConvertNumComponentsToOffsets(
const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id>& offsetsArray,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{});
Algorithm::ScanExtended(device, make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
componentsArraySize = ArrayGetValue(offsetsArray.GetNumberOfValues() - 1, offsetsArray);
}
template <typename NumComponentsArrayType, typename OffsetsStorage>
VTKM_CONT void ConvertNumComponentsToOffsets(
const NumComponentsArrayType& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>& offsetsArray,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
vtkm::cont::Algorithm::ScanExtended(
device, vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
}
template <typename NumComponentsArrayType>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsets(
const NumComponentsArrayType& numComponentsArray,
VTKM_CONT_EXPORT vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsets(
const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::Id& componentsArraySize,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{});
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray;
vtkm::cont::ConvertNumComponentsToOffsets(
numComponentsArray, offsetsArray, componentsArraySize, device);
return offsetsArray;
}
VTKM_CONT_EXPORT vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsets(
const vtkm::cont::UnknownArrayHandle& numComponentsArray,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny{});
template <typename NumComponentsArrayType>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsets(
const NumComponentsArrayType& numComponentsArray,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
vtkm::Id dummy;
return vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, dummy, device);
}
/// @}
} // namespace vtkm::cont
} // namespace vtkm

@ -19,6 +19,7 @@ set(headers
CastInvalidValue.h
CellLocatorBase.h
ConnectivityExplicitInternals.h
ConvertNumComponentsToOffsetsTemplate.h
DeviceAdapterAlgorithmGeneral.h
DeviceAdapterMemoryManager.h
DeviceAdapterMemoryManagerShared.h

@ -0,0 +1,97 @@
//============================================================================
// 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_internal_ConvertNumComponentsToOffsetsTemplate_h
#define vtk_m_cont_internal_ConvertNumComponentsToOffsetsTemplate_h
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValues.h>
namespace vtkm
{
namespace cont
{
namespace internal
{
/// @{
/// \brief Template implementation of `ConvertNumComponentsToOffsets`.
///
/// This form of the function can be used in situations where the precompiled
/// `ConvertNumComponentsToOffsets` does not include code paths for a desired
/// array.
///
template <typename NumComponentsArrayType, typename OffsetsStorage>
VTKM_CONT void ConvertNumComponentsToOffsetsTemplate(
const NumComponentsArrayType& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>& offsetsArray,
vtkm::Id& componentsArraySize,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
using namespace vtkm::cont;
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
Algorithm::ScanExtended(device, make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
componentsArraySize =
vtkm::cont::ArrayGetValue(offsetsArray.GetNumberOfValues() - 1, offsetsArray);
}
template <typename NumComponentsArrayType, typename OffsetsStorage>
VTKM_CONT void ConvertNumComponentsToOffsetsTemplate(
const NumComponentsArrayType& numComponentsArray,
vtkm::cont::ArrayHandle<vtkm::Id, OffsetsStorage>& offsetsArray,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
VTKM_LOG_SCOPE_FUNCTION(vtkm::cont::LogLevel::Perf);
vtkm::cont::Algorithm::ScanExtended(
device, vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
}
template <typename NumComponentsArrayType>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsetsTemplate(
const NumComponentsArrayType& numComponentsArray,
vtkm::Id& componentsArraySize,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray;
vtkm::cont::internal::ConvertNumComponentsToOffsetsTemplate(
numComponentsArray, offsetsArray, componentsArraySize, device);
return offsetsArray;
}
template <typename NumComponentsArrayType>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> ConvertNumComponentsToOffsetsTemplate(
const NumComponentsArrayType& numComponentsArray,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray;
vtkm::cont::internal::ConvertNumComponentsToOffsetsTemplate(
numComponentsArray, offsetsArray, device);
return offsetsArray;
}
/// @}
} // namespace vtkm::cont::internal
} // namespace vtkm::cont
} // namespace vtkm
#endif // vtk_m_cont_internal_ConvertNumComponentsToOffsetsTemplate_h

@ -1112,7 +1112,9 @@ private:
{
vtkm::Id sourceArraySize;
vtkm::cont::ArrayHandleCounting<vtkm::IdComponent> numComponentsArray(1, 1, ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleCounting<vtkm::IdComponent>(1, 1, ARRAY_SIZE),
numComponentsArray);
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray =
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, sourceArraySize);
@ -1167,7 +1169,9 @@ private:
{
vtkm::Id sourceArraySize;
vtkm::cont::ArrayHandleCounting<vtkm::IdComponent> numComponentsArray(1, 1, ARRAY_SIZE);
vtkm::cont::ArrayHandle<vtkm::Id> numComponentsArray;
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleCounting<vtkm::IdComponent>(1, 1, ARRAY_SIZE),
numComponentsArray);
vtkm::cont::ArrayHandle<vtkm::Id> offsetsArray = vtkm::cont::ConvertNumComponentsToOffsets(
numComponentsArray, sourceArraySize, DeviceAdapterTag());