Use variable Vec-like objects for topology map fetching

This change removes the requirement to specify some maximum cell length
in each of the worklets, which is basically impossible. It also makes
some of the loading more lazy, which might help reduce the number of
registers required in a worklet.
This commit is contained in:
Kenneth Moreland 2015-08-14 09:06:11 -06:00
parent 891979e3fa
commit f7a6946d9a
6 changed files with 117 additions and 134 deletions

@ -22,11 +22,8 @@
#include <vtkm/exec/arg/AspectTagDefault.h>
#include <vtkm/exec/arg/Fetch.h>
#include <vtkm/exec/TopologyData.h>
VTKM_THIRDPARTY_PRE_INCLUDE
#include <boost/type_traits.hpp>
VTKM_THIRDPARTY_POST_INCLUDE
#include <vtkm/exec/internal/VecFromPortalPermute.h>
namespace vtkm {
namespace exec {
@ -40,6 +37,40 @@ namespace arg {
///
struct FetchTagArrayTopologyMapIn { };
namespace detail {
// This internal class defines how a TopologyMapIn fetch loads from field data
// based on the connectivity class and the object holding the field data. The
// default implementation gets a Vec of indices and an array portal for the
// field and delivers a VecFromPortalPermute. Specializations could have more
// efficient implementations. For example, if the connectivity is structured
// and the field is regular point coordinates, it is much faster to compute the
// field directly.
template<typename ConnectivityType, typename FieldExecObjectType>
struct FetchArrayTopologyMapInImplementation
{
// The connectivity classes are expected to have an IndicesType that is
// is Vec-like class that will be returned from a GetIndices method.
typedef typename ConnectivityType::IndicesType IndexVecType;
// The FieldExecObjectType is expected to behave like an ArrayPortal.
typedef FieldExecObjectType PortalType;
typedef vtkm::exec::internal::VecFromPortalPermute<
IndexVecType,PortalType> ValueType;
VTKM_EXEC_EXPORT
static ValueType Load(vtkm::Id index,
const ConnectivityType &connectivity,
const FieldExecObjectType &field)
{
return ValueType(connectivity.GetIndices(index), field);
}
};
} // namespace detail
template<typename Invocation, vtkm::IdComponent ParameterIndex>
struct Fetch<
vtkm::exec::arg::FetchTagArrayTopologyMapIn,
@ -47,44 +78,37 @@ struct Fetch<
Invocation,
ParameterIndex>
{
// The parameter for the input domain is stored in the Invocation. (It is
// also in the worklet, but it is safer to get it from the Invocation
// in case some other dispatch operation had to modify it.)
static const vtkm::IdComponent InputDomainIndex =
Invocation::InputDomainIndex;
typedef typename Invocation::ControlInterface::template
ParameterType<InputDomainIndex>::type ControlSignatureTag;
static const vtkm::IdComponent ITEM_TUPLE_LENGTH =
ControlSignatureTag::ITEM_TUPLE_LENGTH;
// Assuming that this fetch is used in a topology map, which is its
// intention, InputDomainIndex points to a connectivity object. Thus,
// ConnectivityType is one of the vtkm::exec::Connectivity* classes.
typedef typename Invocation::ParameterInterface::
template ParameterType<InputDomainIndex>::type ConnectivityType;
// The execution object associated with this parameter is expected to be
// an array portal containing the field values.
typedef typename Invocation::ParameterInterface::
template ParameterType<ParameterIndex>::type ExecObjectType;
typedef boost::remove_const<typename ExecObjectType::ValueType> NonConstType;
typedef vtkm::exec::TopologyData<typename NonConstType::type,
ITEM_TUPLE_LENGTH> ValueType;
typedef detail::FetchArrayTopologyMapInImplementation<
ConnectivityType,ExecObjectType> Implementation;
typedef typename Implementation::ValueType ValueType;
VTKM_EXEC_EXPORT
ValueType Load(vtkm::Id index, const Invocation &invocation) const
{
typedef typename Invocation::ParameterInterface ParameterInterface;
typedef typename ParameterInterface::
template ParameterType<InputDomainIndex>::type TopologyType;
TopologyType topology =
const ConnectivityType &connectivity =
invocation.Parameters.template GetParameter<InputDomainIndex>();
const ExecObjectType &field =
invocation.Parameters.template GetParameter<ParameterIndex>();
vtkm::IdComponent nids =
static_cast<vtkm::IdComponent>(topology.GetNumberOfIndices(index));
typename TopologyType::IndicesType ids = topology.GetIndices(index);
ValueType v;
for (vtkm::IdComponent i=0; i<nids && i<ITEM_TUPLE_LENGTH; ++i)
{
v[i] = invocation.Parameters.template GetParameter<ParameterIndex>().
Get(ids[i]);
}
return v;
return Implementation::Load(index, connectivity, field);
}
VTKM_EXEC_EXPORT

@ -51,7 +51,7 @@ struct FromCount : vtkm::exec::arg::ExecutionSignatureTagBase
template<typename FetchTag, typename Invocation>
struct Fetch<FetchTag, vtkm::exec::arg::AspectTagFromCount, Invocation, 1>
{
typedef vtkm::Id ValueType;
typedef vtkm::IdComponent ValueType;
VTKM_EXEC_EXPORT
ValueType Load(vtkm::Id index, const Invocation &invocation) const

@ -31,27 +31,26 @@ namespace worklet {
//simple functor that returns the average point value.
class CellAverage : public vtkm::worklet::WorkletMapTopology
{
static const int LEN_IDS = 8;
public:
typedef void ControlSignature(FieldInFrom<Scalar> inPoints,
TopologyIn<LEN_IDS> topology,
TopologyIn topology,
FieldOut<Scalar> outCells);
typedef void ExecutionSignature(_1, FromCount, _3);
typedef _2 InputDomain;
template<typename T1, typename T2>
template<typename PointValueVecType, typename OutType>
VTKM_EXEC_EXPORT
void operator()(const vtkm::exec::TopologyData<T1,LEN_IDS> &pointValues,
const vtkm::Id &count,
T2 &average) const
void operator()(const PointValueVecType &pointValues,
const vtkm::IdComponent &numPoints,
OutType &average) const
{
T1 sum = pointValues[0];
for (vtkm::IdComponent i=1; i< count; ++i)
OutType sum = static_cast<OutType>(pointValues[0]);
for (vtkm::IdComponent pointIndex = 1; pointIndex < numPoints; ++pointIndex)
{
sum += pointValues[i];
sum = sum + static_cast<OutType>(pointValues[pointIndex]);
}
average = static_cast<T2>(sum / static_cast<T1>(count));
average = sum / static_cast<OutType>(numPoints);
}
};

@ -83,15 +83,10 @@ public:
/// \brief A control signature tag for input connectivity.
///
/// This tag takes a template argument that is a type list tag that limits
/// the possible value types in the array.
///
template< vtkm::IdComponent ItemTupleLength>
struct TopologyIn : vtkm::cont::arg::ControlSignatureTagBase {
typedef vtkm::cont::arg::TypeCheckTagTopology TypeCheckTag;
typedef vtkm::cont::arg::TransportTagTopologyIn TransportTag;
typedef vtkm::exec::arg::FetchTagTopologyIn FetchTag;
static const int ITEM_TUPLE_LENGTH = ItemTupleLength;
};
/// \brief A control signature tag for output fields.

@ -21,6 +21,8 @@
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/Math.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/testing/Testing.h>
@ -30,11 +32,10 @@ namespace test_explicit {
class MaxPointOrCellValue : public vtkm::worklet::WorkletMapTopology
{
static const int LEN_IDS = 8;
public:
typedef void ControlSignature(FieldInTo<Scalar> inCells,
FieldInFrom<Scalar> inPoints,
TopologyIn<LEN_IDS> topology,
TopologyIn topology,
FieldOut<Scalar> outCells);
typedef void ExecutionSignature(_1, _4, _2, FromCount, CellShape, FromIndices);
typedef _3 InputDomain;
@ -42,43 +43,33 @@ public:
VTKM_CONT_EXPORT
MaxPointOrCellValue() { }
template<typename T, typename FromIndexType>
template<typename InCellType,
typename OutCellType,
typename InPointVecType,
typename FromIndexType>
VTKM_EXEC_EXPORT
void operator()(const T &cellValue,
T& maxValue,
const vtkm::exec::TopologyData<T,LEN_IDS> &pointValues,
const vtkm::Id &count,
const vtkm::Id & vtkmNotUsed(type),
const FromIndexType& vtkmNotUsed(pointIDs)) const
void operator()(const InCellType &cellValue,
OutCellType &maxValue,
const InPointVecType &pointValues,
const vtkm::IdComponent &numPoints,
const vtkm::Id &vtkmNotUsed(type),
const FromIndexType &vtkmNotUsed(pointIDs)) const
{
//simple functor that returns the max of cellValue and pointValue
maxValue = cellValue;
for (vtkm::IdComponent i=0; i<count; ++i)
//simple functor that returns the max of cellValue and pointValue
maxValue = static_cast<OutCellType>(cellValue);
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; ++pointIndex)
{
maxValue = pointValues[i] > maxValue ? pointValues[i] : maxValue;
maxValue = vtkm::Max(maxValue,
static_cast<OutCellType>(pointValues[pointIndex]));
}
}
template<typename T1, typename T2, typename T3, typename FromIndexType>
VTKM_EXEC_EXPORT
void operator()(const T1 &,
T2 &,
const vtkm::exec::TopologyData<T3,LEN_IDS> &,
const vtkm::Id &,
const vtkm::Id &,
const FromIndexType &) const
{
this->RaiseError("Cannot call this worklet with different types.");
}
};
class AveragePointToCellValue : public vtkm::worklet::WorkletMapTopology
{
static const int LEN_IDS = 8;
public:
typedef void ControlSignature(FieldInFrom<Scalar> inPoints,
TopologyIn<LEN_IDS> topology,
TopologyIn topology,
FieldOut<Scalar> outCells);
typedef void ExecutionSignature(_1, _3, FromCount);
typedef _2 InputDomain;
@ -86,28 +77,20 @@ public:
VTKM_CONT_EXPORT
AveragePointToCellValue() { }
template<typename T>
template<typename PointVecType, typename OutType>
VTKM_EXEC_EXPORT
void operator()(const vtkm::exec::TopologyData<T,LEN_IDS> &pointValues,
T& avgVal,
const vtkm::Id &count) const
void operator()(const PointVecType &pointValues,
OutType &avgVal,
const vtkm::IdComponent &numPoints) const
{
//simple functor that returns the average pointValue.
avgVal = pointValues[0];
for (vtkm::IdComponent i=1; i<count; ++i)
avgVal = static_cast<OutType>(pointValues[0]);
for (vtkm::IdComponent pointIndex = 1; pointIndex < numPoints; ++pointIndex)
{
avgVal += pointValues[i];
avgVal += static_cast<OutType>(pointValues[pointIndex]);
}
avgVal = avgVal / count;
avgVal = avgVal / static_cast<OutType>(numPoints);
}
template<typename T1, typename T2>
VTKM_EXEC_EXPORT
void operator()(const T1 &, T2 &, const vtkm::Id &) const
{
this->RaiseError("Cannot call this worklet with different types.");
}
};
}

@ -21,6 +21,8 @@
#include <vtkm/worklet/DispatcherMapTopology.h>
#include <vtkm/worklet/WorkletMapTopology.h>
#include <vtkm/Math.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/exec/TopologyData.h>
@ -32,56 +34,44 @@ namespace test_regular {
class MaxPointOrCellValue : public vtkm::worklet::WorkletMapTopology
{
static const int LEN_IDS = 4;
public:
typedef void ControlSignature(FieldInTo<Scalar> inCells,
FieldInFrom<Scalar> inPoints,
TopologyIn<LEN_IDS> topology,
TopologyIn topology,
FieldOut<Scalar> outCells);
//Todo: we need a way to mark what control signature item each execution signature for topology comes from
typedef void ExecutionSignature(_1, _4, _2, FromCount, CellShape, FromIndices);
typedef _3 InputDomain;
VTKM_CONT_EXPORT
MaxPointOrCellValue() { }
template<typename T, typename FromIndexType>
template<typename InCellType,
typename OutCellType,
typename InPointVecType,
typename FromIndexType>
VTKM_EXEC_EXPORT
void operator()(const T &cellval,
T& max_value,
const vtkm::exec::TopologyData<T,LEN_IDS> &pointValues,
const vtkm::Id &count,
const vtkm::Id & vtkmNotUsed(type),
const FromIndexType & vtkmNotUsed(pointIDs)) const
void operator()(const InCellType &cellValue,
OutCellType &maxValue,
const InPointVecType &pointValues,
const vtkm::IdComponent &numPoints,
const vtkm::Id &vtkmNotUsed(type),
const FromIndexType &vtkmNotUsed(pointIDs)) const
{
//simple functor that returns the max of cellValue and pointValue
max_value = cellval;
for (vtkm::IdComponent i=0; i< count; ++i)
//simple functor that returns the max of cellValue and pointValue
maxValue = static_cast<OutCellType>(cellValue);
for (vtkm::IdComponent pointIndex = 0; pointIndex < numPoints; ++pointIndex)
{
max_value = pointValues[i] > max_value ? pointValues[i] : max_value;
maxValue = vtkm::Max(maxValue,
static_cast<OutCellType>(pointValues[pointIndex]));
}
}
template<typename T1, typename T2, typename T3, typename FromIndex>
VTKM_EXEC_EXPORT
void operator()(const T1 &,
T2 &,
const vtkm::exec::TopologyData<T3,LEN_IDS> &,
const vtkm::Id &,
const vtkm::Id &,
const FromIndex &) const
{
this->RaiseError("Cannot call this worklet with different types.");
}
};
class AveragePointToCellValue : public vtkm::worklet::WorkletMapTopology
{
static const int LEN_IDS = 4;
public:
typedef void ControlSignature(FieldInFrom<Scalar> inPoints,
TopologyIn<LEN_IDS> topology,
TopologyIn topology,
FieldOut<Scalar> outCells);
typedef void ExecutionSignature(_1, _3, FromCount);
typedef _2 InputDomain;
@ -89,28 +79,20 @@ public:
VTKM_CONT_EXPORT
AveragePointToCellValue() { }
template<typename T>
template<typename PointVecType, typename OutType>
VTKM_EXEC_EXPORT
void operator()(const vtkm::exec::TopologyData<T,LEN_IDS> &pointValues,
T& avgVal,
const vtkm::Id &count) const
void operator()(const PointVecType &pointValues,
OutType &avgVal,
const vtkm::IdComponent &numPoints) const
{
//simple functor that returns the average pointValue.
avgVal = pointValues[0];
for (vtkm::IdComponent i=1; i<count; ++i)
avgVal = static_cast<OutType>(pointValues[0]);
for (vtkm::IdComponent pointIndex = 1; pointIndex < numPoints; ++pointIndex)
{
avgVal += pointValues[i];
avgVal += static_cast<OutType>(pointValues[pointIndex]);
}
avgVal = avgVal / count;
avgVal = avgVal / static_cast<OutType>(numPoints);
}
template<typename T1, typename T2>
VTKM_EXEC_EXPORT
void operator()(const T1 &, T2 &, const vtkm::Id &) const
{
this->RaiseError("Cannot call this worklet with different types.");
}
};
}