mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Replace FindDeviceAdapterTagAndCall with TryExecuteOnDevice
Also add a throwFailedRuntimeDeviceTransfer that throws a nicely detailed message on why a something couldn't be transfered to the requested device adapter.
This commit is contained in:
parent
554bc3d369
commit
28e0eb9da6
@ -22,8 +22,8 @@
|
||||
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
|
||||
#include <vtkm/cont/TryExecute.h>
|
||||
#include <vtkm/cont/VirtualObjectHandle.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterListHelpers.h>
|
||||
#include <vtkm/cont/internal/DynamicTransform.h>
|
||||
|
||||
#include <vtkm/VecTraits.h>
|
||||
@ -246,9 +246,14 @@ public:
|
||||
|
||||
VTKM_CONT PortalConst PrepareForInput(vtkm::cont::DeviceAdapterId deviceId) override
|
||||
{
|
||||
|
||||
PortalConst portal;
|
||||
vtkm::cont::internal::FindDeviceAdapterTagAndCall(
|
||||
deviceId, DeviceList(), PrepareForInputFunctor(), this, portal);
|
||||
bool success = vtkm::cont::TryExecuteOnDevice(
|
||||
deviceId, PrepareForInputFunctor(), DeviceList(), this, portal);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("ArrayHandleVirtualCoordinates", deviceId);
|
||||
}
|
||||
return portal;
|
||||
}
|
||||
|
||||
@ -256,16 +261,24 @@ public:
|
||||
vtkm::cont::DeviceAdapterId deviceId) override
|
||||
{
|
||||
Portal portal;
|
||||
vtkm::cont::internal::FindDeviceAdapterTagAndCall(
|
||||
deviceId, DeviceList(), PrepareForOutputFunctor(), this, numberOfValues, portal);
|
||||
bool success = vtkm::cont::TryExecuteOnDevice(
|
||||
deviceId, PrepareForOutputFunctor(), DeviceList(), this, numberOfValues, portal);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("ArrayHandleVirtualCoordinates", deviceId);
|
||||
}
|
||||
return portal;
|
||||
}
|
||||
|
||||
VTKM_CONT Portal PrepareForInPlace(vtkm::cont::DeviceAdapterId deviceId) override
|
||||
{
|
||||
Portal portal;
|
||||
vtkm::cont::internal::FindDeviceAdapterTagAndCall(
|
||||
deviceId, DeviceList(), PrepareForInPlaceFunctor(), this, portal);
|
||||
bool success = vtkm::cont::TryExecuteOnDevice(
|
||||
deviceId, PrepareForInPlaceFunctor(), DeviceList(), this, portal);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("ArrayHandleVirtualCoordinates", deviceId);
|
||||
}
|
||||
return portal;
|
||||
}
|
||||
|
||||
@ -273,7 +286,7 @@ private:
|
||||
struct PrepareForInputFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void operator()(DeviceAdapter device,
|
||||
VTKM_CONT bool operator()(DeviceAdapter device,
|
||||
CoordinatesArrayHandle* instance,
|
||||
PortalConst& ret) const
|
||||
{
|
||||
@ -283,13 +296,14 @@ private:
|
||||
vtkm::ListTagBase<DeviceAdapter>());
|
||||
ret = PortalConst(portal.GetNumberOfValues(),
|
||||
instance->DevicePortalHandle.PrepareForExecution(device));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct PrepareForOutputFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void operator()(DeviceAdapter device,
|
||||
VTKM_CONT bool operator()(DeviceAdapter device,
|
||||
CoordinatesArrayHandle* instance,
|
||||
vtkm::Id numberOfValues,
|
||||
Portal& ret) const
|
||||
@ -298,13 +312,14 @@ private:
|
||||
instance->DevicePortalHandle.Reset(
|
||||
new CoordinatesPortal<decltype(portal)>(portal), true, vtkm::ListTagBase<DeviceAdapter>());
|
||||
ret = Portal(numberOfValues, instance->DevicePortalHandle.PrepareForExecution(device));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct PrepareForInPlaceFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void operator()(DeviceAdapter device,
|
||||
VTKM_CONT bool operator()(DeviceAdapter device,
|
||||
CoordinatesArrayHandle* instance,
|
||||
Portal& ret) const
|
||||
{
|
||||
@ -313,6 +328,7 @@ private:
|
||||
new CoordinatesPortal<decltype(portal)>(portal), true, vtkm::ListTagBase<DeviceAdapter>());
|
||||
ret = Portal(instance->Array.GetNumberOfValues(),
|
||||
instance->DevicePortalHandle.PrepareForExecution(device));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterListHelpers.h>
|
||||
#include <vtkm/exec/BoundingIntervalHierarchyExec.h>
|
||||
#include <vtkm/worklet/DispatcherMapField.h>
|
||||
#include <vtkm/worklet/DispatcherMapTopology.h>
|
||||
@ -455,7 +454,7 @@ class BoundingIntervalHierarchy::PrepareForExecutionFunctor
|
||||
{
|
||||
public:
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void operator()(DeviceAdapter,
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::BoundingIntervalHierarchy& bih,
|
||||
HandleType& bihExec) const
|
||||
{
|
||||
@ -508,6 +507,7 @@ public:
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Could not determine type to write out.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -522,9 +522,12 @@ VTKM_CONT
|
||||
const HandleType BoundingIntervalHierarchy::PrepareForExecutionImpl(
|
||||
const vtkm::cont::DeviceAdapterId deviceId) const
|
||||
{
|
||||
using DeviceList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG;
|
||||
vtkm::cont::internal::FindDeviceAdapterTagAndCall(
|
||||
deviceId, DeviceList(), PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
const bool success =
|
||||
vtkm::cont::TryExecuteOnDevice(deviceId, PrepareForExecutionFunctor(), *this, this->ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("BoundingIntervalHierarchy", deviceId);
|
||||
}
|
||||
|
||||
return this->ExecHandle;
|
||||
}
|
||||
|
@ -126,6 +126,7 @@ set(sources
|
||||
DataSetBuilderUniform.cxx
|
||||
DynamicArrayHandle.cxx
|
||||
EnvironmentTracker.cxx
|
||||
ErrorBadDevice.cxx
|
||||
Field.cxx
|
||||
FieldRangeCompute.cxx
|
||||
FieldRangeGlobalCompute.cxx
|
||||
|
@ -860,15 +860,20 @@ const vtkm::exec::ColorTableBase* ColorTable::PrepareForExecution(
|
||||
this->Impl->OpacityMidSharpHandle = vtkm::cont::make_ArrayHandle(this->Impl->OpacityMidSharp);
|
||||
}
|
||||
|
||||
bool transfered = true;
|
||||
if (this->Impl->ColorArraysChanged || this->Impl->OpacityArraysChanged ||
|
||||
this->Impl->HostSideCacheChanged)
|
||||
{
|
||||
vtkm::cont::internal::FindDeviceAdapterTagAndCall(deviceId,
|
||||
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG(),
|
||||
detail::transfer_color_table_to_device{},
|
||||
this->Impl->HostSideCache.get(),
|
||||
this->Impl.get());
|
||||
transfered = vtkm::cont::TryExecuteOnDevice(deviceId,
|
||||
detail::transfer_color_table_to_device{},
|
||||
this->Impl->HostSideCache.get(),
|
||||
this->Impl.get());
|
||||
}
|
||||
if (!transfered)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("ColorTable", deviceId);
|
||||
}
|
||||
|
||||
|
||||
this->Impl->ColorArraysChanged = false;
|
||||
this->Impl->OpacityArraysChanged = false;
|
||||
|
42
vtkm/cont/ErrorBadDevice.cxx
Normal file
42
vtkm/cont/ErrorBadDevice.cxx
Normal file
@ -0,0 +1,42 @@
|
||||
//============================================================================
|
||||
// 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 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
|
||||
// Copyright 2016 UT-Battelle, LLC.
|
||||
// Copyright 2016 Los Alamos National Security.
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#include <vtkm/cont/ErrorBadDevice.h>
|
||||
#include <vtkm/cont/internal/DeviceAdapterTag.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
void throwFailedRuntimeDeviceTransfer(const std::string& className,
|
||||
vtkm::cont::DeviceAdapterId deviceId)
|
||||
{ //Should we support typeid() instead of className?
|
||||
const std::string msg = "VTK-m was unable to transfer " + className + " to DeviceAdapter[id=" +
|
||||
std::to_string(deviceId.GetValue()) +
|
||||
"]. This is generally caused by asking for execution on a DeviceAdapter that "
|
||||
"isn't compiled into VTK-m. In the case of CUDA it can also be caused by accidentally "
|
||||
"compiling source files as C++ files instead of CUDA.";
|
||||
throw vtkm::cont::ErrorBadDevice(msg);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,11 +22,15 @@
|
||||
|
||||
#include <vtkm/cont/Error.h>
|
||||
|
||||
#include <vtkm/cont/internal/DeviceAdapterTag.h>
|
||||
#include <vtkm/cont/vtkm_cont_export.h>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace cont
|
||||
{
|
||||
|
||||
|
||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
||||
|
||||
/// This class is thrown when VTK-m performs an operation that is not supported
|
||||
@ -42,6 +46,15 @@ public:
|
||||
};
|
||||
|
||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
||||
|
||||
/// Throws an ErrorBadeDevice exception with the following message:
|
||||
/// "VTK-m was unable to transfer \c className to DeviceAdapter[id=\c device].
|
||||
/// This is generally caused by asking for execution on a DeviceAdapter that
|
||||
/// isn't compiled into VTK-m. In the case of CUDA it can also be caused by accidentally
|
||||
/// compiling source files as C++ files instead of CUDA."
|
||||
//
|
||||
VTKM_CONT_EXPORT void throwFailedRuntimeDeviceTransfer(const std::string& className,
|
||||
vtkm::cont::DeviceAdapterId device);
|
||||
}
|
||||
} // namespace vtkm::cont
|
||||
|
||||
|
@ -60,7 +60,6 @@ public:
|
||||
return PrepareForExecutionImp(device).PrepareForExecution(device);
|
||||
}
|
||||
|
||||
//VTKM_CONT virtual const vtkm::exec::PointLocator*
|
||||
using HandleType = vtkm::cont::VirtualObjectHandle<vtkm::exec::PointLocator>;
|
||||
VTKM_CONT virtual const HandleType PrepareForExecutionImp(
|
||||
vtkm::cont::DeviceAdapterId deviceId) const = 0;
|
||||
|
@ -140,11 +140,10 @@ public:
|
||||
struct PrepareForExecutionFunctor
|
||||
{
|
||||
template <typename DeviceAdapter>
|
||||
VTKM_CONT void operator()(DeviceAdapter,
|
||||
VTKM_CONT bool operator()(DeviceAdapter,
|
||||
const vtkm::cont::PointLocatorUniformGrid& self,
|
||||
HandleType& handle) const
|
||||
{
|
||||
//vtkm::exec::PointLocatorUniformGrid* locator =
|
||||
vtkm::exec::PointLocatorUniformGrid<DeviceAdapter>* h =
|
||||
new vtkm::exec::PointLocatorUniformGrid<DeviceAdapter>(
|
||||
self.Min,
|
||||
@ -155,27 +154,20 @@ public:
|
||||
self.cellLower.PrepareForInput(DeviceAdapter()),
|
||||
self.cellUpper.PrepareForInput(DeviceAdapter()));
|
||||
handle.Reset(h);
|
||||
//return handle.PrepareForExecution(DeviceAdapter());
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
VTKM_CONT
|
||||
//const vtkm::exec::PointLocator *
|
||||
const HandleType PrepareForExecutionImp(vtkm::cont::DeviceAdapterId deviceId) const override
|
||||
{
|
||||
// TODO: call VirtualObjectHandle::PrepareForExecution() and return vtkm::exec::PointLocator
|
||||
// TODO: how to convert deviceId back to DeviceAdapter tag?
|
||||
//using DeviceList = vtkm::ListTagBase<vtkm::cont::DeviceAdapterTagCuda,
|
||||
// vtkm::cont::DeviceAdapterTagTBB,
|
||||
// vtkm::cont::DeviceAdapterTagSerial>;
|
||||
|
||||
using DeviceList = VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG;
|
||||
//HandleType ExecHandle; // = new HandleType(locator, false);
|
||||
vtkm::cont::internal::FindDeviceAdapterTagAndCall(
|
||||
deviceId, DeviceList(), PrepareForExecutionFunctor(), *this, ExecHandle);
|
||||
const bool success =
|
||||
vtkm::cont::TryExecuteOnDevice(deviceId, PrepareForExecutionFunctor(), *this, ExecHandle);
|
||||
if (!success)
|
||||
{
|
||||
throwFailedRuntimeDeviceTransfer("PointLocatorUniformGrid", deviceId);
|
||||
}
|
||||
return ExecHandle;
|
||||
|
||||
//return ExecHandle.PrepareForExecution(DeviceAdapter());
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -130,11 +130,12 @@ public:
|
||||
{
|
||||
if (!this->Internals->Transfers[static_cast<std::size_t>(deviceId.GetValue())])
|
||||
{
|
||||
std::string msg = "VTK-m was asked to transfer an object for execution on DeviceAdapter " +
|
||||
std::string msg =
|
||||
"VTK-m was asked to transfer a VirtualObjectHandle for execution on DeviceAdapter " +
|
||||
std::to_string(deviceId.GetValue()) +
|
||||
". It can't as this VirtualObjectHandle was not constructed/bound with this "
|
||||
"DeviceAdapter in the list of valid DeviceAdapters.";
|
||||
throw vtkm::cont::ErrorBadType(msg);
|
||||
throw vtkm::cont::ErrorBadDevice(msg);
|
||||
}
|
||||
|
||||
if (this->Internals->Current)
|
||||
@ -198,17 +199,9 @@ private:
|
||||
std::unique_ptr<TransferInterface>* transfers,
|
||||
const VirtualDerivedType* virtualObject) const
|
||||
{
|
||||
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
|
||||
if (!device.IsValueValid())
|
||||
{
|
||||
|
||||
std::string msg =
|
||||
"VTK-m is unable to construct a VirtualObjectHandle for execution on DeviceAdapter" +
|
||||
DeviceInfo::GetName() + "[id=" + std::to_string(device.GetValue()) +
|
||||
"]. This is generally caused by either asking for execution on a DeviceAdapter that "
|
||||
"wasn't compiled into VTK-m. In the case of CUDA it can also be caused by accidentally "
|
||||
"compiling source files as C++ files instead of CUDA.";
|
||||
throw vtkm::cont::ErrorBadType(msg);
|
||||
throwFailedRuntimeDeviceTransfer("VirtualObjectHandle", device);
|
||||
}
|
||||
using TransferImpl = TransferInterfaceImpl<VirtualDerivedType, DeviceAdapter>;
|
||||
transfers[device.GetValue()].reset(new TransferImpl(virtualObject));
|
||||
|
@ -32,104 +32,43 @@ namespace internal
|
||||
{
|
||||
|
||||
//============================================================================
|
||||
template <typename FunctorType>
|
||||
class ExecuteIfValidDeviceTag
|
||||
struct ExecuteIfValidDeviceTag
|
||||
{
|
||||
private:
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
using EnableIfValid = std::enable_if<DeviceAdapter::IsEnabled>;
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
using EnableIfInvalid = std::enable_if<!DeviceAdapter::IsEnabled>;
|
||||
|
||||
public:
|
||||
explicit ExecuteIfValidDeviceTag(const FunctorType& functor)
|
||||
: Functor(functor)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter, typename... Args>
|
||||
template <typename DeviceAdapter, typename Functor, typename... Args>
|
||||
typename EnableIfValid<DeviceAdapter>::type operator()(
|
||||
DeviceAdapter device,
|
||||
Functor&& f,
|
||||
const vtkm::cont::RuntimeDeviceTracker& tracker,
|
||||
Args&&... args) const
|
||||
{
|
||||
if (tracker.CanRunOn(device))
|
||||
{
|
||||
this->Functor(device, std::forward<Args>(args)...);
|
||||
f(device, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
// do not generate code for invalid devices
|
||||
template <typename DeviceAdapter, typename... Args>
|
||||
typename EnableIfInvalid<DeviceAdapter>::type operator()(DeviceAdapter,
|
||||
const vtkm::cont::RuntimeDeviceTracker&,
|
||||
Args&&...) const
|
||||
typename EnableIfInvalid<DeviceAdapter>::type operator()(DeviceAdapter, Args&&...) const
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
FunctorType Functor;
|
||||
};
|
||||
|
||||
/// Execute the given functor on each valid device in \c DeviceList.
|
||||
///
|
||||
template <typename DeviceList, typename Functor, typename... Args>
|
||||
VTKM_CONT void ForEachValidDevice(DeviceList devices, const Functor& functor, Args&&... args)
|
||||
VTKM_CONT void ForEachValidDevice(DeviceList devices, Functor&& functor, Args&&... args)
|
||||
{
|
||||
auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
|
||||
|
||||
ExecuteIfValidDeviceTag<Functor> wrapped(functor);
|
||||
vtkm::ListForEach(wrapped, devices, tracker, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
template <typename FunctorType>
|
||||
class ExecuteIfSameDeviceId
|
||||
{
|
||||
public:
|
||||
ExecuteIfSameDeviceId(FunctorType functor)
|
||||
: Functor(functor)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename DeviceAdapter, typename... Args>
|
||||
void operator()(DeviceAdapter device,
|
||||
vtkm::cont::DeviceAdapterId deviceId,
|
||||
bool& status,
|
||||
Args&&... args) const
|
||||
{
|
||||
if (device == deviceId)
|
||||
{
|
||||
VTKM_ASSERT(status == false);
|
||||
this->Functor(device, std::forward<Args>(args)...);
|
||||
status = true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
FunctorType Functor;
|
||||
};
|
||||
|
||||
/// Finds the \c DeviceAdapterTag in \c DeviceList with id equal to deviceId
|
||||
/// and executes the functor with the tag. Throws \c ErrorBadDevice if a valid
|
||||
/// \c DeviceAdapterTag is not found.
|
||||
///
|
||||
template <typename DeviceList, typename Functor, typename... Args>
|
||||
VTKM_CONT void FindDeviceAdapterTagAndCall(vtkm::cont::DeviceAdapterId deviceId,
|
||||
DeviceList devices,
|
||||
const Functor& functor,
|
||||
Args&&... args)
|
||||
{
|
||||
bool status = false;
|
||||
ExecuteIfSameDeviceId<Functor> wrapped(functor);
|
||||
ForEachValidDevice(devices, wrapped, deviceId, status, std::forward<Args>(args)...);
|
||||
if (!status)
|
||||
{
|
||||
std::string msg = "Device with id " + std::to_string(deviceId.GetValue()) +
|
||||
" is either not in the list or is invalid";
|
||||
throw vtkm::cont::ErrorBadDevice(msg);
|
||||
}
|
||||
vtkm::ListForEach(
|
||||
ExecuteIfValidDeviceTag{}, devices, functor, tracker, std::forward<Args>(args)...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user