mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-08 13:23:51 +00:00
Deprecate ArrayHandle::GetDeviceAdapterId
This method is a remenant of when `ArrayHandle` could only store data on one device at a time. It is now capable of storing data on any number of devices (as well as the host), so asking for "the" device no longer makes sense. Thus, this method is deprecated in favor of `ArrayHandle::IsOnDevice`. This deprecation leads to fixing some older functionality that still assumed data could only be on one device at a time. Fixes #592.
This commit is contained in:
parent
f34b432832
commit
34615a9858
@ -69,14 +69,29 @@ struct BitFieldToUnorderedSetFunctor
|
||||
|
||||
struct CopyFunctor
|
||||
{
|
||||
template <typename T, typename S, typename... Args>
|
||||
VTKM_CONT bool InputArrayOnDevice(vtkm::cont::DeviceAdapterId device,
|
||||
const vtkm::cont::ArrayHandle<T, S>& input,
|
||||
Args&&...) const
|
||||
{
|
||||
return input.IsOnDevice(device);
|
||||
}
|
||||
|
||||
template <typename Device, typename... Args>
|
||||
VTKM_CONT bool operator()(Device, Args&&... args) const
|
||||
VTKM_CONT bool operator()(Device device, bool useExistingDevice, Args&&... args) const
|
||||
{
|
||||
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Copy(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
if (!useExistingDevice || this->InputArrayOnDevice(device, std::forward<Args>(args)...))
|
||||
{
|
||||
vtkm::cont::Token token;
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Copy(
|
||||
PrepareArgForExec<Device>(std::forward<Args>(args), token)...);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -399,14 +414,14 @@ struct Algorithm
|
||||
// If we can use any device, prefer to use source's already loaded device.
|
||||
if (devId == vtkm::cont::DeviceAdapterTagAny())
|
||||
{
|
||||
bool isCopied = vtkm::cont::TryExecuteOnDevice(
|
||||
input.GetDeviceAdapterId(), detail::CopyFunctor(), input, output);
|
||||
bool isCopied =
|
||||
vtkm::cont::TryExecuteOnDevice(devId, detail::CopyFunctor(), true, input, output);
|
||||
if (isCopied)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return vtkm::cont::TryExecuteOnDevice(devId, detail::CopyFunctor(), input, output);
|
||||
return vtkm::cont::TryExecuteOnDevice(devId, detail::CopyFunctor(), false, input, output);
|
||||
}
|
||||
template <typename T, typename U, class CIn, class COut>
|
||||
VTKM_CONT static void Copy(const vtkm::cont::ArrayHandle<T, CIn>& input,
|
||||
|
@ -33,34 +33,12 @@ namespace detail
|
||||
{
|
||||
|
||||
// Element-wise copy.
|
||||
// TODO: Remove last argument once ArryHandleNewStyle becomes ArrayHandle
|
||||
template <typename InArrayType, typename OutArrayType>
|
||||
void ArrayCopyWithAlgorithm(const InArrayType& source, OutArrayType& destination)
|
||||
{
|
||||
// Find the device that already has a copy of the data:
|
||||
vtkm::cont::DeviceAdapterId devId = source.GetDeviceAdapterId();
|
||||
|
||||
// If the data is not on any device, let the runtime tracker pick an available
|
||||
// parallel copy algorithm.
|
||||
if (devId.GetValue() == VTKM_DEVICE_ADAPTER_UNDEFINED)
|
||||
{
|
||||
devId = vtkm::cont::make_DeviceAdapterId(VTKM_DEVICE_ADAPTER_ANY);
|
||||
}
|
||||
|
||||
bool success = vtkm::cont::Algorithm::Copy(devId, source, destination);
|
||||
|
||||
if (!success && devId.GetValue() != VTKM_DEVICE_ADAPTER_ANY)
|
||||
{ // Retry on any device if the first attempt failed.
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Error,
|
||||
"Failed to run ArrayCopy on device '" << devId.GetName()
|
||||
<< "'. Retrying on any device.");
|
||||
success = vtkm::cont::Algorithm::Copy(vtkm::cont::DeviceAdapterTagAny{}, source, destination);
|
||||
}
|
||||
|
||||
if (!success)
|
||||
{
|
||||
throw vtkm::cont::ErrorExecution("Failed to run ArrayCopy on any device.");
|
||||
}
|
||||
// Current implementation of Algorithm::Copy will first try to copy on devices where the
|
||||
// data is already available.
|
||||
vtkm::cont::Algorithm::Copy(source, destination);
|
||||
}
|
||||
|
||||
// TODO: Remove last argument once ArryHandleNewStyle becomes ArrayHandle
|
||||
|
@ -26,6 +26,33 @@ namespace vtkm
|
||||
namespace cont
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct ArrayGetValuesFunctor
|
||||
{
|
||||
template <typename Device, typename IdsArray, typename DataArray, typename OutputArray>
|
||||
VTKM_CONT bool operator()(Device,
|
||||
const IdsArray& ids,
|
||||
const DataArray& data,
|
||||
OutputArray& output) const
|
||||
{
|
||||
// Only get data on a device the data are already on.
|
||||
if (data.IsOnDevice(Device{}))
|
||||
{
|
||||
const auto input = vtkm::cont::make_ArrayHandlePermutation(ids, data);
|
||||
vtkm::cont::DeviceAdapterAlgorithm<Device>::Copy(input, output);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Obtain a small set of values from an ArrayHandle with minimal device
|
||||
/// transfers.
|
||||
///
|
||||
@ -90,25 +117,17 @@ VTKM_CONT void ArrayGetValues(const vtkm::cont::ArrayHandle<vtkm::Id, SIds>& ids
|
||||
{
|
||||
bool copyComplete = false;
|
||||
|
||||
// Find the device that already has a copy of the data:
|
||||
vtkm::cont::DeviceAdapterId devId = data.GetDeviceAdapterId();
|
||||
|
||||
if (devId.GetValue() != VTKM_DEVICE_ADAPTER_UNDEFINED)
|
||||
{ // Data exists on some device -- use it:
|
||||
const auto input = vtkm::cont::make_ArrayHandlePermutation(ids, data);
|
||||
copyComplete = vtkm::cont::Algorithm::Copy(devId, input, output);
|
||||
if (!copyComplete)
|
||||
{ // Retry on any device if the first attempt failed.
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Error,
|
||||
"Failed to run ArrayGetValues on device '"
|
||||
<< devId.GetName() << "'. Falling back to control-side copy.");
|
||||
copyComplete = vtkm::cont::Algorithm::Copy(vtkm::cont::DeviceAdapterTagAny{}, input, output);
|
||||
}
|
||||
// If the data are not already on the host, attempt to copy on the device.
|
||||
if (!data.IsOnHost())
|
||||
{
|
||||
copyComplete = vtkm::cont::TryExecute(detail::ArrayGetValuesFunctor{}, ids, data, output);
|
||||
}
|
||||
|
||||
if (!copyComplete)
|
||||
{ // Fallback to a control-side copy if the device copy fails or if the device
|
||||
// is undefined:
|
||||
// is undefined or if the data were already on the host. In this case, the
|
||||
// best we can do is grab the portals and copy one at a time on the host with
|
||||
// a for loop.
|
||||
const vtkm::Id numVals = ids.GetNumberOfValues();
|
||||
auto idPortal = ids.ReadPortal();
|
||||
auto dataPortal = data.ReadPortal();
|
||||
|
@ -647,10 +647,8 @@ public:
|
||||
/// Note that in a multithreaded environment the validity of this result can
|
||||
/// change.
|
||||
///
|
||||
/// TODO: Deprecate this method in favor of IsOnDevice since the data can be on multiple
|
||||
/// devices at once.
|
||||
VTKM_CONT
|
||||
DeviceAdapterId GetDeviceAdapterId() const
|
||||
VTKM_DEPRECATED(1.7, "Use ArrayHandle::IsOnDevice.") DeviceAdapterId GetDeviceAdapterId() const
|
||||
{
|
||||
return detail::ArrayHandleGetDeviceAdapterId(this->Buffers);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user