Make RuntimeDeviceInformation class template independent

By making RuntimeDeviceInformation class template independent, vtkm is
able to detect
device info at runtime with a runtime specified deviceId. In the past
it's impossible
because the CRTP pattern does not allow function overloading(compiler
would complain
that DeviceAdapterRuntimeDetector does not have Exists() function
defined).
This commit is contained in:
Haocheng LIU 2018-10-30 09:49:41 -04:00
parent 5ded6352fe
commit bb06717803
10 changed files with 97 additions and 43 deletions

@ -0,0 +1,9 @@
# Make RuntimeDeviceInformation class template independent
By making RuntimeDeviceInformation class template independent, vtkm is able to detect
device info at runtime with a runtime specified deviceId. In the past it's impossible
because the CRTP pattern does not allow function overloading(compiler would complain
that DeviceAdapterRuntimeDetector does not have Exists() function defined).

@ -28,6 +28,8 @@
#include <vtkm/cont/ExecutionAndControlObjectBase.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/serial/internal/DeviceAdapterRuntimeDetectorSerial.h>
namespace vtkm
{
namespace cont

@ -146,6 +146,7 @@ set(sources
Logging.cxx
MultiBlock.cxx
PresetColorTables.cxx
RuntimeDeviceInformation.cxx
RuntimeDeviceTracker.cxx
StorageBasic.cxx
TryExecute.cxx

@ -0,0 +1,61 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2016 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2016 UT-Battelle, LLC.
// Copyright 2016 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#include <vtkm/cont/RuntimeDeviceInformation.h>
#include <vtkm/ListTag.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/DeviceAdapterListTag.h>
//Bring in each device adapters runtime class
#include <vtkm/cont/cuda/internal/DeviceAdapterRuntimeDetectorCuda.h>
#include <vtkm/cont/internal/DeviceAdapterError.h>
#include <vtkm/cont/openmp/internal/DeviceAdapterRuntimeDetectorOpenMP.h>
#include <vtkm/cont/serial/internal/DeviceAdapterRuntimeDetectorSerial.h>
#include <vtkm/cont/tbb/internal/DeviceAdapterRuntimeDetectorTBB.h>
namespace vtkm
{
namespace cont
{
namespace detail
{
struct RuntimeDeviceInformationFunctor
{
bool Exists = false;
template <typename DeviceAdapter>
VTKM_CONT void operator()(DeviceAdapter, DeviceAdapterId device)
{
if (DeviceAdapter() == device)
{
this->Exists = vtkm::cont::DeviceAdapterRuntimeDetector<DeviceAdapter>().Exists();
}
}
};
}
VTKM_CONT
bool RuntimeDeviceInformation::Exists(DeviceAdapterId id) const
{
detail::RuntimeDeviceInformationFunctor functor;
vtkm::ListForEach(functor, VTKM_DEFAULT_DEVICE_ADAPTER_LIST_TAG(), id);
return functor.Exists;
}
}
} // namespace vtkm::cont

@ -20,14 +20,8 @@
#ifndef vtk_m_cont_RuntimeDeviceInformation_h
#define vtk_m_cont_RuntimeDeviceInformation_h
#include <vtkm/cont/DeviceAdapter.h>
//Bring in each device adapters runtime class
#include <vtkm/cont/cuda/internal/DeviceAdapterRuntimeDetectorCuda.h>
#include <vtkm/cont/internal/DeviceAdapterError.h>
#include <vtkm/cont/openmp/internal/DeviceAdapterRuntimeDetectorOpenMP.h>
#include <vtkm/cont/serial/internal/DeviceAdapterRuntimeDetectorSerial.h>
#include <vtkm/cont/tbb/internal/DeviceAdapterRuntimeDetectorTBB.h>
#include <vtkm/cont/internal/DeviceAdapterTag.h>
#include <vtkm/internal/ExportMacros.h>
namespace vtkm
{
@ -40,24 +34,18 @@ namespace cont
/// or a Accelerator Card.
///
///
template <class Device>
class RuntimeDeviceInformation
class VTKM_CONT_EXPORT RuntimeDeviceInformation
{
public:
VTKM_CONT
RuntimeDeviceInformation()
: RuntimeImplementation()
{
}
RuntimeDeviceInformation() {}
/// Returns true if the given device adapter is supported on the current
/// machine.
///
VTKM_CONT
bool Exists() const { return this->RuntimeImplementation.Exists(); }
private:
vtkm::cont::DeviceAdapterRuntimeDetector<Device> RuntimeImplementation;
bool Exists(DeviceAdapterId id) const;
};
}
} // namespace vtkm::cont

@ -23,6 +23,7 @@
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/DeviceAdapterListTag.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/internal/DeviceAdapterError.h>
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>

@ -109,8 +109,8 @@ public:
template <typename DeviceAdapterTag>
VTKM_CONT void ResetDevice(DeviceAdapterTag device)
{
vtkm::cont::RuntimeDeviceInformation<DeviceAdapterTag> runtimeDevice;
this->SetDeviceState(device, runtimeDevice.Exists());
vtkm::cont::RuntimeDeviceInformation runtimeDevice;
this->SetDeviceState(device, runtimeDevice.Exists(DeviceAdapterTag()));
}
/// Reset the tracker to its default state for default devices.
@ -192,8 +192,8 @@ public:
template <typename DeviceAdapterTag>
VTKM_CONT void ForceDevice(DeviceAdapterTag device)
{
vtkm::cont::RuntimeDeviceInformation<DeviceAdapterTag> runtimeDevice;
this->ForceDeviceImpl(device, runtimeDevice.Exists());
vtkm::cont::RuntimeDeviceInformation runtimeDevice;
this->ForceDeviceImpl(device, runtimeDevice.Exists(DeviceAdapterTag()));
}
VTKM_CONT_EXPORT

@ -608,18 +608,6 @@ private:
VTKM_TEST_ASSERT(elapsedTime < 2.0, "Timer counted too far or system really busy.");
}
VTKM_CONT
static void TestRuntime()
{
std::cout << "-------------------------------------------" << std::endl;
std::cout << "Testing RuntimeDeviceInformation" << std::endl;
vtkm::cont::RuntimeDeviceInformation<DeviceAdapterTag> runtime;
const bool valid_runtime = runtime.Exists();
VTKM_TEST_ASSERT(valid_runtime, "runtime detection failed for device");
}
VTKM_CONT
static void TestVirtualObjectTransfer()
{
@ -2416,7 +2404,6 @@ private:
TestArrayManagerExecution();
TestOutOfMemory();
TestTimer();
TestRuntime();
TestVirtualObjectTransfer();
TestAlgorithmSchedule();

@ -22,6 +22,7 @@
//include all backends
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/openmp/DeviceAdapterOpenMP.h>
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>
@ -50,8 +51,8 @@ struct DoesExist<false>
{
//runtime information for this device should return false
vtkm::cont::RuntimeDeviceInformation<DeviceAdapterTag> runtime;
VTKM_TEST_ASSERT(runtime.Exists() == false,
vtkm::cont::RuntimeDeviceInformation runtime;
VTKM_TEST_ASSERT(runtime.Exists(DeviceAdapterTag()) == false,
"A backend with zero compile time support, can't have runtime support");
}
@ -60,12 +61,12 @@ struct DoesExist<false>
//Since we are in a C++ compilation unit the Device Adapter
//trait should be false. But CUDA could still be enabled.
//That is why we check VTKM_ENABLE_CUDA.
vtkm::cont::RuntimeDeviceInformation<vtkm::cont::DeviceAdapterTagCuda> runtime;
vtkm::cont::RuntimeDeviceInformation runtime;
#ifdef VTKM_ENABLE_CUDA
VTKM_TEST_ASSERT(runtime.Exists() == true,
VTKM_TEST_ASSERT(runtime.Exists(vtkm::cont::DeviceAdapterTagCuda()) == true,
"with cuda backend enabled, runtime support should be enabled");
#else
VTKM_TEST_ASSERT(runtime.Exists() == false,
VTKM_TEST_ASSERT(runtime.Exists(vtkm::cont::DeviceAdapterTagCuda()) == false,
"with cuda backend disabled, runtime support should be disabled");
#endif
}
@ -78,8 +79,8 @@ struct DoesExist<true>
void Exist(DeviceAdapterTag) const
{
//runtime information for this device should return true
vtkm::cont::RuntimeDeviceInformation<DeviceAdapterTag> runtime;
VTKM_TEST_ASSERT(runtime.Exists() == true,
vtkm::cont::RuntimeDeviceInformation runtime;
VTKM_TEST_ASSERT(runtime.Exists(DeviceAdapterTag()) == true,
"A backend with compile time support, should have runtime support");
}
};
@ -87,14 +88,16 @@ struct DoesExist<true>
void Detection()
{
using SerialTag = ::vtkm::cont::DeviceAdapterTagSerial;
using OpenMPTag = ::vtkm::cont::DeviceAdapterTagOpenMP;
using TBBTag = ::vtkm::cont::DeviceAdapterTagTBB;
using CudaTag = ::vtkm::cont::DeviceAdapterTagCuda;
//Verify that for each device adapter we compile code for, that it
//has valid runtime support.
detect_if_exists(SerialTag());
detect_if_exists(OpenMPTag());
detect_if_exists(CudaTag());
detect_if_exists(TBBTag());
detect_if_exists(SerialTag());
}
} // anonymous namespace

@ -19,6 +19,8 @@
//============================================================================
#include <vtkm/cont/Error.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/RuntimeDeviceInformation.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/internal/DeviceAdapterError.h>