Merge branch 'try-run-on-device' into 'master'

Add general purpose TryExecute

The filters directory had a couple of classes designed to try executing
filters on a list of devices until one succeeds. There was quite a bit
of code duplication in these, and the code was inaccessible to other
parts of VTK-m. This resolves both of these issues by moving the
functionality to a TryExecute method located in the vtkm::cont
package.

See merge request !507
This commit is contained in:
Kenneth Moreland 2016-08-18 15:05:03 -04:00
commit 069fc69869
18 changed files with 568 additions and 470 deletions

@ -131,14 +131,14 @@ public:
typedef typename vtkm::VecTraits<FieldInType>::ComponentType FieldType;
const FieldType iso = static_cast<FieldType>(this->IsoValue);
caseNumber= ((fieldIn[0] > this->IsoValue) |
(fieldIn[1] > this->IsoValue) << 1 |
(fieldIn[2] > this->IsoValue) << 2 |
(fieldIn[3] > this->IsoValue) << 3 |
(fieldIn[4] > this->IsoValue) << 4 |
(fieldIn[5] > this->IsoValue) << 5 |
(fieldIn[6] > this->IsoValue) << 6 |
(fieldIn[7] > this->IsoValue) << 7);
caseNumber= ((fieldIn[0] > iso) |
(fieldIn[1] > iso) << 1 |
(fieldIn[2] > iso) << 2 |
(fieldIn[3] > iso) << 3 |
(fieldIn[4] > iso) << 4 |
(fieldIn[5] > iso) << 5 |
(fieldIn[6] > iso) << 6 |
(fieldIn[7] > iso) << 7);
}
};
@ -386,4 +386,4 @@ int main(int argc, char *argv[])
//now actually execute the benchmarks
return vtkm::benchmarking::BenchmarkTopologyAlgorithms
<VTKM_DEFAULT_DEVICE_ADAPTER_TAG>::Run(benchmarks);
}
}

@ -50,6 +50,7 @@ set(headers
DataSetFieldAdd.h
DeviceAdapter.h
DeviceAdapterAlgorithm.h
DeviceAdapterListTag.h
DeviceAdapterSerial.h
DynamicArrayHandle.h
DynamicCellSet.h
@ -68,6 +69,7 @@ set(headers
StorageImplicit.h
StorageListTag.h
Timer.h
TryExecute.h
)
#-----------------------------------------------------------------------------

@ -0,0 +1,46 @@
//============================================================================
// 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.
//
// Copyright 2016 Sandia Corporation.
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_DeviceAdapterListTag_h
#define vtk_m_cont_DeviceAdapterListTag_h
#ifndef VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG
#define VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG \
::vtkm::cont::DeviceAdapterListTagCommon
#endif
#include <vtkm/ListTag.h>
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>
namespace vtkm {
namespace cont {
struct DeviceAdapterListTagCommon
: vtkm::ListTagBase<
vtkm::cont::DeviceAdapterTagCuda,
vtkm::cont::DeviceAdapterTagTBB,
vtkm::cont::DeviceAdapterTagSerial> { };
}
} // namespace vtkm::cont
#endif //vtk_m_cont_DeviceAdapterListTag_h

208
vtkm/cont/TryExecute.h Normal file

@ -0,0 +1,208 @@
//============================================================================
// 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.
//
// Copyright 2016 Sandia Corporation.
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_cont_TryExecute_h
#define vtk_m_cont_TryExecute_h
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ErrorControlBadAllocation.h>
#include <vtkm/cont/ErrorControlBadType.h>
#include <vtkm/cont/ErrorControlBadValue.h>
#include <vtkm/cont/internal/RuntimeDeviceTracker.h>
namespace vtkm {
namespace cont {
namespace detail {
template<typename Functor, typename Device, bool DeviceAdapterValid>
struct TryExecuteRunIfValid;
template<typename Functor, typename Device>
struct TryExecuteRunIfValid<Functor, Device, false>
{
VTKM_CONT_EXPORT
static bool Run(Functor &, vtkm::cont::internal::RuntimeDeviceTracker &) {
return false;
}
};
template<typename Functor, typename Device>
struct TryExecuteRunIfValid<Functor, Device, true>
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
VTKM_CONT_EXPORT
static bool Run(Functor &functor,
vtkm::cont::internal::RuntimeDeviceTracker &tracker)
{
if (tracker.CanRunOn(Device()))
{
try
{
return functor(Device());
}
catch(vtkm::cont::ErrorControlBadAllocation e)
{
std::cerr << "caught ErrorControlBadAllocation " << e.GetMessage() << std::endl;
//currently we only consider OOM errors worth disabling a device for
//than we fallback to another device
tracker.ReportAllocationFailure(Device(), e);
}
catch(vtkm::cont::ErrorControlBadType e)
{
//should bad type errors should stop the execution, instead of
//deferring to another device adapter?
std::cerr << "caught ErrorControlBadType : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::ErrorControlBadValue e)
{
//should bad value errors should stop the filter, instead of deferring
//to another device adapter?
std::cerr << "caught ErrorControlBadValue : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::Error e)
{
//general errors should be caught and let us try the next device adapter.
std::cerr << "exception is: " << e.GetMessage() << std::endl;
}
catch (std::exception e)
{
std::cerr << "caught standard exception: " << e.what() << std::endl;
}
catch (...)
{
std::cerr << "unknown exception caught" << std::endl;
}
}
// If we are here, then the functor was either never run or failed.
return false;
}
};
template<typename FunctorType>
struct TryExecuteImpl
{
// Warning, these are a references. Make sure referenced objects do not go
// out of scope.
FunctorType &Functor;
vtkm::cont::internal::RuntimeDeviceTracker &Tracker;
bool Success;
VTKM_CONT_EXPORT
TryExecuteImpl(FunctorType &functor,
vtkm::cont::internal::RuntimeDeviceTracker &tracker)
: Functor(functor), Tracker(tracker), Success(false) { }
template<typename Device>
VTKM_CONT_EXPORT
bool operator()(Device)
{
if (!this->Success)
{
typedef vtkm::cont::DeviceAdapterTraits<Device> DeviceTraits;
this->Success =
detail::TryExecuteRunIfValid<FunctorType,Device,DeviceTraits::Valid>
::Run(this->Functor, this->Tracker);
}
return this->Success;
}
};
} // namespace detail
/// \brief Try to execute a functor on a list of devices until one succeeds.
///
/// This function takes a functor and a list of devices. It then tries to run
/// the functor for each device (in the order given in the list) until the
/// execution succeeds.
///
/// The functor parentheses operator should take exactly one argument, which is
/// the \c DeviceAdapterTag to use. The functor should return a \c bool that is
/// \c true if the execution succeeds, \c false if it fails. If an exception is
/// thrown from the functor, then the execution is assumed to have failed.
///
/// This function also optionally takes a \c RuntimeDeviceTracker, which will
/// monitor for certain failures across calls to TryExecute and skip trying
/// devices with a history of failure.
///
/// This function returns \c true if the functor succeeded on a device,
/// \c false otherwise.
///
/// If no device list is specified, then \c VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG
/// is used.
///
template<typename Functor, typename DeviceList>
VTKM_CONT_EXPORT
bool TryExecute(const Functor &functor,
vtkm::cont::internal::RuntimeDeviceTracker &tracker,
DeviceList)
{
detail::TryExecuteImpl<const Functor> internals(functor, tracker);
vtkm::ListForEach(internals, DeviceList());
return internals.Success;
}
template<typename Functor, typename DeviceList>
VTKM_CONT_EXPORT
bool TryExecute(Functor &functor,
vtkm::cont::internal::RuntimeDeviceTracker &tracker,
DeviceList)
{
detail::TryExecuteImpl<Functor> internals(functor, tracker);
vtkm::ListForEach(internals, DeviceList());
return internals.Success;
}
template<typename Functor, typename DeviceList>
VTKM_CONT_EXPORT
bool TryExecute(const Functor &functor, DeviceList)
{
vtkm::cont::internal::RuntimeDeviceTracker tracker;
return vtkm::cont::TryExecute(functor, tracker, DeviceList());
}
template<typename Functor, typename DeviceList>
VTKM_CONT_EXPORT
bool TryExecute(Functor &functor, DeviceList)
{
vtkm::cont::internal::RuntimeDeviceTracker tracker;
return vtkm::cont::TryExecute(functor, tracker, DeviceList());
}
template<typename Functor>
VTKM_CONT_EXPORT
bool TryExecute(const Functor &functor)
{
return vtkm::cont::TryExecute(functor,
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
}
template<typename Functor>
VTKM_CONT_EXPORT
bool TryExecute(Functor &functor)
{
return vtkm::cont::TryExecute(functor,
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
}
}
} // namespace vtkm::cont
#endif //vtk_m_cont_TryExecute_h

@ -36,6 +36,7 @@ set(headers
FunctorsGeneral.h
IteratorFromArrayPortal.h
PointCoordinatesBase.h
RuntimeDeviceTracker.h
SimplePolymorphicContainer.h
StorageError.h
)

@ -27,6 +27,6 @@
/// point, you have to specify an appropriate DeviceAdapter or else get a
/// compile error.
///
VTKM_VALID_DEVICE_ADAPTER(Error, VTKM_DEVICE_ADAPTER_ERROR);
VTKM_INVALID_DEVICE_ADAPTER(Error, VTKM_DEVICE_ADAPTER_ERROR);
#endif //vtk_m_cont_internal_DeviceAdapterError_h

@ -17,8 +17,8 @@
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_filter_internal_RuntimeDeviceTracker_h
#define vtk_m_filter_internal_RuntimeDeviceTracker_h
#ifndef vtk_m_cont_internal_RuntimeDeviceTracker_h
#define vtk_m_cont_internal_RuntimeDeviceTracker_h
#include <vtkm/cont/ErrorControlBadAllocation.h>
#include <vtkm/cont/RuntimeDeviceInformation.h>
@ -31,7 +31,7 @@
#include <cstring>
namespace vtkm {
namespace filter {
namespace cont {
namespace internal {
/// A class that can be used to determine if a given device adapter
@ -54,6 +54,7 @@ public:
/// machine.
///
template<typename DeviceAdapterTag>
VTKM_CONT_EXPORT
bool CanRunOn(DeviceAdapterTag) const
{
typedef vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag> Traits;
@ -64,6 +65,7 @@ public:
///as being unusable for all future invocations of the instance of the filter.
///
template<typename DeviceAdapterTag>
VTKM_CONT_EXPORT
void ReportAllocationFailure(DeviceAdapterTag,
const vtkm::cont::ErrorControlBadAllocation&)
{
@ -74,6 +76,7 @@ public:
///Reset the tracker to its default state.
/// Will discard any updates caused by reported failures.
///
VTKM_CONT_EXPORT
void Reset()
{
std::memset(this->RuntimeValid, 0, sizeof(bool)*8 );
@ -115,6 +118,6 @@ private:
}
}
} // namespace vtkm::filter::internal
} // namespace vtkm::cont::internal
#endif //vtk_m_filter_internal_RuntimeDeviceTracker_h

@ -64,6 +64,7 @@ set(unit_tests
UnitTestStorageImplicit.cxx
UnitTestStorageListTag.cxx
UnitTestTimer.cxx
UnitTestTryExecute.cxx
)
vtkm_unit_tests(SOURCES ${unit_tests})

@ -0,0 +1,110 @@
//============================================================================
// 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.
//
// Copyright 2016 Sandia Corporation.
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#define VTKM_DEVICE_ADAPTER VTKM_DEVICE_ADAPTER_ERROR
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/internal/DeviceAdapterError.h>
#include <vtkm/cont/testing/Testing.h>
namespace {
static const vtkm::Id ARRAY_SIZE = 10;
struct TryExecuteTestFunctor
{
vtkm::IdComponent NumCalls;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> InArray;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> OutArray;
VTKM_CONT_EXPORT
TryExecuteTestFunctor(vtkm::cont::ArrayHandle<vtkm::FloatDefault> inArray,
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray)
: NumCalls(0), InArray(inArray), OutArray(outArray)
{ }
template<typename Device>
VTKM_CONT_EXPORT
bool operator()(Device)
{
typedef vtkm::cont::DeviceAdapterAlgorithm<Device> Algorithm;
Algorithm::Copy(this->InArray, this->OutArray);
this->NumCalls++;
return true;
}
};
template<typename DeviceList>
void TryExecuteWithList(DeviceList, bool expectSuccess)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> inArray;
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outArray;
inArray.Allocate(ARRAY_SIZE);
SetPortal(inArray.GetPortalControl());
TryExecuteTestFunctor functor(inArray, outArray);
bool result = vtkm::cont::TryExecute(functor, DeviceList());
if (expectSuccess)
{
VTKM_TEST_ASSERT(result, "Call returned failure when expected success.");
VTKM_TEST_ASSERT(functor.NumCalls == 1, "Bad number of calls");
CheckPortal(outArray.GetPortalConstControl());
}
else
{
VTKM_TEST_ASSERT(!result, "Call returned true when expected failure.");
}
}
static void Run()
{
typedef vtkm::cont::DeviceAdapterTagSerial ValidDevice;
typedef vtkm::cont::DeviceAdapterTagError InvalidDevice;
std::cout << "Try a list with a single entry." << std::endl;
typedef vtkm::ListTagBase<ValidDevice> SingleValidList;
TryExecuteWithList(SingleValidList(), true);
std::cout << "Try a list with two valid devices." << std::endl;
typedef vtkm::ListTagBase<ValidDevice,ValidDevice> DoubleValidList;
TryExecuteWithList(DoubleValidList(), true);
std::cout << "Try a list with only invalid device." << std::endl;
typedef vtkm::ListTagBase<InvalidDevice> SingleInvalidList;
TryExecuteWithList(SingleInvalidList(), false);
std::cout << "Try a list with an invalid and valid device." << std::endl;
typedef vtkm::ListTagBase<InvalidDevice,ValidDevice> InvalidAndValidList;
TryExecuteWithList(InvalidAndValidList(), true);
}
} // anonymous namespace
int UnitTestTryExecute(int, char*[])
{
return vtkm::cont::testing::Testing::Run(Run);
}

@ -25,10 +25,10 @@
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/internal/RuntimeDeviceTracker.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/ResultDataSet.h>
#include <vtkm/filter/internal/RuntimeDeviceTracker.h>
namespace vtkm {
namespace filter {
@ -90,7 +90,7 @@ private:
std::string OutputFieldName;
vtkm::Id CellSetIndex;
vtkm::Id CoordinateSystemIndex;
vtkm::filter::internal::RuntimeDeviceTracker Tracker;
vtkm::cont::internal::RuntimeDeviceTracker Tracker;
};
}

@ -64,38 +64,48 @@ ResultDataSet FilterDataSet<Derived>::Execute(const vtkm::cont::DataSet &input,
//-----------------------------------------------------------------------------
namespace detail {
template<typename Derived, typename DerivedPolicy>
struct FilterDataSetPrepareForExecutionFunctor
{
vtkm::filter::ResultDataSet Result;
Derived *Self;
const vtkm::cont::DataSet &Input;
const vtkm::filter::PolicyBase<DerivedPolicy> &Policy;
VTKM_CONT_EXPORT
FilterDataSetPrepareForExecutionFunctor(
Derived *self,
const vtkm::cont::DataSet &input,
const vtkm::filter::PolicyBase<DerivedPolicy> &policy)
: Self(self), Input(input), Policy(policy)
{ }
template<typename Device>
VTKM_CONT_EXPORT
bool operator()(Device)
{
this->Result = this->Self->DoExecute(this->Input, this->Policy, Device());
return this->Result.IsValid();
}
};
} // namespace detail
template<typename Derived>
template<typename DerivedPolicy>
ResultDataSet FilterDataSet<Derived>::PrepareForExecution(const vtkm::cont::DataSet &input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy )
ResultDataSet FilterDataSet<Derived>::PrepareForExecution(
const vtkm::cont::DataSet &input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy )
{
typedef vtkm::cont::DeviceAdapterTagCuda CudaTag;
typedef vtkm::cont::DeviceAdapterTagTBB TBBTag;
typedef vtkm::cont::DeviceAdapterTagSerial SerialTag;
// When we move to C++11, this could probably be an anonymous class
detail::FilterDataSetPrepareForExecutionFunctor<Derived, DerivedPolicy>
functor(static_cast<Derived*>(this), input, policy);
ResultDataSet result = run_if_valid<ResultDataSet>( static_cast<Derived*>(this),
input,
policy,
this->Tracker,
CudaTag() );
if( !result.IsValid() )
{
result = run_if_valid<ResultDataSet>( static_cast<Derived*>(this),
input,
policy,
this->Tracker,
TBBTag() );
}
if( !result.IsValid() )
{
result = run_if_valid<ResultDataSet>( static_cast<Derived*>(this),
input,
policy,
this->Tracker,
SerialTag() );
}
vtkm::cont::TryExecute(functor,
this->Tracker,
typename DerivedPolicy::DeviceAdapterList());
return result;
return functor.Result;
}
//-----------------------------------------------------------------------------

@ -25,10 +25,10 @@
#include <vtkm/cont/DynamicCellSet.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/internal/RuntimeDeviceTracker.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/ResultDataSet.h>
#include <vtkm/filter/internal/RuntimeDeviceTracker.h>
namespace vtkm {
namespace filter {
@ -117,7 +117,7 @@ private:
std::string OutputFieldName;
vtkm::Id CellSetIndex;
vtkm::Id CoordinateSystemIndex;
vtkm::filter::internal::RuntimeDeviceTracker Tracker;
vtkm::cont::internal::RuntimeDeviceTracker Tracker;
};
}

@ -24,10 +24,10 @@
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/internal/RuntimeDeviceTracker.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/ResultField.h>
#include <vtkm/filter/internal/RuntimeDeviceTracker.h>
namespace vtkm {
namespace filter {
@ -88,7 +88,7 @@ private:
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
std::string OutputFieldName;
vtkm::filter::internal::RuntimeDeviceTracker Tracker;
vtkm::cont::internal::RuntimeDeviceTracker Tracker;
};
}

@ -23,10 +23,8 @@
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/cont/CellSetListTag.h>
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/StorageListTag.h>
#include <vtkm/cont/DeviceAdapterSerial.h>
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>
#include <vtkm/TypeListTag.h>
namespace vtkm {
@ -46,10 +44,7 @@ public:
typedef VTKM_DEFAULT_COORDINATE_SYSTEM_STORAGE_LIST_TAG CoordinateStorageList;
// List of backends to try in sequence (if one fails, the next is attempted).
typedef vtkm::ListTagBase<
::vtkm::cont::DeviceAdapterTagCuda,
::vtkm::cont::DeviceAdapterTagTBB,
::vtkm::cont::DeviceAdapterTagSerial> DeviceAdapterList;
typedef VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG DeviceAdapterList;
};
}

@ -21,7 +21,6 @@
set(headers
ResolveFieldTypeAndExecute.h
ResolveFieldTypeAndMap.h
RuntimeDeviceTracker.h
)
vtkm_declare_headers(${headers})

@ -6,9 +6,9 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
// Copyright 2016 Sandia Corporation.
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
@ -21,268 +21,83 @@
#define vtk_m_filter_internal_ResolveFieldTypeAndExecute_h
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/internal/RuntimeDeviceTracker.h>
#include <vtkm/filter/FieldMetadata.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/internal/RuntimeDeviceTracker.h>
namespace
{
template<typename ReturnType, bool> struct CanExecute;
template<typename ReturnType,
typename ClassType,
typename ArrayType,
typename DerivedPolicy,
typename DeviceAdapterTag
>
ReturnType run_if_valid(ClassType* c,
const vtkm::cont::DataSet& ds,
const ArrayType &field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
DeviceAdapterTag tag)
{
typedef vtkm::cont::DeviceAdapterTraits<
DeviceAdapterTag> DeviceAdapterTraits;
typedef CanExecute<ReturnType, DeviceAdapterTraits::Valid> CanExecuteType;
return CanExecuteType::Run(c,ds,field,fieldMeta,policy,tracker,tag);
}
template<typename ReturnType,
typename ClassType,
typename DerivedPolicy,
typename DeviceAdapterTag
>
ReturnType run_if_valid(ClassType* c,
const vtkm::cont::DataSet& ds,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
DeviceAdapterTag tag)
{
typedef vtkm::cont::DeviceAdapterTraits<
DeviceAdapterTag> DeviceAdapterTraits;
typedef CanExecute<ReturnType, DeviceAdapterTraits::Valid> CanExecuteType;
return CanExecuteType::Run(c,ds,policy,tracker,tag);
}
//Implementation that we call on device adapters we don't have support
//enabled for
template<typename ReturnType>
struct CanExecute<ReturnType, false>
{
template<typename ClassType,
typename ArrayType,
typename DerivedPolicy,
typename DeviceAdapterTag>
static ReturnType Run(ClassType*,
const vtkm::cont::DataSet &,
const ArrayType &,
const vtkm::filter::FieldMetadata&,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
vtkm::filter::internal::RuntimeDeviceTracker&,
DeviceAdapterTag)
{
return ReturnType();
}
template<typename ClassType,
typename DerivedPolicy,
typename DeviceAdapterTag>
static ReturnType Run(ClassType*,
const vtkm::cont::DataSet &,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
vtkm::filter::internal::RuntimeDeviceTracker&,
DeviceAdapterTag)
{
return ReturnType();
}
};
//Implementation that we call on device adapters we do have support
//enabled for
template<typename ReturnType>
struct CanExecute<ReturnType,true>
{
template<typename ClassType,
typename ArrayType,
typename DerivedPolicy,
typename DeviceAdapterTag>
static ReturnType Run(ClassType* c,
const vtkm::cont::DataSet &input,
const ArrayType &field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
DeviceAdapterTag tag)
{
const bool runtime_usable_device = tracker.CanRunOn(tag);
ReturnType result;
if(runtime_usable_device)
{
try
{
result = c->DoExecute(input,field,fieldMeta,policy,tag);
}
catch(vtkm::cont::ErrorControlBadAllocation e)
{
std::cerr << "caught ErrorControlBadAllocation " << e.GetMessage() << std::endl;
//currently we only consider OOM errors worth disabling a device for
//than we fallback to another device
tracker.ReportAllocationFailure(tag,e);
}
catch(vtkm::cont::ErrorControlBadType e)
{
//bad type errors should stop the filter, instead of deferring to
//another device adapter
std::cerr << "caught ErrorControlBadType : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::ErrorControlBadValue e)
{
//bad value errors should stop the filter, instead of deferring to
//another device adapter
std::cerr << "caught ErrorControlBadValue : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::Error e)
{
//general errors should be caught and let us try the next device adapter.
std::cerr << "exception is: " << e.GetMessage() << std::endl;
}
}
return result;
}
template<typename ClassType,
typename DerivedPolicy,
typename DeviceAdapterTag>
static ReturnType Run(ClassType* c,
const vtkm::cont::DataSet &input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
DeviceAdapterTag tag)
{
const bool runtime_usable_device = tracker.CanRunOn(tag);
ReturnType result;
if(runtime_usable_device)
{
try
{
result = c->DoExecute(input,policy,tag);
}
catch(vtkm::cont::ErrorControlBadAllocation e)
{
std::cerr << "caught ErrorControlBadAllocation " << e.GetMessage() << std::endl;
//currently we only consider OOM errors worth disabling a device for
//than we fallback to another device
tracker.ReportAllocationFailure(tag,e);
}
catch(vtkm::cont::ErrorControlBadType e)
{
//bad type errors should stop the filter, instead of deferring to
//another device adapter
std::cerr << "caught ErrorControlBadType : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::ErrorControlBadValue e)
{
//bad value errors should stop the filter, instead of deferring to
//another device adapter
std::cerr << "caught ErrorControlBadValue : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::Error e)
{
//general errors should be caught and let us try the next device adapter.
std::cerr << "exception is: " << e.GetMessage() << std::endl;
}
}
return result;
}
};
}
namespace vtkm {
namespace filter {
namespace internal {
namespace
template<typename Derived, typename DerivedPolicy, typename ResultType>
struct ResolveFieldTypeAndExecute
{
template<typename Derived, typename DerivedPolicy, typename ResultType>
struct ResolveFieldTypeAndExecute
typedef ResolveFieldTypeAndExecute<Derived, DerivedPolicy, ResultType> Self;
Derived* DerivedClass;
const vtkm::cont::DataSet &InputData;
const vtkm::filter::FieldMetadata& Metadata;
const vtkm::filter::PolicyBase<DerivedPolicy>& Policy;
vtkm::cont::internal::RuntimeDeviceTracker& Tracker;
ResultType& Result;
ResolveFieldTypeAndExecute(
Derived* derivedClass,
const vtkm::cont::DataSet &inputData,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::cont::internal::RuntimeDeviceTracker& tracker,
ResultType& result):
DerivedClass(derivedClass),
InputData(inputData),
Metadata(fieldMeta),
Policy(policy),
Tracker(tracker),
Result(result)
{
typedef ResolveFieldTypeAndExecute<Derived, DerivedPolicy, ResultType> Self;
Derived* DerivedClass;
const vtkm::cont::DataSet &InputData;
const vtkm::filter::FieldMetadata& Metadata;
const vtkm::filter::PolicyBase<DerivedPolicy>& Policy;
vtkm::filter::internal::RuntimeDeviceTracker& Tracker;
ResultType& Result;
}
ResolveFieldTypeAndExecute(Derived* derivedClass,
const vtkm::cont::DataSet &inputData,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
ResultType& result):
DerivedClass(derivedClass),
InputData(inputData),
Metadata(fieldMeta),
Policy(policy),
Tracker(tracker),
Result(result)
{
private:
}
template<typename T, typename StorageTag>
struct ResolveFieldTypeAndExecuteForDevice
{
typedef vtkm::cont::ArrayHandle<T,StorageTag> FieldArrayHandle;
ResolveFieldTypeAndExecuteForDevice(const Self& instance,
const FieldArrayHandle& field) :
Instance(instance), Field(field) {}
private:
const Self& Instance;
const vtkm::cont::ArrayHandle<T,StorageTag>& Field;
template<typename T, typename StorageTag>
struct ResolveFieldTypeAndExecuteForDevice
template <typename DeviceAdapterTag>
bool operator()(DeviceAdapterTag tag) const
{
typedef vtkm::cont::ArrayHandle<T,StorageTag> FieldArrayHandle;
ResolveFieldTypeAndExecuteForDevice(const Self& instance,
const FieldArrayHandle& field) :
Instance(instance), Field(field) {}
const Self& Instance;
const vtkm::cont::ArrayHandle<T,StorageTag>& Field;
template <typename DeviceAdapterTag>
void operator()(DeviceAdapterTag tag) const
{
if( !this->Instance.Result.IsValid() )
{
this->Instance.Result =
run_if_valid<ResultType>( this->Instance.DerivedClass,
this->Instance.InputData,
this->Field,
this->Instance.Metadata,
this->Instance.Policy,
this->Instance.Tracker,
tag );
}
}
};
public:
template<typename T, typename StorageTag>
void operator()(const vtkm::cont::ArrayHandle<T,StorageTag>& field) const
{
ResolveFieldTypeAndExecuteForDevice<T, StorageTag> doResolve(*this,field);
ListForEach(doResolve, typename DerivedPolicy::DeviceAdapterList());
this->Instance.Result =
this->Instance.DerivedClass->DoExecute(this->Instance.InputData,
this->Field,
this->Instance.Metadata,
this->Instance.Policy,
tag );
return this->Instance.Result.IsValid();
}
};
}
public:
template<typename T, typename StorageTag>
void operator()(const vtkm::cont::ArrayHandle<T,StorageTag>& field) const
{
ResolveFieldTypeAndExecuteForDevice<T, StorageTag> doResolve(*this,field);
vtkm::cont::TryExecute(doResolve,
this->Tracker,
typename DerivedPolicy::DeviceAdapterList());
}
};
}
}

@ -6,9 +6,9 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
// Copyright 2016 Sandia Corporation.
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
@ -21,11 +21,12 @@
#define vtk_m_filter_internal_ResolveFieldTypeAndMap_h
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/TryExecute.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/cont/internal/RuntimeDeviceTracker.h>
#include <vtkm/filter/FieldMetadata.h>
#include <vtkm/filter/PolicyBase.h>
#include <vtkm/filter/internal/RuntimeDeviceTracker.h>
//forward declarations needed
namespace vtkm {
@ -34,186 +35,78 @@ namespace filter {
}
}
namespace
{
template<bool> struct CanMap;
template<typename ClassType,
typename ArrayType,
typename DerivedPolicy,
typename DeviceAdapterTag
>
bool map_if_valid(ClassType* c,
vtkm::filter::ResultDataSet& input,
const ArrayType &field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
DeviceAdapterTag tag)
{
typedef vtkm::cont::DeviceAdapterTraits<
DeviceAdapterTag> DeviceAdapterTraits;
typedef CanMap<DeviceAdapterTraits::Valid> CanMapType;
return CanMapType::Run(c,input,field,fieldMeta,policy,tracker,tag);
}
//Implementation that we call on device adapters we don't have support
//enabled for
template<>
struct CanMap<false>
{
template<typename ClassType,
typename ArrayType,
typename DerivedPolicy,
typename DeviceAdapterTag>
static bool Run(ClassType*,
vtkm::filter::ResultDataSet&,
const ArrayType &,
const vtkm::filter::FieldMetadata&,
const vtkm::filter::PolicyBase<DerivedPolicy>&,
vtkm::filter::internal::RuntimeDeviceTracker&,
DeviceAdapterTag)
{
return false;
}
};
//Implementation that we call on device adapters we do have support
//enabled for
template<>
struct CanMap<true>
{
template<typename ClassType,
typename ArrayType,
typename DerivedPolicy,
typename DeviceAdapterTag>
static bool Run(ClassType* c,
vtkm::filter::ResultDataSet& input,
const ArrayType &field,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
DeviceAdapterTag tag)
{
const bool runtime_usable_device = tracker.CanRunOn(tag);
bool valid = false;
if(runtime_usable_device)
{
try
{
valid = c->DoMapField(input,field,fieldMeta,policy,tag);
}
catch(vtkm::cont::ErrorControlBadAllocation e)
{
std::cerr << "caught ErrorControlBadAllocation " << e.GetMessage() << std::endl;
//currently we only consider OOM errors worth disabling a device for
//than we fallback to another device
tracker.ReportAllocationFailure(tag,e);
}
catch(vtkm::cont::ErrorControlBadType e)
{
//bad type errors should stop the filter, instead of deferring to
//another device adapter
std::cerr << "caught ErrorControlBadType : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::ErrorControlBadValue e)
{
//bad value errors should stop the filter, instead of deferring to
//another device adapter
std::cerr << "caught ErrorControlBadValue : " << e.GetMessage() << std::endl;
}
catch(vtkm::cont::Error e)
{
//general errors should be caught and let us try the next device adapter.
std::cerr << "exception is: " << e.GetMessage() << std::endl;
}
}
return valid;
}
};
}
namespace vtkm {
namespace filter {
namespace internal {
namespace
template<typename Derived, typename DerivedPolicy>
struct ResolveFieldTypeAndMap
{
template<typename Derived, typename DerivedPolicy>
struct ResolveFieldTypeAndMap
typedef ResolveFieldTypeAndMap<Derived, DerivedPolicy> Self;
Derived* DerivedClass;
vtkm::filter::ResultDataSet& InputResult;
const vtkm::filter::FieldMetadata& Metadata;
const vtkm::filter::PolicyBase<DerivedPolicy>& Policy;
vtkm::cont::internal::RuntimeDeviceTracker& Tracker;
bool& RanProperly;
ResolveFieldTypeAndMap(Derived* derivedClass,
vtkm::filter::ResultDataSet& inResult,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::cont::internal::RuntimeDeviceTracker& tracker,
bool& ran):
DerivedClass(derivedClass),
InputResult(inResult),
Metadata(fieldMeta),
Policy(policy),
Tracker(tracker),
RanProperly(ran)
{
typedef ResolveFieldTypeAndMap<Derived, DerivedPolicy> Self;
Derived* DerivedClass;
vtkm::filter::ResultDataSet& InputResult;
const vtkm::filter::FieldMetadata& Metadata;
const vtkm::filter::PolicyBase<DerivedPolicy>& Policy;
vtkm::filter::internal::RuntimeDeviceTracker& Tracker;
bool& RanProperly;
}
private:
ResolveFieldTypeAndMap(Derived* derivedClass,
vtkm::filter::ResultDataSet& inResult,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy,
vtkm::filter::internal::RuntimeDeviceTracker& tracker,
bool& ran):
DerivedClass(derivedClass),
InputResult(inResult),
Metadata(fieldMeta),
Policy(policy),
Tracker(tracker),
RanProperly(ran)
{
template<typename T, typename StorageTag>
struct ResolveFieldTypeAndMapForDevice
{
typedef vtkm::cont::ArrayHandle<T,StorageTag> FieldArrayHandle;
ResolveFieldTypeAndMapForDevice(const Self& instance,
const FieldArrayHandle& field) :
Instance(instance), Field(field), Valid(false) {}
}
const Self& Instance;
const vtkm::cont::ArrayHandle<T,StorageTag>& Field;
mutable bool Valid;
private:
template<typename T, typename StorageTag>
struct ResolveFieldTypeAndMapForDevice
template <typename DeviceAdapterTag>
bool operator()(DeviceAdapterTag tag) const
{
typedef vtkm::cont::ArrayHandle<T,StorageTag> FieldArrayHandle;
ResolveFieldTypeAndMapForDevice(const Self& instance,
const FieldArrayHandle& field) :
Instance(instance), Field(field), Valid(false) {}
this->Valid =
this->Instance.DerivedClass->DoMapField(this->Instance.InputResult,
this->Field,
this->Instance.Metadata,
this->Instance.Policy,
tag);
const Self& Instance;
const vtkm::cont::ArrayHandle<T,StorageTag>& Field;
mutable bool Valid;
template <typename DeviceAdapterTag>
void operator()(DeviceAdapterTag tag) const
{
if( !this->Valid )
{
this->Valid = map_if_valid( this->Instance.DerivedClass,
this->Instance.InputResult,
this->Field,
this->Instance.Metadata,
this->Instance.Policy,
this->Instance.Tracker,
tag );
}
}
};
public:
template<typename T, typename StorageTag>
void operator()(const vtkm::cont::ArrayHandle<T,StorageTag>& field) const
{
ResolveFieldTypeAndMapForDevice<T, StorageTag> doResolve(*this,field);
ListForEach(doResolve, typename DerivedPolicy::DeviceAdapterList());
this->RanProperly = doResolve.Valid;
return this->Valid;
}
};
}
public:
template<typename T, typename StorageTag>
void operator()(const vtkm::cont::ArrayHandle<T,StorageTag>& field) const
{
ResolveFieldTypeAndMapForDevice<T, StorageTag> doResolve(*this,field);
vtkm::cont::TryExecute(doResolve,
this->Tracker,
typename DerivedPolicy::DeviceAdapterList());
this->RanProperly = doResolve.Valid;
}
};
}
}

@ -491,4 +491,19 @@ void CheckPortal(const PortalType &portal)
}
}
/// Sets all the values in a given array portal to be the values returned
/// by vtkm::testing::TestValue. The ArrayPortal must be allocated first.
///
template<typename PortalType>
VTKM_CONT_EXPORT
void SetPortal(const PortalType &portal)
{
typedef typename PortalType::ValueType ValueType;
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); index++)
{
portal.Set(index, TestValue(index, ValueType()));
}
}
#endif //vtk_m_testing_Testing_h