Merge topic 'shallow-array-copy'

1fb114172 Update code to use ArrayCopyShallowIfPossible
5c36eafe5 Add ArrayCopyShallowIfPossible

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Li-Ta Lo <ollie@lanl.gov>
Merge-request: !2529
This commit is contained in:
Kenneth Moreland 2021-07-21 15:29:23 +00:00 committed by Kitware Robot
commit bf6d6ca517
10 changed files with 79 additions and 71 deletions

@ -0,0 +1,12 @@
# Added `ArrayCopyShallowIfPossible`
Often times you have an array of an unknown type (likely from a data set),
and you need it to be of a particular type (or can make a reasonable but
uncertain assumption about it being a particular type). You really just
want a shallow copy (a reference in a concrete `ArrayHandle`) if that is
possible.
`ArrayCopyShallowIfPossible` pulls an array of a specific type from an
`UnknownArrayHandle`. If the type is compatible, it will perform a shallow
copy. If it is not possible, a deep copy is performed to get it to the
correct type.

@ -130,6 +130,8 @@ VTKM_CONT void ArrayCopyImpl(const vtkm::cont::ArrayHandle<T, S>& source,
/// This should work on some non-writable array handles as well, as long as
/// both \a source and \a destination are the same type.
///
/// @{
///
template <typename InValueType, typename InStorage, typename OutValueType, typename OutStorage>
VTKM_CONT void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>& source,
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination)
@ -169,7 +171,7 @@ VTKM_CONT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
vtkm::cont::ArrayHandle<T, S>& destination)
{
using DestType = vtkm::cont::ArrayHandle<T, S>;
if (source.IsType<DestType>())
if (source.CanConvert<DestType>())
{
ArrayCopy(source.AsArrayHandle<DestType>(), destination);
}
@ -182,6 +184,37 @@ VTKM_CONT void ArrayCopy(const vtkm::cont::UnknownArrayHandle& source,
}
}
/// @}
/// \brief Copies from an unknown to a known array type.
///
/// Often times you have an array of an unknown type (likely from a data set),
/// and you need it to be of a particular type (or can make a reasonable but uncertain
/// assumption about it being a particular type). You really just want a shallow
/// copy (a reference in a concrete `ArrayHandle`) if that is possible.
///
/// `ArrayCopyShallowIfPossible` pulls an array of a specific type from an
/// `UnknownArrayHandle`. If the type is compatible, it will perform a shallow copy.
/// If it is not possible, a deep copy is performed to get it to the correct type.
///
template <typename T, typename S>
VTKM_CONT void ArrayCopyShallowIfPossible(const vtkm::cont::UnknownArrayHandle source,
vtkm::cont::ArrayHandle<T, S>& destination)
{
using DestType = vtkm::cont::ArrayHandle<T, S>;
if (source.CanConvert<DestType>())
{
source.AsArrayHandle(destination);
}
else
{
vtkm::cont::UnknownArrayHandle destWrapper(destination);
ArrayCopy(source, destWrapper);
// Destination array should not change, but just in case.
destWrapper.AsArrayHandle(destination);
}
}
}
} // namespace vtkm::cont

@ -120,11 +120,32 @@ void TryCopy()
}
}
void TryArrayCopyShallowIfPossible()
{
vtkm::cont::ArrayHandle<vtkm::Float32> input = MakeInputArray<vtkm::Float32>();
vtkm::cont::UnknownArrayHandle unknownInput = input;
{
std::cout << "shallow copy" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Float32> output;
vtkm::cont::ArrayCopyShallowIfPossible(unknownInput, output);
VTKM_TEST_ASSERT(input == output, "Copy was not shallow");
}
{
std::cout << "cannot shallow copy" << std::endl;
vtkm::cont::ArrayHandle<vtkm::Float64> output;
vtkm::cont::ArrayCopyShallowIfPossible(unknownInput, output);
TestValues(input, output);
}
}
void TestArrayCopy()
{
TryCopy<vtkm::Id>();
TryCopy<vtkm::IdComponent>();
TryCopy<vtkm::Float32>();
TryArrayCopyShallowIfPossible();
}
} // anonymous namespace

@ -13,6 +13,7 @@
#include <vtkm/filter/ImageDifference.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/Logging.h>
@ -89,7 +90,7 @@ inline VTKM_CONT vtkm::cont::DataSet ImageDifference::DoExecute(
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info, "Not performing average");
primaryOutput = primary;
secondaryField.GetData().AsArrayHandle(secondaryOutput);
vtkm::cont::ArrayCopyShallowIfPossible(secondaryField.GetData(), secondaryOutput);
}
if (this->PixelShiftRadius > 0)

@ -74,11 +74,7 @@ protected:
FieldHandleType fieldArray;
auto fieldData = ds.GetField(fieldNm).GetData();
if (fieldData.IsType<FieldHandleType>())
fieldArray = fieldData.AsArrayHandle<FieldHandleType>();
else
vtkm::cont::ArrayCopy(
fieldData.ResetTypes<vtkm::TypeListFieldVec3, VTKM_DEFAULT_STORAGE_LIST>(), fieldArray);
vtkm::cont::ArrayCopyShallowIfPossible(fieldData, fieldArray);
return fieldArray;
}

@ -306,16 +306,7 @@ void VTKDataSetReaderBase::ReadCells(vtkm::cont::ArrayHandle<vtkm::Id>& connecti
internal::parseAssert(tag == "CONNECTIVITY");
auto conn =
this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, dataType, connSize, 1);
if (conn.IsValueType<vtkm::Id>())
{
conn.AsArrayHandle(connectivity);
}
else
{
conn.CastAndCallForTypes<vtkm::List<vtkm::Int64, vtkm::Int32>,
vtkm::List<vtkm::cont::StorageTagBasic>>(
[&](const auto& connAH) { vtkm::cont::ArrayCopy(connAH, connectivity); });
}
vtkm::cont::ArrayCopyShallowIfPossible(conn, connectivity);
}
}

@ -91,39 +91,9 @@ void VTKRectilinearGridReader::Read()
// We need to store all coordinate arrays as FloatDefault.
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Xc, Yc, Zc;
// But the UnknownArrayHandle has type fileStorageDataType.
// If the fileStorageDataType is the same as the storage type, no problem:
if (fileStorageDataType == vtkm::io::internal::DataTypeName<vtkm::FloatDefault>::Name())
{
X.AsArrayHandle(Xc);
Y.AsArrayHandle(Yc);
Z.AsArrayHandle(Zc);
}
else
{
// Two cases if the data in the file differs from FloatDefault:
if (fileStorageDataType == "float")
{
vtkm::cont::ArrayHandle<vtkm::Float32> Xcf, Ycf, Zcf;
X.AsArrayHandle(Xcf);
Y.AsArrayHandle(Ycf);
Z.AsArrayHandle(Zcf);
vtkm::cont::ArrayCopy(Xcf, Xc);
vtkm::cont::ArrayCopy(Ycf, Yc);
vtkm::cont::ArrayCopy(Zcf, Zc);
}
else
{
vtkm::cont::ArrayHandle<vtkm::Float64> Xcd, Ycd, Zcd;
X.AsArrayHandle(Xcd);
Y.AsArrayHandle(Ycd);
Z.AsArrayHandle(Zcd);
vtkm::cont::ArrayCopy(Xcd, Xc);
vtkm::cont::ArrayCopy(Ycd, Yc);
vtkm::cont::ArrayCopy(Zcd, Zc);
}
}
// As a postscript to this somewhat branchy code, I thought that X.CopyTo(Xc) should be able to cast to the value_type of Xc.
// But that would break the ability to make the cast lazy, and hence if you change it you induce performance bugs.
vtkm::cont::ArrayCopyShallowIfPossible(X, Xc);
vtkm::cont::ArrayCopyShallowIfPossible(Y, Yc);
vtkm::cont::ArrayCopyShallowIfPossible(Z, Zc);
coords = vtkm::cont::make_ArrayHandleCartesianProduct(Xc, Yc, Zc);
vtkm::cont::CoordinateSystem coordSys("coordinates", coords);

@ -710,7 +710,7 @@ public:
vtkm::cont::ArrayHandleCartesianProduct<DefaultHandle, DefaultHandle, DefaultHandle>;
auto coordData = coord.GetData();
if (coordData.IsType<CartesianArrayHandle>())
if (coordData.CanConvert<CartesianArrayHandle>())
{
const auto vertices = coordData.AsArrayHandle<CartesianArrayHandle>();
const auto vertsSize = vertices.GetNumberOfValues();

@ -428,14 +428,7 @@ public:
{
// Get a cast to a concrete set of point coordiantes so that it can be modified in place
vtkm::cont::ArrayHandle<vtkm::Vec3f> concretePoints;
if (points.template IsType<decltype(concretePoints)>())
{
points.AsArrayHandle(concretePoints);
}
else
{
vtkm::cont::ArrayCopy(points, concretePoints);
}
vtkm::cont::ArrayCopyShallowIfPossible(points, concretePoints);
Run(delta, fastCheck, bounds, concretePoints);
@ -450,14 +443,7 @@ public:
{
// Get a cast to a concrete set of point coordiantes so that it can be modified in place
vtkm::cont::ArrayHandle<vtkm::Vec3f> concretePoints;
if (points.template IsType<decltype(concretePoints)>())
{
points.AsArrayHandle(concretePoints);
}
else
{
vtkm::cont::ArrayCopy(points, concretePoints);
}
vtkm::cont::ArrayCopyShallowIfPossible(points, concretePoints);
Run(delta, fastCheck, bounds, concretePoints);

@ -15,6 +15,7 @@
#include <vtkm/CellClassification.h>
#include <vtkm/Types.h>
#include <vtkm/VectorAnalysis.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/CellLocatorGeneral.h>
#include <vtkm/cont/CellLocatorRectilinearGrid.h>
@ -177,10 +178,7 @@ public:
if (dataSet.HasCellField("vtkmGhostCells"))
{
auto arr = dataSet.GetCellField("vtkmGhostCells").GetData();
if (arr.IsType<GhostCellArrayType>())
this->GhostCellArray = arr.AsArrayHandle<GhostCellArrayType>();
else
throw vtkm::cont::ErrorInternal("vtkmGhostCells not of type vtkm::UInt8");
vtkm::cont::ArrayCopyShallowIfPossible(arr, this->GhostCellArray);
}
}