2016-08-15 23:15:17 +00:00
|
|
|
//============================================================================
|
|
|
|
// 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>
|
2017-01-09 21:15:32 +00:00
|
|
|
#include <vtkm/cont/ErrorBadAllocation.h>
|
|
|
|
#include <vtkm/cont/ErrorBadType.h>
|
|
|
|
#include <vtkm/cont/ErrorBadValue.h>
|
2016-08-17 20:13:51 +00:00
|
|
|
|
2017-02-22 20:33:52 +00:00
|
|
|
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
2016-08-15 23:15:17 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace cont
|
|
|
|
{
|
2016-08-15 23:15:17 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace detail
|
|
|
|
{
|
2016-08-15 23:15:17 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor, typename Device, bool DeviceAdapterValid>
|
2016-08-15 23:15:17 +00:00
|
|
|
struct TryExecuteRunIfValid;
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor, typename Device>
|
2016-08-15 23:15:17 +00:00
|
|
|
struct TryExecuteRunIfValid<Functor, Device, false>
|
|
|
|
{
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_CONT
|
2017-05-18 14:29:41 +00:00
|
|
|
static bool Run(Functor&, const vtkm::cont::RuntimeDeviceTracker&) { return false; }
|
2016-08-15 23:15:17 +00:00
|
|
|
};
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor, typename Device>
|
2016-08-17 21:51:43 +00:00
|
|
|
struct TryExecuteRunIfValid<Functor, Device, true>
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
|
|
|
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
|
|
|
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_CONT
|
2017-05-18 14:29:41 +00:00
|
|
|
static bool Run(Functor& functor, vtkm::cont::RuntimeDeviceTracker tracker)
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
2016-08-17 20:13:51 +00:00
|
|
|
if (tracker.CanRunOn(Device()))
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
2016-08-17 20:13:51 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
return functor(Device());
|
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
catch (vtkm::cont::ErrorBadAllocation& e)
|
2016-08-17 20:13:51 +00:00
|
|
|
{
|
2017-01-09 21:15:32 +00:00
|
|
|
std::cerr << "caught ErrorBadAllocation " << e.GetMessage() << std::endl;
|
2016-08-17 20:13:51 +00:00
|
|
|
//currently we only consider OOM errors worth disabling a device for
|
|
|
|
//than we fallback to another device
|
|
|
|
tracker.ReportAllocationFailure(Device(), e);
|
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
catch (vtkm::cont::ErrorBadType& e)
|
2016-08-17 20:13:51 +00:00
|
|
|
{
|
|
|
|
//should bad type errors should stop the execution, instead of
|
|
|
|
//deferring to another device adapter?
|
2017-01-09 21:15:32 +00:00
|
|
|
std::cerr << "caught ErrorBadType : " << e.GetMessage() << std::endl;
|
2016-08-17 20:13:51 +00:00
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
catch (vtkm::cont::ErrorBadValue& e)
|
2016-08-17 20:13:51 +00:00
|
|
|
{
|
|
|
|
//should bad value errors should stop the filter, instead of deferring
|
|
|
|
//to another device adapter?
|
2017-01-09 21:15:32 +00:00
|
|
|
std::cerr << "caught ErrorBadValue : " << e.GetMessage() << std::endl;
|
2016-08-17 20:13:51 +00:00
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
catch (vtkm::cont::Error& e)
|
2016-08-17 20:13:51 +00:00
|
|
|
{
|
|
|
|
//general errors should be caught and let us try the next device adapter.
|
|
|
|
std::cerr << "exception is: " << e.GetMessage() << std::endl;
|
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
catch (std::exception& e)
|
2016-08-17 20:13:51 +00:00
|
|
|
{
|
|
|
|
std::cerr << "caught standard exception: " << e.what() << std::endl;
|
|
|
|
}
|
|
|
|
catch (...)
|
|
|
|
{
|
|
|
|
std::cerr << "unknown exception caught" << std::endl;
|
|
|
|
}
|
2016-08-15 23:15:17 +00:00
|
|
|
}
|
2016-08-17 20:13:51 +00:00
|
|
|
|
|
|
|
// If we are here, then the functor was either never run or failed.
|
|
|
|
return false;
|
2016-08-15 23:15:17 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename FunctorType>
|
2016-08-15 23:15:17 +00:00
|
|
|
struct TryExecuteImpl
|
|
|
|
{
|
2016-08-17 20:13:51 +00:00
|
|
|
// Warning, these are a references. Make sure referenced objects do not go
|
|
|
|
// out of scope.
|
2017-05-18 14:29:41 +00:00
|
|
|
FunctorType& Functor;
|
2017-02-23 16:54:41 +00:00
|
|
|
vtkm::cont::RuntimeDeviceTracker Tracker;
|
2016-08-15 23:15:17 +00:00
|
|
|
|
|
|
|
bool Success;
|
|
|
|
|
2016-10-19 22:42:58 +00:00
|
|
|
VTKM_CONT
|
2017-05-26 17:53:28 +00:00
|
|
|
TryExecuteImpl(
|
|
|
|
FunctorType& functor,
|
|
|
|
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker())
|
2017-05-18 14:29:41 +00:00
|
|
|
: Functor(functor)
|
|
|
|
, Tracker(tracker)
|
|
|
|
, Success(false)
|
|
|
|
{
|
|
|
|
}
|
2016-08-15 23:15:17 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Device>
|
|
|
|
VTKM_CONT bool operator()(Device)
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
|
|
|
if (!this->Success)
|
|
|
|
{
|
2017-08-16 15:34:21 +00:00
|
|
|
using DeviceTraits = vtkm::cont::DeviceAdapterTraits<Device>;
|
2016-08-15 23:15:17 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
this->Success = detail::TryExecuteRunIfValid<FunctorType, Device, DeviceTraits::Valid>::Run(
|
|
|
|
this->Functor, this->Tracker);
|
2016-08-15 23:15:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return this->Success;
|
|
|
|
}
|
2017-01-10 18:10:38 +00:00
|
|
|
|
|
|
|
private:
|
2017-05-18 14:29:41 +00:00
|
|
|
void operator=(const TryExecuteImpl<FunctorType>&) = delete;
|
2016-08-15 23:15:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
/// \brief Try to execute a functor on a list of devices until one succeeds.
|
|
|
|
///
|
2016-08-17 20:13:51 +00:00
|
|
|
/// This function takes a functor and a list of devices. It then tries to run
|
2016-08-15 23:15:17 +00:00
|
|
|
/// 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.
|
|
|
|
///
|
2016-08-17 20:13:51 +00:00
|
|
|
/// 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.
|
|
|
|
///
|
2016-08-15 23:15:17 +00:00
|
|
|
/// 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.
|
|
|
|
///
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor, typename DeviceList>
|
2017-05-26 17:53:28 +00:00
|
|
|
VTKM_CONT bool TryExecute(const Functor& functor,
|
|
|
|
vtkm::cont::RuntimeDeviceTracker tracker,
|
2017-05-18 14:29:41 +00:00
|
|
|
DeviceList)
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
2016-08-17 20:13:51 +00:00
|
|
|
detail::TryExecuteImpl<const Functor> internals(functor, tracker);
|
2016-08-15 23:15:17 +00:00
|
|
|
vtkm::ListForEach(internals, DeviceList());
|
|
|
|
return internals.Success;
|
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor, typename DeviceList>
|
|
|
|
VTKM_CONT bool TryExecute(Functor& functor, vtkm::cont::RuntimeDeviceTracker tracker, DeviceList)
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
2016-08-17 20:13:51 +00:00
|
|
|
detail::TryExecuteImpl<Functor> internals(functor, tracker);
|
2016-08-15 23:15:17 +00:00
|
|
|
vtkm::ListForEach(internals, DeviceList());
|
|
|
|
return internals.Success;
|
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor, typename DeviceList>
|
|
|
|
VTKM_CONT bool TryExecute(const Functor& functor, DeviceList)
|
2016-08-17 20:13:51 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
return vtkm::cont::TryExecute(functor, vtkm::cont::GetGlobalRuntimeDeviceTracker(), DeviceList());
|
2016-08-17 20:13:51 +00:00
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor, typename DeviceList>
|
|
|
|
VTKM_CONT bool TryExecute(Functor& functor, DeviceList)
|
2016-08-17 20:13:51 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
return vtkm::cont::TryExecute(functor, vtkm::cont::GetGlobalRuntimeDeviceTracker(), DeviceList());
|
2016-08-17 20:13:51 +00:00
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor>
|
2017-05-26 17:53:28 +00:00
|
|
|
VTKM_CONT bool TryExecute(
|
|
|
|
const Functor& functor,
|
|
|
|
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker())
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
return vtkm::cont::TryExecute(functor, tracker, VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
|
2016-08-15 23:15:17 +00:00
|
|
|
}
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename Functor>
|
2017-05-26 17:53:28 +00:00
|
|
|
VTKM_CONT bool TryExecute(
|
|
|
|
Functor& functor,
|
|
|
|
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker())
|
2016-08-15 23:15:17 +00:00
|
|
|
{
|
2017-05-18 14:29:41 +00:00
|
|
|
return vtkm::cont::TryExecute(functor, tracker, VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG());
|
2016-08-15 23:15:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} // namespace vtkm::cont
|
|
|
|
|
|
|
|
#endif //vtk_m_cont_TryExecute_h
|