ConvertNumComponentsToOffsets using ScanExtented vs. ScanExclusive

This commit also:
- Removes a corner case not longer used at ArrayPortalGroupVecVariable::get
- Changes doc regarding the number of offset elements in the input
  array handler of ConvertNumComponentsToOffsets.
- Updates invokation of make_ArrayGroupVectVariable in multiple files
- Adds its corresponding changelog entry
This commit is contained in:
Vicente Adolfo Bolea Sanchez 2020-03-05 10:56:28 -05:00
parent fd9c21c0d4
commit 9d0da855b3
11 changed files with 66 additions and 58 deletions

@ -0,0 +1,24 @@
# `ArrayHandleGroupVecVariable` holds now one more offset.
This change affects the usage of both `ConvertNumComponentsToOffsets` and
`make_ArrayHandleGroupVecVariable`.
The reason of this change is to remove a branch in
`ArrayHandleGroupVecVariable::Get` which is used to avoid an array overflow,
this in theory would increases the performance since at the CPU level it will
remove penalties due to wrong branch predictions.
The change affects `ConvertNumComponentsToOffsets` by both:
1. Increasing the numbers of elements in `offsetsArray` (its second parameter)
by one.
2. Setting `sourceArraySize` as the sum of all the elements plus the new one
in `offsetsArray`
Note that not every specialization of `ConvertNumComponentsToOffsets` does
return `offsetsArray`. Thus, some of them would not be affected.
Similarly, this change affects `make_ArrayHandleGroupVecVariable` since it
expects its second parameter (offsetsArray) to be one element bigger than
before.

@ -11,6 +11,7 @@
#define vtk_m_cont_ArrayHandleGroupVecVariable_h
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValues.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCast.h>
#include <vtkm/cont/ArrayPortal.h>
@ -69,22 +70,14 @@ public:
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return this->OffsetsPortal.GetNumberOfValues(); }
vtkm::Id GetNumberOfValues() const { return this->OffsetsPortal.GetNumberOfValues() - 1; }
VTKM_SUPPRESS_EXEC_WARNINGS
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const
{
vtkm::Id offsetIndex = this->OffsetsPortal.Get(index);
vtkm::Id nextOffsetIndex;
if (index + 1 < this->GetNumberOfValues())
{
nextOffsetIndex = this->OffsetsPortal.Get(index + 1);
}
else
{
nextOffsetIndex = this->SourcePortal.GetNumberOfValues();
}
vtkm::Id nextOffsetIndex = this->OffsetsPortal.Get(index + 1);
return ValueType(this->SourcePortal,
static_cast<vtkm::IdComponent>(nextOffsetIndex - offsetIndex),
@ -221,7 +214,7 @@ public:
vtkm::Id GetNumberOfValues() const
{
VTKM_ASSERT(this->Valid);
return this->OffsetsArray.GetNumberOfValues();
return this->OffsetsArray.GetNumberOfValues() - 1;
}
VTKM_CONT
@ -234,7 +227,7 @@ public:
void Shrink(vtkm::Id numberOfValues)
{
VTKM_ASSERT(this->Valid);
this->OffsetsArray.Shrink(numberOfValues);
this->OffsetsArray.Shrink(numberOfValues + 1);
}
VTKM_CONT
@ -307,7 +300,7 @@ public:
}
VTKM_CONT
vtkm::Id GetNumberOfValues() const { return this->OffsetsArray.GetNumberOfValues(); }
vtkm::Id GetNumberOfValues() const { return this->OffsetsArray.GetNumberOfValues() - 1; }
VTKM_CONT
PortalConstExecution PrepareForInput(bool vtkmNotUsed(updateData), vtkm::cont::Token& token)
@ -327,7 +320,7 @@ public:
PortalExecution PrepareForOutput(vtkm::Id numberOfValues, vtkm::cont::Token& token)
{
// Cannot reallocate an ArrayHandleGroupVecVariable
VTKM_ASSERT(numberOfValues == this->OffsetsArray.GetNumberOfValues());
VTKM_ASSERT(numberOfValues == this->OffsetsArray.GetNumberOfValues() - 1);
return PortalExecution(
this->SourceArray.PrepareForOutput(this->SourceArray.GetNumberOfValues(), Device(), token),
this->OffsetsArray.PrepareForInput(Device(), token));
@ -371,7 +364,7 @@ private:
/// value contains values from the last offset to the end of the array.
///
/// For example, if you have an array handle with the 9 values
/// 0,1,2,3,4,5,6,7,8 an offsets array handle with the 3 values 0,4,6 and give
/// 0,1,2,3,4,5,6,7,8 an offsets array handle with the 4 values 0,4,6,9 and give
/// them to an \c ArrayHandleGroupVecVariable, you get an array that looks like
/// it contains three values of Vec-like objects with the data [0,1,2,3],
/// [4,5], and [6,7,8].
@ -463,10 +456,12 @@ VTKM_CONT void ConvertNumComponentsToOffsets(
vtkm::Id& sourceArraySize,
vtkm::cont::DeviceAdapterId device = vtkm::cont::DeviceAdapterTagAny())
{
using namespace vtkm::cont;
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
sourceArraySize = vtkm::cont::Algorithm::ScanExclusive(
device, vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
Algorithm::ScanExtended(device, make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
sourceArraySize = ArrayGetValue(offsetsArray.GetNumberOfValues() - 1, offsetsArray);
}
template <typename NumComponentsArrayType, typename OffsetsStorage>
@ -477,8 +472,8 @@ VTKM_CONT void ConvertNumComponentsToOffsets(
{
VTKM_IS_ARRAY_HANDLE(NumComponentsArrayType);
vtkm::Id dummy;
vtkm::cont::ConvertNumComponentsToOffsets(numComponentsArray, offsetsArray, dummy, device);
vtkm::cont::Algorithm::ScanExtended(
device, vtkm::cont::make_ArrayHandleCast<vtkm::Id>(numComponentsArray), offsetsArray);
}
template <typename NumComponentsArrayType>

@ -104,9 +104,7 @@ public:
{
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
connectivity.Allocate(connectivityLength);
const auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
auto connWrap = vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsetsTrim);
auto connWrap = vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsets);
vtkm::cont::Invoker{ Device{} }(WriteConnectivity{}, cs, connWrap);
return connectivity;
}

@ -51,13 +51,10 @@ inline VTKM_CONT vtkm::cont::DataSet CleanGrid::DoExecute(const vtkm::cont::Data
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
connectivity.Allocate(connectivitySize);
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
this->Invoke(worklet::CellDeepCopy::PassCellStructure{},
deducedCellSet,
shapes,
vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsetsTrim));
vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsets));
shapes.ReleaseResourcesExecution();
offsets.ReleaseResourcesExecution();
connectivity.ReleaseResourcesExecution();

@ -83,12 +83,9 @@ struct CellDeepCopy
vtkm::cont::ConvertNumIndicesToOffsets(numIndices, offsets, connectivitySize);
connectivity.Allocate(connectivitySize);
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
vtkm::worklet::DispatcherMapTopology<PassCellStructure> passDispatcher;
passDispatcher.Invoke(
inCellSet, shapes, vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsetsTrim));
inCellSet, shapes, vtkm::cont::make_ArrayHandleGroupVecVariable(connectivity, offsets));
vtkm::cont::CellSetExplicit<ShapeStorage, ConnectivityStorage, OffsetsStorage> newCellSet;
newCellSet.Fill(inCellSet.GetNumberOfPoints(), shapes, connectivity, offsets);

@ -806,13 +806,10 @@ public:
polyDataConnectivity.Allocate(polyDataConnectivitySize);
auto pdOffsetsTrim = vtkm::cont::make_ArrayHandleView(
polyDataOffsets, 0, polyDataOffsets.GetNumberOfValues() - 1);
passPolyDataCellsDispatcher.Invoke(
inCellSet,
polyDataShapes,
vtkm::cont::make_ArrayHandleGroupVecVariable(polyDataConnectivity, pdOffsetsTrim),
vtkm::cont::make_ArrayHandleGroupVecVariable(polyDataConnectivity, polyDataOffsets),
polyDataCellIdMap);
}
}
@ -884,7 +881,7 @@ public:
originCells,
originFaces,
faceShapes,
vtkm::cont::make_ArrayHandleGroupVecVariable(faceConnectivity, faceOffsetsTrim),
vtkm::cont::make_ArrayHandleGroupVecVariable(faceConnectivity, faceOffsets),
faceToCellIdMap);
if (!polyDataConnectivitySize)

@ -95,10 +95,11 @@ VTKM_CONT void Keys<T>::BuildArraysInternal(KeyArrayType& keys, vtkm::cont::Devi
vtkm::Sum());
// Get the offsets from the counts with a scan.
vtkm::Id offsetsTotal = vtkm::cont::Algorithm::ScanExclusive(
vtkm::cont::Algorithm::ScanExtended(
device, vtkm::cont::make_ArrayHandleCast(this->Counts, vtkm::Id()), this->Offsets);
VTKM_ASSERT(offsetsTotal == numKeys); // Sanity check
(void)offsetsTotal; // Shut up, compiler
VTKM_ASSERT(numKeys ==
vtkm::cont::ArrayGetValue(this->Offsets.GetNumberOfValues() - 1, this->Offsets));
}
template <typename T>
@ -123,10 +124,11 @@ VTKM_CONT void Keys<T>::BuildArraysInternalStable(const KeyArrayType& keys,
vtkm::Sum());
// Get the offsets from the counts with a scan.
vtkm::Id offsetsTotal = vtkm::cont::Algorithm::ScanExclusive(
vtkm::cont::make_ArrayHandleCast(this->Counts, vtkm::Id()), this->Offsets);
VTKM_ASSERT(offsetsTotal == numKeys); // Sanity check
(void)offsetsTotal; // Shut up, compiler
vtkm::cont::Algorithm::ScanExtended(
device, vtkm::cont::make_ArrayHandleCast(this->Counts, vtkm::Id()), this->Offsets);
VTKM_ASSERT(numKeys ==
vtkm::cont::ArrayGetValue(this->Offsets.GetNumberOfValues() - 1, this->Offsets));
}
}
}

@ -245,9 +245,7 @@ public:
conn.Allocate(connSize);
// Trim the last value off for the group vec array:
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
auto connGroupVec = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
WorkletWindToCellNormalsGeneric worklet;
invoker(worklet, cellSet, coords, cellNormals, connGroupVec);
@ -291,9 +289,7 @@ public:
const auto& offsets =
cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
WindToCellNormals dispatcher;
dispatcher.Invoke(cellNormals, cells, coords);
@ -337,9 +333,7 @@ public:
const auto& offsets =
cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
auto cells = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
WindToCellNormals dispatcher;
dispatcher.Invoke(cellNormals, cells, coords);

@ -122,8 +122,9 @@ vtkm::cont::ArrayHandle<T> copyFromVec(vtkm::cont::ArrayHandle<vtkm::Vec<T, N>>
struct VertexClustering
{
using PointIdMapType = vtkm::cont::ArrayHandlePermutation<vtkm::cont::ArrayHandle<vtkm::Id>,
vtkm::cont::ArrayHandle<vtkm::Id>>;
using PointIdMapType = vtkm::cont::ArrayHandlePermutation<
vtkm::cont::ArrayHandleView<vtkm::cont::ArrayHandle<vtkm::Id>>,
vtkm::cont::ArrayHandle<vtkm::Id>>;
struct GridInfo
{
@ -375,10 +376,15 @@ public:
vtkm::worklet::Keys<vtkm::Id> keys;
keys.BuildArrays(pointCidArray, vtkm::worklet::KeysSortType::Stable);
// Create a View with all the keys offsets but the last element since
// BuildArrays uses ScanExtended
auto keysView = vtkm::cont::make_ArrayHandleView(
keys.GetOffsets(), 0, keys.GetOffsets().GetNumberOfValues() - 1);
// For mapping properties, this map will select an arbitrary point from
// the cluster:
this->PointIdMap =
vtkm::cont::make_ArrayHandlePermutation(keys.GetOffsets(), keys.GetSortedValuesMap());
vtkm::cont::make_ArrayHandlePermutation(keysView, keys.GetSortedValuesMap());
// Compute representative points from each cluster (may not match the
// PointIdMap indexing)

@ -31,7 +31,7 @@ void CheckKeyReduce(const KeyPortal& originalKeys,
vtkm::Id originalSize = originalKeys.GetNumberOfValues();
vtkm::Id uniqueSize = uniqueKeys.GetNumberOfValues();
VTKM_TEST_ASSERT(originalSize == sortedValuesMap.GetNumberOfValues(), "Inconsistent array size.");
VTKM_TEST_ASSERT(uniqueSize == offsets.GetNumberOfValues(), "Inconsistent array size.");
VTKM_TEST_ASSERT(uniqueSize == offsets.GetNumberOfValues() - 1, "Inconsistent array size.");
VTKM_TEST_ASSERT(uniqueSize == counts.GetNumberOfValues(), "Inconsistent array size.");
for (vtkm::Id uniqueIndex = 0; uniqueIndex < uniqueSize; uniqueIndex++)

@ -58,9 +58,7 @@ void Validate(vtkm::cont::DataSet dataSet)
cellSet.GetConnectivityArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
const auto offsets =
cellSet.GetOffsetsArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{});
const auto offsetsTrim =
vtkm::cont::make_ArrayHandleView(offsets, 0, offsets.GetNumberOfValues() - 1);
const auto cellArray = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsetsTrim);
const auto cellArray = vtkm::cont::make_ArrayHandleGroupVecVariable(conn, offsets);
const auto cellNormalsVar = dataSet.GetCellField("normals").GetData();
const auto cellNormalsArray = cellNormalsVar.Cast<vtkm::cont::ArrayHandle<MyNormalT>>();