mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
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.
This commit is contained in:
parent
b9082cd803
commit
554bc3d369
31
docs/changelog/add_tryexecuteondevice_function.md
Normal file
31
docs/changelog/add_tryexecuteondevice_function.md
Normal file
@ -0,0 +1,31 @@
|
||||
# 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);
|
||||
}
|
||||
}
|
||||
```
|
41
docs/changelog/deviceadapterid_is_now_a_strong_type.md
Normal file
41
docs/changelog/deviceadapterid_is_now_a_strong_type.md
Normal file
@ -0,0 +1,41 @@
|
||||
#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;
|
||||
};
|
||||
```
|
@ -0,0 +1,45 @@
|
||||
# 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:
|
||||
|
@ -37,13 +37,14 @@ VTKM_CONT_EXPORT void HandleTryExecuteException(vtkm::cont::DeviceAdapterId,
|
||||
vtkm::cont::RuntimeDeviceTracker&);
|
||||
|
||||
template <typename DeviceTag, typename Functor, typename... Args>
|
||||
bool TryExecuteIfValid(std::true_type,
|
||||
DeviceTag tag,
|
||||
Functor&& f,
|
||||
vtkm::cont::RuntimeDeviceTracker& tracker,
|
||||
Args&&... args)
|
||||
inline bool TryExecuteIfValid(std::true_type,
|
||||
DeviceTag tag,
|
||||
Functor&& f,
|
||||
vtkm::cont::DeviceAdapterId devId,
|
||||
vtkm::cont::RuntimeDeviceTracker& tracker,
|
||||
Args&&... args)
|
||||
{
|
||||
if (tracker.CanRunOn(tag))
|
||||
if ((tag == devId || devId == DeviceAdapterIdAny()) && tracker.CanRunOn(tag))
|
||||
{
|
||||
try
|
||||
{
|
||||
@ -52,7 +53,7 @@ bool TryExecuteIfValid(std::true_type,
|
||||
catch (...)
|
||||
{
|
||||
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceTag>;
|
||||
detail::HandleTryExecuteException(Traits::GetId(), Traits::GetName(), tracker);
|
||||
detail::HandleTryExecuteException(tag, Traits::GetName(), tracker);
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,11 +62,12 @@ bool TryExecuteIfValid(std::true_type,
|
||||
}
|
||||
|
||||
template <typename DeviceTag, typename Functor, typename... Args>
|
||||
bool TryExecuteIfValid(std::false_type,
|
||||
DeviceTag,
|
||||
Functor&&,
|
||||
vtkm::cont::RuntimeDeviceTracker&,
|
||||
Args&&...)
|
||||
inline bool TryExecuteIfValid(std::false_type,
|
||||
DeviceTag,
|
||||
Functor&&,
|
||||
vtkm::cont::DeviceAdapterId,
|
||||
vtkm::cont::RuntimeDeviceTracker&,
|
||||
Args&&...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -73,18 +75,19 @@ bool TryExecuteIfValid(std::false_type,
|
||||
struct TryExecuteWrapper
|
||||
{
|
||||
template <typename DeviceTag, typename Functor, typename... Args>
|
||||
void operator()(DeviceTag tag,
|
||||
Functor&& f,
|
||||
vtkm::cont::RuntimeDeviceTracker& tracker,
|
||||
bool& ran,
|
||||
Args&&... args) const
|
||||
inline void operator()(DeviceTag tag,
|
||||
Functor&& f,
|
||||
vtkm::cont::DeviceAdapterId devId,
|
||||
vtkm::cont::RuntimeDeviceTracker& tracker,
|
||||
bool& ran,
|
||||
Args&&... args) const
|
||||
{
|
||||
if (!ran)
|
||||
{
|
||||
using DeviceTraits = vtkm::cont::DeviceAdapterTraits<DeviceTag>;
|
||||
ran = TryExecuteIfValid(std::integral_constant<bool, DeviceTraits::Valid>(),
|
||||
ran = TryExecuteIfValid(std::integral_constant<bool, DeviceTag::IsEnabled>(),
|
||||
tag,
|
||||
std::forward<Functor>(f),
|
||||
devId,
|
||||
std::forward<decltype(tracker)>(tracker),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
@ -92,29 +95,40 @@ struct TryExecuteWrapper
|
||||
};
|
||||
|
||||
template <typename Functor, typename DeviceList, typename... Args>
|
||||
VTKM_CONT bool TryExecuteImpl(Functor&& functor,
|
||||
std::true_type,
|
||||
std::true_type,
|
||||
vtkm::cont::RuntimeDeviceTracker& tracker,
|
||||
DeviceList list,
|
||||
Args&&... args)
|
||||
inline bool TryExecuteImpl(vtkm::cont::DeviceAdapterId devId,
|
||||
Functor&& functor,
|
||||
std::true_type,
|
||||
std::true_type,
|
||||
vtkm::cont::RuntimeDeviceTracker& tracker,
|
||||
DeviceList list,
|
||||
Args&&... args)
|
||||
{
|
||||
bool success = false;
|
||||
detail::TryExecuteWrapper task;
|
||||
vtkm::ListForEach(
|
||||
task, list, std::forward<Functor>(functor), tracker, success, std::forward<Args>(args)...);
|
||||
TryExecuteWrapper task;
|
||||
vtkm::ListForEach(task,
|
||||
list,
|
||||
std::forward<Functor>(functor),
|
||||
devId,
|
||||
tracker,
|
||||
success,
|
||||
std::forward<Args>(args)...);
|
||||
return success;
|
||||
}
|
||||
|
||||
template <typename Functor, typename... Args>
|
||||
VTKM_CONT bool TryExecuteImpl(Functor&& functor, std::false_type, std::false_type, Args&&... args)
|
||||
inline bool TryExecuteImpl(vtkm::cont::DeviceAdapterId devId,
|
||||
Functor&& functor,
|
||||
std::false_type,
|
||||
std::false_type,
|
||||
Args&&... args)
|
||||
{
|
||||
bool success = false;
|
||||
auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
|
||||
detail::TryExecuteWrapper task;
|
||||
TryExecuteWrapper task;
|
||||
vtkm::ListForEach(task,
|
||||
VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG(),
|
||||
std::forward<Functor>(functor),
|
||||
devId,
|
||||
tracker,
|
||||
success,
|
||||
std::forward<Args>(args)...);
|
||||
@ -122,13 +136,15 @@ VTKM_CONT bool TryExecuteImpl(Functor&& functor, std::false_type, std::false_typ
|
||||
}
|
||||
|
||||
template <typename Functor, typename Arg1, typename... Args>
|
||||
VTKM_CONT bool TryExecuteImpl(Functor&& functor,
|
||||
std::true_type t,
|
||||
std::false_type,
|
||||
Arg1&& arg1,
|
||||
Args&&... args)
|
||||
inline bool TryExecuteImpl(vtkm::cont::DeviceAdapterId devId,
|
||||
Functor&& functor,
|
||||
std::true_type t,
|
||||
std::false_type,
|
||||
Arg1&& arg1,
|
||||
Args&&... args)
|
||||
{
|
||||
return TryExecuteImpl(std::forward<Functor>(functor),
|
||||
return TryExecuteImpl(devId,
|
||||
std::forward<Functor>(functor),
|
||||
t,
|
||||
t,
|
||||
std::forward<Arg1>(arg1),
|
||||
@ -137,14 +153,16 @@ VTKM_CONT bool TryExecuteImpl(Functor&& functor,
|
||||
}
|
||||
|
||||
template <typename Functor, typename Arg1, typename... Args>
|
||||
VTKM_CONT bool TryExecuteImpl(Functor&& functor,
|
||||
std::false_type,
|
||||
std::true_type t,
|
||||
Arg1&& arg1,
|
||||
Args&&... args)
|
||||
inline bool TryExecuteImpl(vtkm::cont::DeviceAdapterId devId,
|
||||
Functor&& functor,
|
||||
std::false_type,
|
||||
std::true_type t,
|
||||
Arg1&& arg1,
|
||||
Args&&... args)
|
||||
{
|
||||
auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
|
||||
return TryExecuteImpl(std::forward<Functor>(functor),
|
||||
return TryExecuteImpl(devId,
|
||||
std::forward<Functor>(functor),
|
||||
t,
|
||||
t,
|
||||
tracker,
|
||||
@ -155,9 +173,125 @@ VTKM_CONT bool TryExecuteImpl(Functor&& functor,
|
||||
} // namespace detail
|
||||
|
||||
///@{
|
||||
/// \brief Try to execute a functor on a list of devices until one succeeds.
|
||||
/// \brief Try to execute a functor on a specific device selected at runtime.
|
||||
///
|
||||
/// This function takes a functor and a \c DeviceAdapterId which represents a
|
||||
/// specific device to attempt to run on at runtime. It also optionally accepts
|
||||
/// the following parameters:
|
||||
/// - A set of devices to compile support for
|
||||
/// - \c RuntimeDeviceTracker which holds which devices have been enabled at runtime, and
|
||||
/// records any functor execution failures
|
||||
///
|
||||
/// It then iterates over the set of devices finding which one matches the provided
|
||||
/// adapter Id and is also enabled in the runtime. The function will return true
|
||||
/// only if the device adapter was valid, and the task was successfully run.
|
||||
/// The optional \c RuntimeDeviceTracker allows for monitoring for certain
|
||||
/// failures across calls to TryExecute and skip trying devices with a history of failure.
|
||||
///
|
||||
/// The TryExecuteOnDevice is also able to perfectly forward arbitrary arguments onto the functor.
|
||||
/// These arguments must be placed after the optional \c RuntimeDeviceTracker, and device adapter
|
||||
/// list and will passed to the functor in the same order as listed.
|
||||
///
|
||||
/// The functor must implement the function call operator ( \c operator() ) with a return type of
|
||||
/// \c bool and 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. The functor call
|
||||
/// operator must also take at least one argument being the required \c DeviceAdapterTag to use.
|
||||
///
|
||||
/// \code{.cpp}
|
||||
/// struct TryCallExample
|
||||
/// {
|
||||
/// template<typename DeviceList>
|
||||
/// bool operator()(DeviceList tags, int) const
|
||||
/// {
|
||||
/// return true;
|
||||
/// }
|
||||
/// };
|
||||
///
|
||||
///
|
||||
/// // Execute only on the device which corresponds to devId
|
||||
/// // Will not execute all if devId is
|
||||
/// vtkm::cont::TryExecuteOnDevice(devId, TryCallExample(), int{42});
|
||||
///
|
||||
/// // Executing on a specific deviceID with a runtime tracker
|
||||
/// auto tracker = vtkm::cont::GetGlobalRuntimeDeviceTracker();
|
||||
/// vtkm::cont::TryExecute(devId, TryCallExample(), tracker, int{42});
|
||||
///
|
||||
/// \endcode
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// If no \c RuntimeDeviceTracker specified, then \c GetGlobalRuntimeDeviceTracker()
|
||||
/// is used.
|
||||
template <typename Functor>
|
||||
VTKM_CONT bool TryExecuteOnDevice(vtkm::cont::DeviceAdapterId devId, Functor&& functor)
|
||||
{
|
||||
//we haven't been passed either a runtime tracker or a device list
|
||||
return detail::TryExecuteImpl(
|
||||
devId, std::forward<Functor>(functor), std::false_type{}, std::false_type{});
|
||||
}
|
||||
template <typename Functor, typename Arg1>
|
||||
VTKM_CONT bool TryExecuteOnDevice(vtkm::cont::DeviceAdapterId devId, Functor&& functor, Arg1&& arg1)
|
||||
{
|
||||
//determine if we are being passed a device adapter or runtime tracker as our argument
|
||||
using is_deviceAdapter = typename std::is_base_of<vtkm::detail::ListRoot, Arg1>::type;
|
||||
using is_tracker = typename std::is_base_of<vtkm::cont::RuntimeDeviceTracker,
|
||||
typename std::remove_reference<Arg1>::type>::type;
|
||||
|
||||
return detail::TryExecuteImpl(devId,
|
||||
std::forward<Functor>(functor),
|
||||
is_tracker{},
|
||||
is_deviceAdapter{},
|
||||
std::forward<Arg1>(arg1));
|
||||
}
|
||||
template <typename Functor, typename Arg1, typename Arg2, typename... Args>
|
||||
VTKM_CONT bool TryExecuteOnDevice(vtkm::cont::DeviceAdapterId devId,
|
||||
Functor&& functor,
|
||||
Arg1&& arg1,
|
||||
Arg2&& arg2,
|
||||
Args&&... args)
|
||||
{
|
||||
//So arg1 can be runtime or device adapter
|
||||
//if arg1 is runtime, we need to see if arg2 is device adapter
|
||||
using is_arg1_tracker =
|
||||
typename std::is_base_of<vtkm::cont::RuntimeDeviceTracker,
|
||||
typename std::remove_reference<Arg1>::type>::type;
|
||||
using is_arg2_devicelist = typename std::is_base_of<vtkm::detail::ListRoot, Arg2>::type;
|
||||
|
||||
//We now know what of three states we are currently at
|
||||
using has_runtime_and_deviceAdapter =
|
||||
brigand::bool_<is_arg1_tracker::value && is_arg2_devicelist::value>;
|
||||
using has_just_runtime = brigand::bool_<is_arg1_tracker::value && !is_arg2_devicelist::value>;
|
||||
using has_just_devicelist = typename std::is_base_of<vtkm::detail::ListRoot, Arg1>::type;
|
||||
|
||||
//With this information we can now compute if we have a runtime tracker and/or
|
||||
//the device adapter and enable the correct flags
|
||||
using first_true =
|
||||
brigand::bool_<has_runtime_and_deviceAdapter::value || has_just_runtime::value>;
|
||||
using second_true =
|
||||
brigand::bool_<has_runtime_and_deviceAdapter::value || has_just_devicelist::value>;
|
||||
|
||||
return detail::TryExecuteImpl(devId,
|
||||
functor,
|
||||
first_true{},
|
||||
second_true{},
|
||||
std::forward<Arg1>(arg1),
|
||||
std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
//@} //block doxygen all TryExecuteOnDevice functions
|
||||
|
||||
///@{
|
||||
/// \brief Try to execute a functor on a set of devices until one succeeds.
|
||||
///
|
||||
/// This function takes a functor and optionally the following:
|
||||
/// - A set of devices to compile support for
|
||||
/// - \c RuntimeDeviceTracker which holds which devices have been enabled at runtime, and
|
||||
/// records any functor execution failures
|
||||
///
|
||||
/// This function takes a functor and optionally a list of devices and \c RuntimeDeviceTracker.
|
||||
/// It then tries to run the functor for each device (in the order given in the list) until the
|
||||
/// execution succeeds. The optional \c RuntimeDeviceTracker allows for monitoring for certain
|
||||
/// failures across calls to TryExecute and skip trying devices with a history of failure.
|
||||
@ -182,7 +316,7 @@ VTKM_CONT bool TryExecuteImpl(Functor&& functor,
|
||||
/// };
|
||||
///
|
||||
///
|
||||
/// // Executing without a runtime tracker or device list
|
||||
/// // Executing without a runtime tracker, deviceId, or device list
|
||||
/// vtkm::cont::TryExecute(TryCallExample(), int{42});
|
||||
///
|
||||
/// // Executing with a runtime tracker
|
||||
@ -206,53 +340,13 @@ VTKM_CONT bool TryExecuteImpl(Functor&& functor,
|
||||
///
|
||||
/// If no \c RuntimeDeviceTracker specified, then \c GetGlobalRuntimeDeviceTracker()
|
||||
/// is used.
|
||||
template <typename Functor>
|
||||
VTKM_CONT bool TryExecute(Functor&& functor)
|
||||
template <typename Functor, typename... Args>
|
||||
VTKM_CONT bool TryExecute(Functor&& functor, Args&&... args)
|
||||
{
|
||||
//we haven't been passed either a runtime tracker or a device list
|
||||
return detail::TryExecuteImpl(functor, std::false_type{}, std::false_type{});
|
||||
return TryExecuteOnDevice(
|
||||
vtkm::cont::DeviceAdapterIdAny(), std::forward<Functor>(functor), std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Functor, typename Arg1>
|
||||
VTKM_CONT bool TryExecute(Functor&& functor, Arg1&& arg1)
|
||||
{
|
||||
//determine if we are being passed a device adapter or runtime tracker as our argument
|
||||
using is_deviceAdapter = typename std::is_base_of<vtkm::detail::ListRoot, Arg1>::type;
|
||||
using is_tracker = typename std::is_base_of<vtkm::cont::RuntimeDeviceTracker,
|
||||
typename std::remove_reference<Arg1>::type>::type;
|
||||
|
||||
return detail::TryExecuteImpl(
|
||||
functor, is_tracker{}, is_deviceAdapter{}, std::forward<Arg1>(arg1));
|
||||
}
|
||||
template <typename Functor, typename Arg1, typename Arg2, typename... Args>
|
||||
VTKM_CONT bool TryExecute(Functor&& functor, Arg1&& arg1, Arg2&& arg2, Args&&... args)
|
||||
{
|
||||
//So arg1 can be runtime or device adapter
|
||||
//if arg1 is runtime, we need to see if arg2 is device adapter
|
||||
using is_arg1_tracker =
|
||||
typename std::is_base_of<vtkm::cont::RuntimeDeviceTracker,
|
||||
typename std::remove_reference<Arg1>::type>::type;
|
||||
using is_arg2_devicelist = typename std::is_base_of<vtkm::detail::ListRoot, Arg2>::type;
|
||||
|
||||
//We now know what of three states we are currently at
|
||||
using has_runtime_and_deviceAdapter =
|
||||
brigand::bool_<is_arg1_tracker::value && is_arg2_devicelist::value>;
|
||||
using has_just_runtime = brigand::bool_<is_arg1_tracker::value && !is_arg2_devicelist::value>;
|
||||
using has_just_devicelist = typename std::is_base_of<vtkm::detail::ListRoot, Arg1>::type;
|
||||
|
||||
//With this information we can now compute if we have a runtime tracker and/or
|
||||
//the device adapter and enable the correct flags
|
||||
using first_true =
|
||||
brigand::bool_<has_runtime_and_deviceAdapter::value || has_just_runtime::value>;
|
||||
using second_true =
|
||||
brigand::bool_<has_runtime_and_deviceAdapter::value || has_just_devicelist::value>;
|
||||
|
||||
return detail::TryExecuteImpl(functor,
|
||||
first_true{},
|
||||
second_true{},
|
||||
std::forward<Arg1>(arg1),
|
||||
std::forward<Arg2>(arg2),
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//@} //block doxygen all TryExecute functions
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
// Represents when using TryExecute that the functor
|
||||
// can be executed on any device instead of a specific
|
||||
// one
|
||||
struct DeviceAdapterIdAny : DeviceAdapterId
|
||||
{
|
||||
constexpr DeviceAdapterIdAny()
|
||||
: DeviceAdapterId(127)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct DeviceAdapterIdUndefined : DeviceAdapterId
|
||||
{
|
||||
constexpr DeviceAdapterIdUndefined()
|
||||
: DeviceAdapterId(VTKM_DEVICE_ADAPTER_UNDEFINED)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
using DeviceAdapterNameType = std::string;
|
||||
|
||||
template <typename DeviceAdapter>
|
||||
@ -55,15 +98,18 @@ struct DeviceAdapterTraits;
|
||||
{ \
|
||||
namespace cont \
|
||||
{ \
|
||||
struct VTKM_ALWAYS_EXPORT DeviceAdapterTag##Name \
|
||||
struct VTKM_ALWAYS_EXPORT DeviceAdapterTag##Name : DeviceAdapterId \
|
||||
{ \
|
||||
constexpr DeviceAdapterTag##Name() \
|
||||
: DeviceAdapterId(Id) \
|
||||
{ \
|
||||
} \
|
||||
static constexpr bool IsEnabled = true; \
|
||||
}; \
|
||||
template <> \
|
||||
struct DeviceAdapterTraits<vtkm::cont::DeviceAdapterTag##Name> \
|
||||
{ \
|
||||
static DeviceAdapterId GetId() { return DeviceAdapterId(Id); } \
|
||||
static DeviceAdapterNameType GetName() { return DeviceAdapterNameType(#Name); } \
|
||||
static constexpr bool Valid = true; \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
@ -76,15 +122,18 @@ struct DeviceAdapterTraits;
|
||||
{ \
|
||||
namespace cont \
|
||||
{ \
|
||||
struct VTKM_ALWAYS_EXPORT DeviceAdapterTag##Name \
|
||||
struct VTKM_ALWAYS_EXPORT DeviceAdapterTag##Name : DeviceAdapterId \
|
||||
{ \
|
||||
constexpr DeviceAdapterTag##Name() \
|
||||
: DeviceAdapterId(Id) \
|
||||
{ \
|
||||
} \
|
||||
static constexpr bool IsEnabled = false; \
|
||||
}; \
|
||||
template <> \
|
||||
struct DeviceAdapterTraits<vtkm::cont::DeviceAdapterTag##Name> \
|
||||
{ \
|
||||
static DeviceAdapterId GetId() { return DeviceAdapterId(Id); } \
|
||||
static DeviceAdapterNameType GetName() { return DeviceAdapterNameType(#Name); } \
|
||||
static constexpr bool Valid = false; \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
@ -95,7 +144,8 @@ struct DeviceAdapterTraits;
|
||||
/// elsewhere in the code when a mistake is made.)
|
||||
///
|
||||
#define VTKM_IS_DEVICE_ADAPTER_TAG(tag) \
|
||||
VTKM_STATIC_ASSERT_MSG(::vtkm::cont::DeviceAdapterTraits<tag>::Valid, \
|
||||
"Provided type is not a valid VTK-m device adapter tag.")
|
||||
static_assert(std::is_base_of<vtkm::cont::DeviceAdapterId, tag>::value && \
|
||||
!std::is_same<vtkm::cont::DeviceAdapterId, tag>::value, \
|
||||
"Provided type is not a valid VTK-m device adapter tag.")
|
||||
|
||||
#endif //vtk_m_cont_internal_DeviceAdapterTag_h
|
||||
|
@ -25,8 +25,7 @@ namespace cont
|
||||
{
|
||||
VTKM_CONT bool DeviceAdapterRuntimeDetector<vtkm::cont::DeviceAdapterTagOpenMP>::Exists() const
|
||||
{
|
||||
using DeviceAdapterTraits = vtkm::cont::DeviceAdapterTraits<vtkm::cont::DeviceAdapterTagOpenMP>;
|
||||
return DeviceAdapterTraits::Valid;
|
||||
return vtkm::cont::DeviceAdapterTagOpenMP::IsEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ namespace cont
|
||||
{
|
||||
VTKM_CONT bool DeviceAdapterRuntimeDetector<vtkm::cont::DeviceAdapterTagSerial>::Exists() const
|
||||
{
|
||||
using DeviceAdapterTraits = vtkm::cont::DeviceAdapterTraits<vtkm::cont::DeviceAdapterTagSerial>;
|
||||
return DeviceAdapterTraits::Valid;
|
||||
return vtkm::cont::DeviceAdapterTagSerial::IsEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,8 +24,7 @@ namespace cont
|
||||
{
|
||||
VTKM_CONT bool DeviceAdapterRuntimeDetector<vtkm::cont::DeviceAdapterTagTBB>::Exists() const
|
||||
{
|
||||
using DeviceAdapterTraits = vtkm::cont::DeviceAdapterTraits<vtkm::cont::DeviceAdapterTagTBB>;
|
||||
return DeviceAdapterTraits::Valid;
|
||||
return vtkm::cont::DeviceAdapterTagTBB::IsEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include <vtkm/worklet/WorkletMapField.h>
|
||||
|
||||
#include <vtkm/cont/ArrayHandleExtractComponent.h>
|
||||
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
#include <algorithm>
|
||||
@ -406,7 +405,7 @@ private:
|
||||
VTKM_TEST_ASSERT(a1 == a2, "Shallow copied array not equal.");
|
||||
VTKM_TEST_ASSERT(!(a1 != a2), "Shallow copied array not equal.");
|
||||
|
||||
a1.PrepareForInPlace(DeviceAdapterTagSerial());
|
||||
a1.PrepareForInPlace(DeviceAdapterTag());
|
||||
VTKM_TEST_ASSERT(a1 == a2, "Shallow copied array not equal.");
|
||||
VTKM_TEST_ASSERT(!(a1 != a2), "Shallow copied array not equal.");
|
||||
}
|
||||
|
@ -471,14 +471,17 @@ private:
|
||||
std::cout << "-------------------------------------------" << std::endl;
|
||||
std::cout << "Testing device adapter tag" << std::endl;
|
||||
|
||||
constexpr DeviceAdapterTag deviceTag;
|
||||
constexpr vtkm::cont::DeviceAdapterTagError errorTag;
|
||||
|
||||
VTKM_TEST_ASSERT(deviceTag.GetValue() == deviceTag.GetValue(),
|
||||
"Device adapter Id does not equal itself.");
|
||||
VTKM_TEST_ASSERT(deviceTag.GetValue() != errorTag.GetValue(),
|
||||
"Device adapter Id not distinguishable from others.");
|
||||
|
||||
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
|
||||
using ErrorTraits = vtkm::cont::DeviceAdapterTraits<vtkm::cont::DeviceAdapterTagError>;
|
||||
|
||||
VTKM_TEST_ASSERT(Traits::GetId() == Traits::GetId(),
|
||||
"Device adapter Id does not equal itself.");
|
||||
VTKM_TEST_ASSERT(Traits::GetId() != ErrorTraits::GetId(),
|
||||
"Device adapter Id not distinguishable from others.");
|
||||
|
||||
VTKM_TEST_ASSERT(Traits::GetName() == Traits::GetName(),
|
||||
"Device adapter Name does not equal itself.");
|
||||
VTKM_TEST_ASSERT(Traits::GetName() != ErrorTraits::GetName(),
|
||||
|
@ -116,11 +116,11 @@ struct ExecutionPortalFactoryBasic<T, DeviceAdapterTagTestAlgorithmGeneral>
|
||||
{
|
||||
using Superclass = ExecutionPortalFactoryBasicShareWithControl<T>;
|
||||
|
||||
using typename Superclass::ValueType;
|
||||
using typename Superclass::PortalType;
|
||||
using typename Superclass::PortalConstType;
|
||||
using Superclass::CreatePortal;
|
||||
using Superclass::CreatePortalConst;
|
||||
using typename Superclass::PortalConstType;
|
||||
using typename Superclass::PortalType;
|
||||
using typename Superclass::ValueType;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
@ -38,7 +38,7 @@ void detect_if_exists(DeviceAdapterTag tag)
|
||||
{
|
||||
using DeviceAdapterTraits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
|
||||
std::cout << "testing runtime support for " << DeviceAdapterTraits::GetName() << std::endl;
|
||||
DoesExist<DeviceAdapterTraits::Valid> exist;
|
||||
DoesExist<tag.IsEnabled> exist;
|
||||
exist.Exist(tag);
|
||||
}
|
||||
|
||||
|
@ -38,25 +38,40 @@ namespace interop
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename ArrayT>
|
||||
struct PrepareForInteropFunctor
|
||||
struct TransferToOpenGL
|
||||
{
|
||||
ArrayT& Array;
|
||||
PrepareForInteropFunctor(ArrayT& array)
|
||||
: Array(array)
|
||||
template <typename DeviceAdapterTag, typename ValueType, typename StorageTag>
|
||||
VTKM_CONT bool operator()(DeviceAdapterTag,
|
||||
const vtkm::cont::ArrayHandle<ValueType, StorageTag>& handle,
|
||||
BufferState& state) const
|
||||
{
|
||||
}
|
||||
|
||||
template <typename DeviceAdapterTag>
|
||||
bool operator()(DeviceAdapterTag) const
|
||||
{
|
||||
using Traits = vtkm::cont::DeviceAdapterTraits<DeviceAdapterTag>;
|
||||
this->Array.PrepareForInput(DeviceAdapterTag());
|
||||
return this->Array.GetDeviceAdapterId() == Traits::GetId();
|
||||
vtkm::interop::internal::TransferToOpenGL<ValueType, DeviceAdapterTag> toGL(state);
|
||||
return toGL.Transfer(handle);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// \brief Manages transferring an ArrayHandle to opengl .
|
||||
///
|
||||
/// \c TransferToOpenGL manages to transfer the contents of an ArrayHandle
|
||||
/// to OpenGL as efficiently as possible. Will use the given \p state to determine
|
||||
/// what buffer handle to use, and the type to bind the buffer handle too.
|
||||
/// Lastly state also holds on to per backend resources that allow for efficient
|
||||
/// updating to open gl.
|
||||
///
|
||||
/// This function keeps the buffer as the active buffer of the input type.
|
||||
///
|
||||
///
|
||||
template <typename ValueType, class StorageTag, class DeviceAdapterTag>
|
||||
VTKM_CONT void TransferToOpenGL(vtkm::cont::ArrayHandle<ValueType, StorageTag> handle,
|
||||
BufferState& state,
|
||||
DeviceAdapterTag)
|
||||
{
|
||||
vtkm::interop::internal::TransferToOpenGL<ValueType, DeviceAdapterTag> toGL(state);
|
||||
toGL.Transfer(handle);
|
||||
}
|
||||
|
||||
/// \brief Manages transferring an ArrayHandle to opengl .
|
||||
///
|
||||
/// \c TransferToOpenGL manages to transfer the contents of an ArrayHandle
|
||||
@ -70,60 +85,22 @@ struct PrepareForInteropFunctor
|
||||
///
|
||||
/// This function will throw exceptions if the transfer wasn't possible
|
||||
///
|
||||
template <typename ValueType, class StorageTag, class DeviceAdapterTag>
|
||||
VTKM_CONT void TransferToOpenGL(vtkm::cont::ArrayHandle<ValueType, StorageTag> handle,
|
||||
BufferState& state,
|
||||
DeviceAdapterTag)
|
||||
{
|
||||
vtkm::interop::internal::TransferToOpenGL<ValueType, DeviceAdapterTag> toGL(state);
|
||||
return toGL.Transfer(handle);
|
||||
}
|
||||
|
||||
/// Dispatch overload for TransferToOpenGL that deduces the DeviceAdapter for
|
||||
/// the given ArrayHandle.
|
||||
///
|
||||
/// \overload
|
||||
///
|
||||
template <typename ValueType, class StorageTag>
|
||||
template <typename ValueType, typename StorageTag>
|
||||
VTKM_CONT void TransferToOpenGL(vtkm::cont::ArrayHandle<ValueType, StorageTag> handle,
|
||||
BufferState& state)
|
||||
{
|
||||
|
||||
vtkm::cont::DeviceAdapterId devId = handle.GetDeviceAdapterId();
|
||||
|
||||
if (devId == VTKM_DEVICE_ADAPTER_UNDEFINED)
|
||||
bool success = vtkm::cont::TryExecuteOnDevice(devId, TransferToOpenGL, handle, state);
|
||||
if (!success)
|
||||
{
|
||||
using ArrayT = vtkm::cont::ArrayHandle<ValueType, StorageTag>;
|
||||
using Functor = detail::PrepareForInteropFunctor<ArrayT>;
|
||||
// Undefined device means that the array is not in an execution environment.
|
||||
// In this case, call PrepareForInput using the devices in the tracker
|
||||
// to move the data onto a device. This is required for a CUDA usecase
|
||||
// where a device pointer is set as control memory to reuse an already
|
||||
// allocated buffer. PrepareForInput on CUDA will detect this and set the
|
||||
// execution pointer to match the control pointer.
|
||||
vtkm::cont::TryExecute(Functor(handle));
|
||||
devId = handle.GetDeviceAdapterId();
|
||||
//Generally we are here because the devId is undefined
|
||||
//or for some reason the last executed device is now disabled
|
||||
success = vtkm::cont::TryExecute(TransferToOpenGL, handle, state);
|
||||
}
|
||||
|
||||
switch (devId)
|
||||
if (!success)
|
||||
{
|
||||
case VTKM_DEVICE_ADAPTER_SERIAL:
|
||||
TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagSerial());
|
||||
break;
|
||||
|
||||
#ifdef VTKM_ENABLE_TBB
|
||||
case VTKM_DEVICE_ADAPTER_TBB:
|
||||
TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagTBB());
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef VTKM_CUDA
|
||||
case VTKM_DEVICE_ADAPTER_CUDA:
|
||||
TransferToOpenGL(handle, state, vtkm::cont::DeviceAdapterTagCuda());
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
throw vtkm::cont::ErrorBadValue("Unknown device id.");
|
||||
throw vtkm::cont::ErrorBadValue("Unknown device id.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -213,10 +213,10 @@ public:
|
||||
|
||||
//set up stack size for cuda environment
|
||||
#ifdef VTKM_CUDA
|
||||
using DeviceAdapterTraits = vtkm::cont::DeviceAdapterTraits<DeviceAdapter>;
|
||||
constexpr DeviceAdapter deviceId;
|
||||
std::size_t stackSizeBackup;
|
||||
(void)stackSizeBackup;
|
||||
if (DeviceAdapterTraits::GetId() == VTKM_DEVICE_ADAPTER_CUDA)
|
||||
if (deviceId.GetValue() == VTKM_DEVICE_ADAPTER_CUDA)
|
||||
{
|
||||
cudaDeviceGetLimit(&stackSizeBackup, cudaLimitStackSize);
|
||||
cudaDeviceSetLimit(cudaLimitStackSize, 1024 * 16);
|
||||
@ -230,7 +230,7 @@ public:
|
||||
qc_Handle, pointId_Handle, splitId_Handle, coordi_Handle, nnId_Handle, nnDis_Handle);
|
||||
|
||||
#ifdef VTKM_CUDA
|
||||
if (DeviceAdapterTraits::GetId() == VTKM_DEVICE_ADAPTER_CUDA)
|
||||
if (deviceId.GetValue() == VTKM_DEVICE_ADAPTER_CUDA)
|
||||
{
|
||||
cudaDeviceSetLimit(cudaLimitStackSize, stackSizeBackup);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user