Add general ArrayCopy
between UnknownArrayHandle
s
Add an overload of `ArrayCopy` that takes `UnknownArrayHandle`s and copies them for (almost) any `ArrayHandle` type. The code uses `CastAndCallWithExtractedArray` to reduce the total number of copy conditions to about 100, which are all precompiled into the library. On a debug build on my mac, this creates a .o file of 21MB. That's not great, but not terrible. Hopefully, this can be used to consolidate copy implementations elsewhere.
This commit is contained in:
parent
26ea2ab420
commit
916a01d7b9
92
vtkm/cont/ArrayCopy.cxx
Normal file
92
vtkm/cont/ArrayCopy.cxx
Normal file
@ -0,0 +1,92 @@
|
||||
//============================================================================
|
||||
// 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/ArrayCopy.h>
|
||||
#include <vtkm/cont/DeviceAdapterList.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Use a worklet because device adapter copies often have an issue with casting the values from the
|
||||
// `ArrayHandleRecomineVec` that comes from `UnknownArrayHandle::CastAndCallWithExtractedArray`.
|
||||
struct CopyWorklet : vtkm::worklet::WorkletMapField
|
||||
{
|
||||
using ControlSignature = void(FieldIn, FieldOut);
|
||||
using ExecutionSignature = void(_1, _2);
|
||||
using InputDomain = _1;
|
||||
|
||||
template <typename InType, typename OutType>
|
||||
void operator()(const InType& in, OutType& out) const
|
||||
{
|
||||
out = in;
|
||||
}
|
||||
};
|
||||
|
||||
struct UnknownCopyOnDevice
|
||||
{
|
||||
bool Called = false;
|
||||
|
||||
template <typename InArrayType, typename OutArrayType>
|
||||
void operator()(vtkm::cont::DeviceAdapterId device,
|
||||
const InArrayType& in,
|
||||
const OutArrayType& out)
|
||||
{
|
||||
if (!this->Called && ((device == vtkm::cont::DeviceAdapterTagAny{}) || (in.IsOnDevice(device))))
|
||||
{
|
||||
vtkm::cont::Invoker invoke(device);
|
||||
invoke(CopyWorklet{}, in, out);
|
||||
this->Called = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct UnknownCopyFunctor2
|
||||
{
|
||||
template <typename OutArrayType, typename InArrayType>
|
||||
void operator()(const OutArrayType& out, const InArrayType& in) const
|
||||
{
|
||||
UnknownCopyOnDevice doCopy;
|
||||
|
||||
// Try to copy on a device that the data are already on.
|
||||
vtkm::ListForEach(doCopy, VTKM_DEFAULT_DEVICE_ADAPTER_LIST{}, in, out);
|
||||
|
||||
// If it was not on any device, call one more time with any adapter to copy wherever.
|
||||
doCopy(vtkm::cont::DeviceAdapterTagAny{}, in, out);
|
||||
}
|
||||
};
|
||||
|
||||
struct UnknownCopyFunctor1
|
||||
{
|
||||
template <typename InArrayType>
|
||||
void operator()(const InArrayType& in, const vtkm::cont::UnknownArrayHandle& out) const
|
||||
{
|
||||
out.Allocate(in.GetNumberOfValues());
|
||||
out.CastAndCallWithExtractedArray(UnknownCopyFunctor2{}, in);
|
||||
}
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
||||
const vtkm::cont::UnknownArrayHandle& destination)
|
||||
{
|
||||
destination.CastAndCallWithExtractedArray(UnknownCopyFunctor1{}, source);
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::cont
|
@ -15,7 +15,7 @@
|
||||
#include <vtkm/cont/DeviceAdapterTag.h>
|
||||
#include <vtkm/cont/ErrorExecution.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/VariantArrayHandle.h>
|
||||
#include <vtkm/cont/UnknownArrayHandle.h>
|
||||
|
||||
#include <vtkm/cont/internal/ArrayHandleDeprecated.h>
|
||||
|
||||
@ -160,46 +160,25 @@ VTKM_CONT void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>&
|
||||
detail::ArrayCopyImpl(source, destination, std::integral_constant<bool, !IsOldStyle::value>{});
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct ArrayCopyFunctor
|
||||
VTKM_CONT_EXPORT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
||||
const vtkm::cont::UnknownArrayHandle& destination);
|
||||
|
||||
template <typename T, typename S>
|
||||
VTKM_CONT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
|
||||
vtkm::cont::ArrayHandle<T, S>& destination)
|
||||
{
|
||||
template <typename InValueType, typename InStorage, typename OutValueType, typename OutStorage>
|
||||
VTKM_CONT void operator()(const vtkm::cont::ArrayHandle<InValueType, InStorage>& source,
|
||||
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination) const
|
||||
using DestType = vtkm::cont::ArrayHandle<T, S>;
|
||||
if (source.IsType<DestType>())
|
||||
{
|
||||
vtkm::cont::ArrayCopy(source, destination);
|
||||
ArrayCopy(source.AsArrayHandle<DestType>(), destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrayCopy(source, vtkm::cont::UnknownArrayHandle(destination));
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Deep copies data in an `UncertainArrayHandle` to an array of a known type.
|
||||
///
|
||||
/// This form of `ArrayCopy` can be used to copy data from an unknown array type to
|
||||
/// an array of a known type. Note that regardless of the source type, the data will
|
||||
/// be deep copied.
|
||||
///
|
||||
template <typename InValueList, typename InStorageList, typename OutValue, typename OutStorage>
|
||||
VTKM_CONT void ArrayCopy(const vtkm::cont::UncertainArrayHandle<InValueList, InStorageList>& src,
|
||||
vtkm::cont::ArrayHandle<OutValue, OutStorage>& dest)
|
||||
{
|
||||
src.CastAndCall(detail::ArrayCopyFunctor{}, dest);
|
||||
}
|
||||
|
||||
/// \brief Deep copies data in a `VariantArrayHandle` to an array of a known type.
|
||||
///
|
||||
/// This form of `ArrayCopy` can be used to copy data from an unknown array type to
|
||||
/// an array of a known type. Note that regardless of the source type, the data will
|
||||
/// be deep copied.
|
||||
///
|
||||
template <typename InTypeList, typename OutValueType, typename OutStorage>
|
||||
VTKM_CONT void ArrayCopy(const vtkm::cont::VariantArrayHandleBase<InTypeList>& source,
|
||||
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination)
|
||||
{
|
||||
source.CastAndCall(detail::ArrayCopyFunctor{}, destination);
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
@ -160,9 +160,10 @@ set(sources
|
||||
TryExecute.cxx
|
||||
)
|
||||
|
||||
# This list of sources has code that uses devices and so might need to be
|
||||
# compiled with a device-specific compiler (like CUDA).
|
||||
set(device_sources
|
||||
# This list of sources has code that uses devices and so might need to be
|
||||
# compiled with a device-specific compiler (like CUDA).
|
||||
set(device_sources
|
||||
ArrayCopy.cxx
|
||||
ArrayRangeCompute.cxx
|
||||
AssignerPartitionedDataSet.cxx
|
||||
BoundsCompute.cxx
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <vtkm/cont/ArrayHandleMultiplexer.h>
|
||||
#include <vtkm/cont/ArrayHandleRecombineVec.h>
|
||||
#include <vtkm/cont/ArrayHandleStride.h>
|
||||
#include <vtkm/cont/CastAndCall.h>
|
||||
#include <vtkm/cont/DefaultTypes.h>
|
||||
|
||||
#include <memory>
|
||||
|
@ -59,6 +59,10 @@ void TryCopy()
|
||||
vtkm::cont::ArrayHandle<ValueType> output;
|
||||
vtkm::cont::ArrayCopy(input, output);
|
||||
TestValues(input, output);
|
||||
|
||||
output.ReleaseResources();
|
||||
vtkm::cont::ArrayCopy(vtkm::cont::UnknownArrayHandle(input), output);
|
||||
TestValues(input, output);
|
||||
}
|
||||
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user