Commit 554bc3d3 authored by Robert Maynard's avatar Robert Maynard

At runtime TryExecute supports a specific deviceId to execute on.

Instead of always using the first enabled device, now TryExecute
can be told which device at runtime to use.
parent b9082cd8
# TryExecuteOnDevice allows for runtime selection of which device to execute on
VTK-m now offers `vtkm::cont::TryExecuteOnDevice` to allow for the user to select
which device to execute a function on at runtime. The original `vtkm::cont::TryExecute`
used the first valid device, which meant users had to modify the runtime state
through the `RuntimeTracker` which was verbose and unwieldy.
Here is an example of how you can execute a function on the device that an array handle was last executed
on:
```cpp
struct ArrayCopyFunctor
{
template <typename Device, typename InArray, typename OutArray>
VTKM_CONT bool operator()(Device, const InArray& src, OutArray& dest)
{
vtkm::cont::DeviceAdapterAlgorithm<Device>::Copy(src, dest);
return true;
}
};
template<typename T, typename InStorage, typename OutStorage>
void SmartCopy(const vtkm::cont::ArrayHandle<T, InStorage>& src, vtkm::cont::ArrayHandle<T, OutStorage>& dest)
{
bool success = vtkm::cont::TryExecuteOnDevice(devId, ArrayCopyFunctor(), src, dest);
if (!success)
{
vtkm::cont::TryExecute(ArrayCopyFunctor(), src, dest);
}
}
```
#DeviceAdapterId has becomes a real constexpr type and not an alias to vtkm::UInt8
As part of the ability to support `vtkm::cont::TryExecuteOnDevice` VTK-m has made the
DeviceAdapterId a real constexpr type instead of a vtkm::UInt8.
The benefits of a real type are as follows:
- Easier to add functionality like range verification, which previously had
to be located in each user of `DeviceAdapterId`
- In ability to have ambiguous arguments. Previously it wasn't perfectly clear
what a method parameter of `vtkm::UInt8` represented. Was it actually the
DeviceAdapterId or something else?
- Ability to add subclasses that represent things such as Undefined, Error, or Any.
The implementation of DeviceAdapterId is:
```cpp
struct DeviceAdapterId
{
constexpr explicit DeviceAdapterId(vtkm::Int8 id)
: Value(id)
{
}
constexpr bool operator==(DeviceAdapterId other) const { return this->Value == other.Value; }
constexpr bool operator!=(DeviceAdapterId other) const { return this->Value != other.Value; }
constexpr bool operator<(DeviceAdapterId other) const { return this->Value < other.Value; }
constexpr bool IsValueValid() const
{
return this->Value > 0 && this->Value < VTKM_MAX_DEVICE_ADAPTER_ID;
}
constexpr vtkm::Int8 GetValue() const { return this->Value; }
private:
vtkm::Int8 Value;
};
```
# DeviceAdapterTags are usable for runtime device selection
VTK-m DeviceAdapterTags now are both a compile time representation of which device to use, and
also the runtime representation of that device. Previously the runtime representation was handled
by `vtkm::cont::DeviceAdapterId`. This was done by making `DeviceAdapterTag`'s' a constexpr type that
inherits from the constexpr `vtkm::cont::DeviceAdapterId` type.
At at ten thousand foot level this change means that in general instead of using `vtkm::cont::DeviceAdapterTraits<DeviceTag>`
you can simply use `DeviceTag`, or an instance of if `DeviceTag runtimeDeviceId;`.
Previously if you wanted to get the runtime representation of a device you would do the following:
```cpp
template<typename DeviceTag>
vtkm::cont::DeviceAdapterId getDeviceId()
{
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceTag>;
return Traits::GetId();
}
...
vtkm::cont::DeviceAdapterId runtimeId = getDeviceId<DeviceTag>();
```
Now with the updates you could do the following.
```cpp
vtkm::cont::DeviceAdapterId runtimeId = DeviceTag();
```
More importantly this conversion is unnecessary as you can pass instances `DeviceAdapterTags` into methods or functions
that want `vtkm::cont::DeviceAdapterId` as they are that type!
Previously if you wanted to see if a DeviceAdapter was enabled you would the following:
```cpp
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceTag>;
constexpr auto isValid = std::integral_constant<bool, Traits::Valid>();
```
Now you would do:
```cpp
constexpr auto isValid = std::integral_constant<bool, DeviceTag::IsEnabled>();
```
So why did VTK-m make these changes?
That is a good question, and the answer for that is two fold. The VTK-m project is working better support for ArraysHandles that leverage runtime polymorphism (aka virtuals), and the ability to construct `vtkm::worklet::Dispatchers` without specifying
the explicit device they should run on. Both of these designs push more of the VTK-m logic to operate at runtime rather than compile time. This changes are designed to allow for consistent object usage between runtime and compile time instead of having
to convert between compile time and runtime types.
......@@ -59,43 +59,13 @@ VTKM_CONT void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>&
namespace detail
{
template <typename InValueType, typename InStorage, typename OutValueType, typename OutStorage>
struct ArrayCopyFunctor
{
using InArrayHandleType = vtkm::cont::ArrayHandle<InValueType, InStorage>;
InArrayHandleType InputArray;
using OutArrayHandleType = vtkm::cont::ArrayHandle<OutValueType, OutStorage>;
OutArrayHandleType OutputArray;
bool OnlyUseCurrentInputDevice;
VTKM_CONT
ArrayCopyFunctor(const InArrayHandleType& input,
OutArrayHandleType& output,
bool onlyUseCurrentInputDevice)
: InputArray(input)
, OutputArray(output)
, OnlyUseCurrentInputDevice(onlyUseCurrentInputDevice)
{
}
template <typename Device>
VTKM_CONT bool operator()(Device)
template <typename Device, typename InArray, typename OutArray>
VTKM_CONT bool operator()(Device, const InArray& input, OutArray& output)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
if (this->OnlyUseCurrentInputDevice &&
(vtkm::cont::DeviceAdapterTraits<Device>::GetId() != this->InputArray.GetDeviceAdapterId()))
{
// We were asked to only copy on the device that already has the data from the input array.
// This is not that device, so return without copying.
return false;
}
vtkm::cont::ArrayCopy(this->InputArray, this->OutputArray, Device());
vtkm::cont::ArrayCopy(input, output, Device());
return true;
}
};
......@@ -116,28 +86,19 @@ VTKM_CONT void ArrayCopy(
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination,
vtkm::cont::RuntimeDeviceTracker tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker())
{
bool isCopied = false;
detail::ArrayCopyFunctor<InValueType, InStorage, OutValueType, OutStorage> functor(
source, destination, true);
detail::ArrayCopyFunctor functor;
// First pass, only use source's already loaded device.
isCopied = vtkm::cont::TryExecute(functor, tracker);
if (isCopied)
{
return;
bool isCopied = vtkm::cont::TryExecuteOnDevice(
source.GetDeviceAdapterId(), functor, tracker, source, destination);
if (!isCopied)
{ // Second pass, use any available device.
isCopied = vtkm::cont::TryExecute(functor, tracker, source, destination);
}
// Second pass, use any available device.
functor.OnlyUseCurrentInputDevice = false;
isCopied = vtkm::cont::TryExecute(functor, tracker);
if (isCopied)
{
return;
if (!isCopied)
{ // If after the second pass, still not valid through an exception
throw vtkm::cont::ErrorExecution("Failed to run ArrayCopy on any device.");
}
// If we are here, then we just failed to copy.
throw vtkm::cont::ErrorExecution("Failed to run ArrayCopy on any device.");
}
}
} // namespace vtkm::cont
......
......@@ -498,7 +498,7 @@ public:
{
return this->Internals->ExecutionArrayValid
? this->Internals->ExecutionArray->GetDeviceAdapterId()
: VTKM_DEVICE_ADAPTER_UNDEFINED;
: DeviceAdapterIdUndefined{};
}
struct VTKM_ALWAYS_EXPORT InternalStruct
......
......@@ -273,45 +273,46 @@ private:
struct PrepareForInputFunctor
{
template <typename DeviceAdapter>
VTKM_CONT void operator()(DeviceAdapter,
VTKM_CONT void operator()(DeviceAdapter device,
CoordinatesArrayHandle* instance,
PortalConst& ret) const
{
auto portal = instance->Array.PrepareForInput(DeviceAdapter());
auto portal = instance->Array.PrepareForInput(device);
instance->DevicePortalHandle.Reset(new CoordinatesPortalConst<decltype(portal)>(portal),
true,
vtkm::ListTagBase<DeviceAdapter>());
ret = PortalConst(portal.GetNumberOfValues(),
instance->DevicePortalHandle.PrepareForExecution(DeviceAdapter()));
instance->DevicePortalHandle.PrepareForExecution(device));
}
};
struct PrepareForOutputFunctor
{
template <typename DeviceAdapter>
VTKM_CONT void operator()(DeviceAdapter,
VTKM_CONT void operator()(DeviceAdapter device,
CoordinatesArrayHandle* instance,
vtkm::Id numberOfValues,
Portal& ret) const
{
auto portal = instance->Array.PrepareForOutput(numberOfValues, DeviceAdapter());
auto portal = instance->Array.PrepareForOutput(numberOfValues, device);
instance->DevicePortalHandle.Reset(
new CoordinatesPortal<decltype(portal)>(portal), true, vtkm::ListTagBase<DeviceAdapter>());
ret =
Portal(numberOfValues, instance->DevicePortalHandle.PrepareForExecution(DeviceAdapter()));
ret = Portal(numberOfValues, instance->DevicePortalHandle.PrepareForExecution(device));
}
};
struct PrepareForInPlaceFunctor
{
template <typename DeviceAdapter>
VTKM_CONT void operator()(DeviceAdapter, CoordinatesArrayHandle* instance, Portal& ret) const
VTKM_CONT void operator()(DeviceAdapter device,
CoordinatesArrayHandle* instance,
Portal& ret) const
{
auto portal = instance->Array.PrepareForInPlace(DeviceAdapter());
auto portal = instance->Array.PrepareForInPlace(device);
instance->DevicePortalHandle.Reset(
new CoordinatesPortal<decltype(portal)>(portal), true, vtkm::ListTagBase<DeviceAdapter>());
ret = Portal(instance->Array.GetNumberOfValues(),
instance->DevicePortalHandle.PrepareForExecution(DeviceAdapter()));
instance->DevicePortalHandle.PrepareForExecution(device));
}
};
......@@ -384,20 +385,19 @@ public:
VTKM_CONT
PortalConstExecution PrepareForInput(bool)
{
return this->Array->PrepareForInput(vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId());
return this->Array->PrepareForInput(DeviceAdapter());
}
VTKM_CONT
PortalExecution PrepareForInPlace(bool)
{
return this->Array->PrepareForInPlace(vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId());
return this->Array->PrepareForInPlace(DeviceAdapter());
}
VTKM_CONT
PortalExecution PrepareForOutput(vtkm::Id numberOfValues)
{
return this->Array->PrepareForOutput(numberOfValues,
vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId());
return this->Array->PrepareForOutput(numberOfValues, DeviceAdapter());
}
VTKM_CONT
......
......@@ -67,10 +67,9 @@ public:
}
template <typename DeviceAdapter>
VTKM_CONT const vtkm::exec::CellLocator* PrepareForExecution(DeviceAdapter) const
VTKM_CONT const vtkm::exec::CellLocator* PrepareForExecution(DeviceAdapter device) const
{
vtkm::cont::DeviceAdapterId deviceId = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
return PrepareForExecutionImpl(deviceId).PrepareForExecution(DeviceAdapter());
return PrepareForExecutionImpl(device).PrepareForExecution(device);
}
protected:
......
......@@ -666,17 +666,6 @@ public:
/// This pointer is only valid as long as the ColorTable is unmodified
const vtkm::exec::ColorTableBase* PrepareForExecution(vtkm::cont::DeviceAdapterId deviceId) const;
/// \brief returns a virtual object pointer of the exec color table
///
/// This pointer is only valid as long as the ColorTable is unmodified
template <typename DeviceAdapter>
const vtkm::exec::ColorTableBase* PrepareForExecution(DeviceAdapter) const
{
auto deviceId = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
return this->PrepareForExecution(deviceId);
}
/// \brief returns the modified count for the virtual object handle of the exec color table
///
/// The modified count allows consumers of a shared color table to keep track
......
......@@ -55,10 +55,9 @@ public:
}
template <typename DeviceAdapter>
VTKM_CONT const vtkm::exec::PointLocator* PrepareForExecution(DeviceAdapter) const
VTKM_CONT const vtkm::exec::PointLocator* PrepareForExecution(DeviceAdapter device) const
{
vtkm::cont::DeviceAdapterId deviceId = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
return PrepareForExecutionImp(deviceId).PrepareForExecution(DeviceAdapter());
return PrepareForExecutionImp(device).PrepareForExecution(device);
}
//VTKM_CONT virtual const vtkm::exec::PointLocator*
......
......@@ -34,8 +34,6 @@
#include <sstream>
#include <thread>
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
namespace vtkm
{
namespace cont
......@@ -66,10 +64,10 @@ VTKM_CONT
void RuntimeDeviceTracker::CheckDevice(vtkm::cont::DeviceAdapterId deviceId,
const vtkm::cont::DeviceAdapterNameType& deviceName) const
{
if ((deviceId < 0) || (deviceId >= VTKM_MAX_DEVICE_ADAPTER_ID))
if (!deviceId.IsValueValid())
{
std::stringstream message;
message << "Device '" << deviceName << "' has invalid ID of " << deviceId;
message << "Device '" << deviceName << "' has invalid ID of " << (int)deviceId.GetValue();
throw vtkm::cont::ErrorBadValue(message.str());
}
}
......@@ -79,7 +77,7 @@ bool RuntimeDeviceTracker::CanRunOnImpl(vtkm::cont::DeviceAdapterId deviceId,
const vtkm::cont::DeviceAdapterNameType& deviceName) const
{
this->CheckDevice(deviceId, deviceName);
return this->Internals->RuntimeValid[deviceId];
return this->Internals->RuntimeValid[deviceId.GetValue()];
}
VTKM_CONT
......@@ -88,7 +86,7 @@ void RuntimeDeviceTracker::SetDeviceState(vtkm::cont::DeviceAdapterId deviceId,
bool state)
{
this->CheckDevice(deviceId, deviceName);
this->Internals->RuntimeValid[deviceId] = state;
this->Internals->RuntimeValid[deviceId.GetValue()] = state;
}
namespace
......@@ -105,9 +103,9 @@ struct VTKM_NEVER_EXPORT RuntimeDeviceTrackerResetFunctor
}
template <typename Device>
VTKM_CONT void operator()(Device)
VTKM_CONT void operator()(Device device)
{
this->Tracker.ResetDevice(Device());
this->Tracker.ResetDevice(device);
}
};
}
......@@ -152,7 +150,7 @@ void RuntimeDeviceTracker::ForceDeviceImpl(vtkm::cont::DeviceAdapterId deviceId,
std::fill_n(this->Internals->RuntimeValid, VTKM_MAX_DEVICE_ADAPTER_ID, false);
this->Internals->RuntimeValid[deviceId] = runtimeExists;
this->Internals->RuntimeValid[deviceId.GetValue()] = runtimeExists;
}
VTKM_CONT
......
......@@ -62,10 +62,10 @@ public:
/// machine.
///
template <typename DeviceAdapterTag>
VTKM_CONT bool CanRunOn(DeviceAdapterTag) const
VTKM_CONT bool CanRunOn(DeviceAdapterTag device) const
{
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
return this->CanRunOnImpl(Traits::GetId(), Traits::GetName());
return this->CanRunOnImpl(device, Traits::GetName());
}
/// Report a failure to allocate memory on a device, this will flag the
......@@ -73,10 +73,11 @@ public:
/// the filter.
///
template <typename DeviceAdapterTag>
VTKM_CONT void ReportAllocationFailure(DeviceAdapterTag, const vtkm::cont::ErrorBadAllocation&)
VTKM_CONT void ReportAllocationFailure(DeviceAdapterTag device,
const vtkm::cont::ErrorBadAllocation&)
{
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
this->SetDeviceState(Traits::GetId(), Traits::GetName(), false);
this->SetDeviceState(device, Traits::GetName(), false);
}
/// Report a failure to allocate memory on a device, this will flag the
......@@ -93,10 +94,10 @@ public:
//@{
/// Report a ErrorBadDevice failure and flag the device as unusable.
template <typename DeviceAdapterTag>
VTKM_CONT void ReportBadDeviceFailure(DeviceAdapterTag, const vtkm::cont::ErrorBadDevice&)
VTKM_CONT void ReportBadDeviceFailure(DeviceAdapterTag device, const vtkm::cont::ErrorBadDevice&)
{
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
this->SetDeviceState(Traits::GetId(), Traits::GetName(), false);
this->SetDeviceState(device, Traits::GetName(), false);
}
VTKM_CONT void ReportBadDeviceFailure(vtkm::cont::DeviceAdapterId deviceId,
......@@ -111,11 +112,11 @@ public:
/// caused by reported failures
///
template <typename DeviceAdapterTag>
VTKM_CONT void ResetDevice(DeviceAdapterTag)
VTKM_CONT void ResetDevice(DeviceAdapterTag device)
{
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
vtkm::cont::RuntimeDeviceInformation<DeviceAdapterTag> runtimeDevice;
this->SetDeviceState(Traits::GetId(), Traits::GetName(), runtimeDevice.Exists());
this->SetDeviceState(device, Traits::GetName(), runtimeDevice.Exists());
}
/// Reset the tracker to its default state for default devices.
......@@ -177,10 +178,10 @@ public:
/// Use \c ResetDevice to turn the device back on (if it is supported).
///
template <typename DeviceAdapterTag>
VTKM_CONT void DisableDevice(DeviceAdapterTag)
VTKM_CONT void DisableDevice(DeviceAdapterTag device)
{
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
this->SetDeviceState(Traits::GetId(), Traits::GetName(), false);
this->SetDeviceState(device, Traits::GetName(), false);
}
/// \brief Disable all devices except the specified one.
......@@ -196,11 +197,11 @@ public:
/// exist on the system.
///
template <typename DeviceAdapterTag>
VTKM_CONT void ForceDevice(DeviceAdapterTag)
VTKM_CONT void ForceDevice(DeviceAdapterTag device)
{
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
vtkm::cont::RuntimeDeviceInformation<DeviceAdapterTag> runtimeDevice;
this->ForceDeviceImpl(Traits::GetId(), Traits::GetName(), runtimeDevice.Exists());
this->ForceDeviceImpl(device, Traits::GetName(), runtimeDevice.Exists());
}
private:
......
This diff is collapsed.
......@@ -30,8 +30,6 @@
#include <array>
#include <type_traits>
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
namespace vtkm
{
namespace cont
......@@ -114,7 +112,6 @@ public:
/// Release all the execution side resources
VTKM_CONT void ReleaseExecutionResources() { this->Internals->ReleaseExecutionResources(); }
/// Get a valid \c VirtualBaseType* with the current control side state for \c deviceId.
/// VirtualObjectHandle and the returned pointer are analogous to ArrayHandle and Portal
/// The returned pointer will be invalidated if:
......@@ -129,21 +126,14 @@ public:
throw vtkm::cont::ErrorBadValue("No target object bound");
}
if (deviceId < 0 || deviceId >= VTKM_MAX_DEVICE_ADAPTER_ID)
{
std::string msg = "An invalid device adapter ID of " + std::to_string(deviceId) +
"was used when trying to construct a virtual object. The valid range is between " +
"0 and " + std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
throw vtkm::cont::ErrorBadType(msg);
}
if (!this->Internals->Current || this->Internals->Current->GetDeviceId() != deviceId)
{
if (!this->Internals->Transfers[static_cast<std::size_t>(deviceId)])
if (!this->Internals->Transfers[static_cast<std::size_t>(deviceId.GetValue())])
{
std::string msg = "The device adapter ID of " + std::to_string(deviceId) +
" was not part of the set of valid adapters when this virtual object was constructed " +
"or last binded to a set of device adapters.";
std::string msg = "VTK-m was asked to transfer an object 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);
}
......@@ -152,25 +142,12 @@ public:
this->Internals->Current->ReleaseResources();
}
this->Internals->Current =
this->Internals->Transfers[static_cast<std::size_t>(deviceId)].get();
this->Internals->Transfers[static_cast<std::size_t>(deviceId.GetValue())].get();
}
return this->Internals->Current->PrepareForExecution();
}
/// Get a valid \c VirtualBaseType* with the current control side state for \c DeviceAdapter.
/// VirtualObjectHandle and the returned pointer are analogous to ArrayHandle and Portal
/// The returned pointer will be invalidated if:
/// 1. A new pointer is requested for a different DeviceAdapter
/// 2. VirtualObjectHandle is destroyed
/// 3. Reset or ReleaseResources is called
///
template <typename DeviceAdapter>
VTKM_CONT const VirtualBaseType* PrepareForExecution(DeviceAdapter) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
return this->PrepareForExecution(DeviceInfo::GetId());
}
private:
class TransferInterface
......@@ -194,10 +171,7 @@ private:
{
}
VTKM_CONT vtkm::cont::DeviceAdapterId GetDeviceId() const override
{
return vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
}
VTKM_CONT vtkm::cont::DeviceAdapterId GetDeviceId() const override { return DeviceAdapter(); }
VTKM_CONT const VirtualBaseType* PrepareForExecution() override
{
......@@ -220,21 +194,24 @@ private:
struct CreateTransferInterface
{
template <typename DeviceAdapter>
VTKM_CONT void operator()(DeviceAdapter,
VTKM_CONT void operator()(DeviceAdapter device,
std::unique_ptr<TransferInterface>* transfers,
const VirtualDerivedType* virtualObject) const
{
using DeviceInfo = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
if (DeviceInfo::GetId() < 0 || DeviceInfo::GetId() >= VTKM_MAX_DEVICE_ADAPTER_ID)
if (!device.IsValueValid())
{
std::string msg = "Device '" + DeviceInfo::GetName() + "' has invalid ID of " +
std::to_string(DeviceInfo::GetId()) + "(VTKM_MAX_DEVICE_ADAPTER_ID = " +
std::to_string(VTKM_MAX_DEVICE_ADAPTER_ID) + ")";
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);
}
using TransferImpl = TransferInterfaceImpl<VirtualDerivedType, DeviceAdapter>;
transfers[DeviceInfo::GetId()].reset(new TransferImpl(virtualObject));
transfers[device.GetValue()].reset(new TransferImpl(virtualObject));
}
};
......@@ -277,6 +254,4 @@ private:
}
} // vtkm::cont
#undef VTKM_MAX_DEVICE_ADAPTER_ID
#endif // vtk_m_cont_VirtualObjectHandle_h
......@@ -250,7 +250,7 @@ bool ArrayHandleImpl::PrepareForDevice(DeviceAdapterId devId, vtkm::UInt64 sizeO
DeviceAdapterId ArrayHandleImpl::GetDeviceAdapterId() const
{
return this->ExecutionArrayValid ? this->ExecutionInterface->GetDeviceId()
: VTKM_DEVICE_ADAPTER_UNDEFINED;
: DeviceAdapterIdUndefined{};
}
......
......@@ -234,10 +234,9 @@ ArrayHandle<T, StorageTagBasic>::PrepareForInPlace(DeviceAdapterTag device)
template <typename T>
template <typename DeviceAdapterTag>
void ArrayHandle<T, StorageTagBasic>::PrepareForDevice(DeviceAdapterTag) const
void ArrayHandle<T, StorageTagBasic>::PrepareForDevice(DeviceAdapterTag device) const
{
DeviceAdapterId devId = DeviceAdapterTraits<DeviceAdapterTag>::GetId();
bool needToRealloc = this->Internals->PrepareForDevice(devId, sizeof(T));
bool needToRealloc = this->Internals->PrepareForDevice(device, sizeof(T));
if (needToRealloc)
{
this->Internals->ExecutionInterface =
......
......@@ -152,9 +152,9 @@ public:
void ReleaseResources() { this->ReleaseResourcesImpl(); }
template <typename DeviceAdapter>
VTKM_CONT bool IsDeviceAdapter(DeviceAdapter) const
VTKM_CONT bool IsDeviceAdapter(DeviceAdapter device) const
{
return this->IsDeviceAdapterImpl(vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId());
return this->IsDeviceAdapterImpl(device);
}
VTKM_CONT
......@@ -255,16 +255,10 @@ protected:
void ReleaseResourcesImpl() { this->Transfer.ReleaseResources(); }
VTKM_CONT
bool IsDeviceAdapterImpl(const DeviceAdapterId& id) const
{
return id == vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
}
bool IsDeviceAdapterImpl(const DeviceAdapterId& id) const { return id == DeviceAdapter(); }
VTKM_CONT
DeviceAdapterId GetDeviceAdapterIdImpl() const
{
return vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId();
}
DeviceAdapterId GetDeviceAdapterIdImpl() const { return DeviceAdapter(); }
private:
ArrayTransferType Transfer;
......
......@@ -37,10 +37,10 @@ class ExecuteIfValidDeviceTag
{
private:
template <typename DeviceAdapter>
using EnableIfValid = std::enable_if<vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
using EnableIfValid = std::enable_if<DeviceAdapter::IsEnabled>;
template <typename DeviceAdapter>
using EnableIfInvalid = std::enable_if<!vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::Valid>;
using EnableIfInvalid = std::enable_if<!DeviceAdapter::IsEnabled>;
public:
explicit ExecuteIfValidDeviceTag(const FunctorType& functor)
......@@ -99,7 +99,7 @@ public:
bool& status,
Args&&... args) const
{
if (vtkm::cont::DeviceAdapterTraits<DeviceAdapter>::GetId() == deviceId)
if (device == deviceId)
{
VTKM_ASSERT(status == false);
this->Functor(device, std::forward<Args>(args)...);
......@@ -126,8 +126,8 @@ VTKM_CONT void FindDeviceAdapterTagAndCall(vtkm::cont::DeviceAdapterId deviceId,
ForEachValidDevice(devices, wrapped, deviceId, status, std::forward<Args>(args)...);
if (!status)
{
std::string msg =
"Device with id " + std::to_string(deviceId) + " is either not in the list or is invalid";
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);
}
}
......
......@@ -33,13 +33,56 @@
#define VTKM_DEVICE_ADAPTER_CUDA 2
#define VTKM_DEVICE_ADAPTER_TBB 3
#define VTKM_DEVICE_ADAPTER_OPENMP 4
//VTKM_DEVICE_ADAPTER_TestAlgorithmGeneral 7
#define VTKM_MAX_DEVICE_ADAPTER_ID 8
#define VTKM_DEVICE_ADAPTER_ANY 127
namespace vtkm
{
namespace cont
{
using DeviceAdapterId = vtkm::Int8;
struct DeviceAdapterId
{