2018-10-30 13:49:41 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2018-10-30 13:49:41 +00:00
|
|
|
// 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.
|
|
|
|
//============================================================================
|
|
|
|
#include <vtkm/cont/RuntimeDeviceInformation.h>
|
|
|
|
|
2019-12-07 04:32:36 +00:00
|
|
|
#include <vtkm/List.h>
|
2018-10-30 13:49:41 +00:00
|
|
|
#include <vtkm/cont/DeviceAdapter.h>
|
2019-12-07 04:32:36 +00:00
|
|
|
#include <vtkm/cont/DeviceAdapterList.h>
|
2019-04-03 20:28:31 +00:00
|
|
|
#include <vtkm/cont/DeviceAdapterTag.h>
|
2020-03-26 23:34:18 +00:00
|
|
|
#include <vtkm/cont/ErrorBadDevice.h>
|
2018-10-30 13:49:41 +00:00
|
|
|
|
|
|
|
//Bring in each device adapters runtime class
|
|
|
|
#include <vtkm/cont/cuda/internal/DeviceAdapterRuntimeDetectorCuda.h>
|
2020-06-16 12:54:01 +00:00
|
|
|
#include <vtkm/cont/kokkos/internal/DeviceAdapterRuntimeDetectorKokkos.h>
|
2018-10-30 13:49:41 +00:00
|
|
|
#include <vtkm/cont/openmp/internal/DeviceAdapterRuntimeDetectorOpenMP.h>
|
|
|
|
#include <vtkm/cont/serial/internal/DeviceAdapterRuntimeDetectorSerial.h>
|
|
|
|
#include <vtkm/cont/tbb/internal/DeviceAdapterRuntimeDetectorTBB.h>
|
|
|
|
|
2019-03-15 19:54:42 +00:00
|
|
|
#include <cctype> //for tolower
|
|
|
|
|
|
|
|
namespace
|
2018-10-30 13:49:41 +00:00
|
|
|
{
|
2020-03-26 23:34:18 +00:00
|
|
|
class DeviceAdapterMemoryManagerInvalid
|
|
|
|
: public vtkm::cont::internal::DeviceAdapterMemoryManagerBase
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
VTKM_CONT virtual ~DeviceAdapterMemoryManagerInvalid() override {}
|
|
|
|
|
2020-04-22 19:58:59 +00:00
|
|
|
VTKM_CONT virtual vtkm::cont::internal::BufferInfo Allocate(vtkm::BufferSizeType) const override
|
2020-03-26 23:34:18 +00:00
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
|
|
|
|
}
|
|
|
|
|
2020-04-22 19:58:59 +00:00
|
|
|
VTKM_CONT virtual vtkm::cont::DeviceAdapterId GetDevice() const override
|
2020-03-26 23:34:18 +00:00
|
|
|
{
|
2020-04-22 19:58:59 +00:00
|
|
|
return vtkm::cont::DeviceAdapterTagUndefined{};
|
2020-03-26 23:34:18 +00:00
|
|
|
}
|
|
|
|
|
2020-04-22 19:58:59 +00:00
|
|
|
VTKM_CONT virtual vtkm::cont::internal::BufferInfo CopyHostToDevice(
|
|
|
|
const vtkm::cont::internal::BufferInfo&) const override
|
2020-03-26 23:34:18 +00:00
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
|
|
|
|
}
|
|
|
|
|
2020-06-24 23:27:36 +00:00
|
|
|
VTKM_CONT virtual void CopyHostToDevice(const vtkm::cont::internal::BufferInfo&,
|
|
|
|
const vtkm::cont::internal::BufferInfo&) const override
|
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
|
|
|
|
}
|
|
|
|
|
2020-04-22 19:58:59 +00:00
|
|
|
VTKM_CONT virtual vtkm::cont::internal::BufferInfo CopyDeviceToHost(
|
|
|
|
const vtkm::cont::internal::BufferInfo&) const override
|
2020-03-26 23:34:18 +00:00
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
|
|
|
|
}
|
|
|
|
|
2020-06-24 23:27:36 +00:00
|
|
|
VTKM_CONT virtual void CopyDeviceToHost(const vtkm::cont::internal::BufferInfo&,
|
|
|
|
const vtkm::cont::internal::BufferInfo&) const override
|
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
|
|
|
|
}
|
|
|
|
|
2020-04-22 19:58:59 +00:00
|
|
|
VTKM_CONT virtual vtkm::cont::internal::BufferInfo CopyDeviceToDevice(
|
|
|
|
const vtkm::cont::internal::BufferInfo&) const override
|
2020-03-26 23:34:18 +00:00
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
|
|
|
|
}
|
2020-06-24 23:27:36 +00:00
|
|
|
|
|
|
|
VTKM_CONT virtual void CopyDeviceToDevice(const vtkm::cont::internal::BufferInfo&,
|
|
|
|
const vtkm::cont::internal::BufferInfo&) const override
|
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadDevice("Tried to manage memory on an invalid device.");
|
|
|
|
}
|
2020-03-26 23:34:18 +00:00
|
|
|
};
|
|
|
|
|
2019-03-15 19:54:42 +00:00
|
|
|
struct VTKM_NEVER_EXPORT InitializeDeviceNames
|
2018-10-30 13:49:41 +00:00
|
|
|
{
|
2019-03-15 19:54:42 +00:00
|
|
|
vtkm::cont::DeviceAdapterNameType* Names;
|
|
|
|
vtkm::cont::DeviceAdapterNameType* LowerCaseNames;
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
InitializeDeviceNames(vtkm::cont::DeviceAdapterNameType* names,
|
|
|
|
vtkm::cont::DeviceAdapterNameType* lower)
|
|
|
|
: Names(names)
|
|
|
|
, LowerCaseNames(lower)
|
|
|
|
{
|
|
|
|
std::fill_n(this->Names, VTKM_MAX_DEVICE_ADAPTER_ID, "InvalidDeviceId");
|
|
|
|
std::fill_n(this->LowerCaseNames, VTKM_MAX_DEVICE_ADAPTER_ID, "invaliddeviceid");
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Device>
|
|
|
|
VTKM_CONT void operator()(Device device)
|
|
|
|
{
|
|
|
|
auto lowerCaseFunc = [](char c) {
|
|
|
|
return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
|
|
|
};
|
|
|
|
|
|
|
|
auto id = device.GetValue();
|
|
|
|
|
|
|
|
if (id > 0 && id < VTKM_MAX_DEVICE_ADAPTER_ID)
|
|
|
|
{
|
|
|
|
auto name = vtkm::cont::DeviceAdapterTraits<Device>::GetName();
|
|
|
|
this->Names[id] = name;
|
|
|
|
std::transform(name.begin(), name.end(), name.begin(), lowerCaseFunc);
|
|
|
|
this->LowerCaseNames[id] = name;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-03-26 23:34:18 +00:00
|
|
|
struct VTKM_NEVER_EXPORT InitializeDeviceMemoryManagers
|
|
|
|
{
|
|
|
|
std::unique_ptr<vtkm::cont::internal::DeviceAdapterMemoryManagerBase>* Managers;
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
InitializeDeviceMemoryManagers(
|
|
|
|
std::unique_ptr<vtkm::cont::internal::DeviceAdapterMemoryManagerBase>* managers)
|
|
|
|
: Managers(managers)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Device>
|
|
|
|
VTKM_CONT void CreateManager(Device device, std::true_type)
|
|
|
|
{
|
|
|
|
auto id = device.GetValue();
|
|
|
|
|
|
|
|
if (id > 0 && id < VTKM_MAX_DEVICE_ADAPTER_ID)
|
|
|
|
{
|
|
|
|
auto name = vtkm::cont::DeviceAdapterTraits<Device>::GetName();
|
|
|
|
this->Managers[id].reset(new vtkm::cont::internal::DeviceAdapterMemoryManager<Device>);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Device>
|
|
|
|
VTKM_CONT void CreateManager(Device, std::false_type)
|
|
|
|
{
|
|
|
|
// No manager for invalid devices.
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename Device>
|
|
|
|
VTKM_CONT void operator()(Device device)
|
|
|
|
{
|
|
|
|
this->CreateManager(device, std::integral_constant<bool, device.IsEnabled>{});
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-03-15 19:54:42 +00:00
|
|
|
struct VTKM_NEVER_EXPORT RuntimeDeviceInformationFunctor
|
2018-10-30 13:49:41 +00:00
|
|
|
{
|
|
|
|
bool Exists = false;
|
|
|
|
template <typename DeviceAdapter>
|
2019-03-15 19:54:42 +00:00
|
|
|
VTKM_CONT void operator()(DeviceAdapter, vtkm::cont::DeviceAdapterId device)
|
2018-10-30 13:49:41 +00:00
|
|
|
{
|
|
|
|
if (DeviceAdapter() == device)
|
|
|
|
{
|
|
|
|
this->Exists = vtkm::cont::DeviceAdapterRuntimeDetector<DeviceAdapter>().Exists();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2019-03-15 19:54:42 +00:00
|
|
|
|
2019-04-19 16:38:14 +00:00
|
|
|
class RuntimeDeviceNames
|
2019-03-15 19:54:42 +00:00
|
|
|
{
|
2019-04-19 16:38:14 +00:00
|
|
|
public:
|
2020-03-26 23:34:18 +00:00
|
|
|
static const vtkm::cont::DeviceAdapterNameType& GetDeviceName(vtkm::Int8 id)
|
2019-04-19 16:38:14 +00:00
|
|
|
{
|
|
|
|
return Instance().DeviceNames[id];
|
|
|
|
}
|
|
|
|
|
2020-03-26 23:34:18 +00:00
|
|
|
static const vtkm::cont::DeviceAdapterNameType& GetLowerCaseDeviceName(vtkm::Int8 id)
|
2019-04-19 16:38:14 +00:00
|
|
|
{
|
|
|
|
return Instance().LowerCaseDeviceNames[id];
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static const RuntimeDeviceNames& Instance()
|
|
|
|
{
|
|
|
|
static RuntimeDeviceNames instance;
|
|
|
|
return instance;
|
|
|
|
}
|
2019-03-15 19:54:42 +00:00
|
|
|
|
|
|
|
RuntimeDeviceNames()
|
|
|
|
{
|
|
|
|
InitializeDeviceNames functor(DeviceNames, LowerCaseDeviceNames);
|
2019-12-05 21:38:41 +00:00
|
|
|
vtkm::ListForEach(functor, VTKM_DEFAULT_DEVICE_ADAPTER_LIST());
|
2019-03-15 19:54:42 +00:00
|
|
|
}
|
|
|
|
|
2019-04-19 16:38:14 +00:00
|
|
|
friend struct InitializeDeviceNames;
|
|
|
|
|
2020-03-26 23:34:18 +00:00
|
|
|
vtkm::cont::DeviceAdapterNameType DeviceNames[VTKM_MAX_DEVICE_ADAPTER_ID];
|
|
|
|
vtkm::cont::DeviceAdapterNameType LowerCaseDeviceNames[VTKM_MAX_DEVICE_ADAPTER_ID];
|
|
|
|
};
|
|
|
|
|
|
|
|
class RuntimeDeviceMemoryManagers
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static vtkm::cont::internal::DeviceAdapterMemoryManagerBase& GetDeviceMemoryManager(
|
|
|
|
vtkm::cont::DeviceAdapterId device)
|
|
|
|
{
|
|
|
|
const auto id = device.GetValue();
|
|
|
|
|
|
|
|
if (device.IsValueValid())
|
|
|
|
{
|
|
|
|
auto&& manager = Instance().DeviceMemoryManagers[id];
|
|
|
|
if (manager)
|
|
|
|
{
|
|
|
|
return *manager.get();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Instance().InvalidManager;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Instance().InvalidManager;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
static RuntimeDeviceMemoryManagers& Instance()
|
|
|
|
{
|
|
|
|
static RuntimeDeviceMemoryManagers instance;
|
|
|
|
return instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
RuntimeDeviceMemoryManagers()
|
|
|
|
{
|
|
|
|
InitializeDeviceMemoryManagers functor(this->DeviceMemoryManagers);
|
|
|
|
vtkm::ListForEach(functor, VTKM_DEFAULT_DEVICE_ADAPTER_LIST());
|
|
|
|
}
|
|
|
|
|
|
|
|
friend struct InitializeDeviceMemoryManagers;
|
|
|
|
|
|
|
|
std::unique_ptr<vtkm::cont::internal::DeviceAdapterMemoryManagerBase>
|
|
|
|
DeviceMemoryManagers[VTKM_MAX_DEVICE_ADAPTER_ID];
|
|
|
|
DeviceAdapterMemoryManagerInvalid InvalidManager;
|
2019-03-15 19:54:42 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2020-03-26 23:34:18 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
|
|
|
namespace cont
|
|
|
|
{
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2019-03-15 19:54:42 +00:00
|
|
|
VTKM_CONT
|
|
|
|
DeviceAdapterNameType RuntimeDeviceInformation::GetName(DeviceAdapterId device) const
|
|
|
|
{
|
|
|
|
const auto id = device.GetValue();
|
|
|
|
|
|
|
|
if (device.IsValueValid())
|
|
|
|
{
|
2020-03-26 23:34:18 +00:00
|
|
|
return RuntimeDeviceNames::GetDeviceName(id);
|
2019-03-15 19:54:42 +00:00
|
|
|
}
|
|
|
|
else if (id == VTKM_DEVICE_ADAPTER_UNDEFINED)
|
|
|
|
{
|
|
|
|
return vtkm::cont::DeviceAdapterTraits<vtkm::cont::DeviceAdapterTagUndefined>::GetName();
|
|
|
|
}
|
|
|
|
else if (id == VTKM_DEVICE_ADAPTER_ANY)
|
|
|
|
{
|
|
|
|
return vtkm::cont::DeviceAdapterTraits<vtkm::cont::DeviceAdapterTagAny>::GetName();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Deviceis invalid:
|
2020-03-26 23:34:18 +00:00
|
|
|
return RuntimeDeviceNames::GetDeviceName(0);
|
2019-03-15 19:54:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VTKM_CONT
|
|
|
|
DeviceAdapterId RuntimeDeviceInformation::GetId(DeviceAdapterNameType name) const
|
|
|
|
{
|
|
|
|
// The GetDeviceAdapterId call is case-insensitive so transform the name to be lower case
|
|
|
|
// as that is how we cache the case-insensitive version.
|
|
|
|
auto lowerCaseFunc = [](char c) {
|
|
|
|
return static_cast<char>(std::tolower(static_cast<unsigned char>(c)));
|
|
|
|
};
|
|
|
|
std::transform(name.begin(), name.end(), name.begin(), lowerCaseFunc);
|
|
|
|
|
|
|
|
//lower-case the name here
|
|
|
|
if (name == "any")
|
|
|
|
{
|
|
|
|
return vtkm::cont::DeviceAdapterTagAny{};
|
|
|
|
}
|
|
|
|
else if (name == "undefined")
|
|
|
|
{
|
|
|
|
return vtkm::cont::DeviceAdapterTagUndefined{};
|
|
|
|
}
|
|
|
|
|
|
|
|
for (vtkm::Int8 id = 0; id < VTKM_MAX_DEVICE_ADAPTER_ID; ++id)
|
|
|
|
{
|
2020-03-26 23:34:18 +00:00
|
|
|
if (name == RuntimeDeviceNames::GetLowerCaseDeviceName(id))
|
2019-03-15 19:54:42 +00:00
|
|
|
{
|
|
|
|
return vtkm::cont::make_DeviceAdapterId(id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return vtkm::cont::DeviceAdapterTagUndefined{};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-10-30 13:49:41 +00:00
|
|
|
VTKM_CONT
|
|
|
|
bool RuntimeDeviceInformation::Exists(DeviceAdapterId id) const
|
|
|
|
{
|
2019-05-21 19:15:06 +00:00
|
|
|
if (id == vtkm::cont::DeviceAdapterTagAny{})
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-03-15 19:54:42 +00:00
|
|
|
RuntimeDeviceInformationFunctor functor;
|
2019-12-05 21:38:41 +00:00
|
|
|
vtkm::ListForEach(functor, VTKM_DEFAULT_DEVICE_ADAPTER_LIST(), id);
|
2018-10-30 13:49:41 +00:00
|
|
|
return functor.Exists;
|
|
|
|
}
|
2020-03-26 23:34:18 +00:00
|
|
|
|
|
|
|
VTKM_CONT vtkm::cont::internal::DeviceAdapterMemoryManagerBase&
|
|
|
|
RuntimeDeviceInformation::GetMemoryManager(DeviceAdapterId device) const
|
|
|
|
{
|
|
|
|
if (device.IsValueValid())
|
|
|
|
{
|
|
|
|
return RuntimeDeviceMemoryManagers::GetDeviceMemoryManager(device);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw vtkm::cont::ErrorBadValue(
|
|
|
|
"Attempted to get a DeviceAdapterMemoryManager for an invalid device.");
|
|
|
|
}
|
|
|
|
}
|
2018-10-30 13:49:41 +00:00
|
|
|
}
|
|
|
|
} // namespace vtkm::cont
|