Merge topic 'multiple_backend_example'

fd685210 Always install all device headers even when device isn't enabled.
b1663b24 Add an example of using multiple backends from a single translation unit.
fc0ff69d Methods with try/catch need to be host only.
4d635d64 DeviceAdapter Tags now always exist, and contain if the device is valid.
cf32b430 Teach Configure.h to store if TBB and CUDA are enabled.

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Kenneth Moreland <kmorel@sandia.gov>
Merge-request: !198
This commit is contained in:
Robert Maynard 2015-09-17 09:49:49 -04:00 committed by Kitware Robot
commit 9b877ef49b
24 changed files with 329 additions and 50 deletions

@ -153,17 +153,26 @@ endfunction(vtkm_requires_thrust_to_test)
# compiled and show up in an IDE.
function(vtkm_declare_headers)
set(options CUDA)
set(oneValueArgs)
set(oneValueArgs TESTABLE)
set(multiValueArgs)
cmake_parse_arguments(VTKm_DH "${options}"
"${oneValueArgs}" "${multiValueArgs}"
${ARGN}
)
#The testable keyword allows the caller to turn off the header testing,
#mainly used so that backends can be installed even when they can't be
#built on the machine.
#Since this is an optional property not setting it means you do want testing
if(NOT DEFINED VTKm_DH_TESTABLE)
set(VTKm_DH_TESTABLE ON)
endif()
set(hfiles ${VTKm_DH_UNPARSED_ARGUMENTS})
vtkm_get_kit_name(name dir_prefix)
#only do header testing if enable testing is turned on
if (VTKm_ENABLE_TESTING)
if (VTKm_ENABLE_TESTING AND VTKm_DH_TESTABLE)
vtkm_add_header_build_test(
"${name}" "${dir_prefix}" "${VTKm_DH_CUDA}" ${hfiles})
endif()

@ -200,6 +200,10 @@ endif(VTKm_BUILD_EXAMPLES)
set(VTKM_USE_DOUBLE_PRECISION ${VTKm_USE_DOUBLE_PRECISION})
set(VTKM_USE_64BIT_IDS ${VTKm_USE_64BIT_IDS})
set(VTKM_ENABLE_CUDA ${VTKm_ENABLE_CUDA})
set(VTKM_ENABLE_TBB ${VTKm_ENABLE_TBB})
set(VTKM_ENABLE_OPENGL_INTEROP ${VTKm_ENABLE_OPENGL_INTEROP})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/vtkm/internal/Configure.h.in
@ -209,6 +213,10 @@ vtkm_install_headers(
vtkm/internal ${CMAKE_CURRENT_BINARY_DIR}/vtkm/internal/Configure.h)
unset(VTKM_ENABLE_OPENGL_INTEROP)
unset(VTKM_ENABLE_TBB)
unset(VTKM_ENABLE_CUDA)
unset(VTKM_USE_64BIT_IDS)
unset(VTKM_USE_DOUBLE_PRECISION)

@ -21,4 +21,5 @@
##=============================================================================
add_subdirectory(hello_world)
add_subdirectory(isosurface)
add_subdirectory(isosurface)
add_subdirectory(multi_backend)

@ -0,0 +1,33 @@
##=============================================================================
##
## 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 2015 Sandia Corporation.
## Copyright 2015 UT-Battelle, LLC.
## Copyright 2015 Los Alamos National Security.
##
## Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
## 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.
##
##=============================================================================
cmake_minimum_required(VERSION 2.8.11)
if(VTKm_Cuda_FOUND)
cuda_add_executable(MultiBackend MultiBackend.cu)
else()
add_executable(MultiBackend MultiBackend.cxx)
endif()
if(VTKm_TBB_FOUND)
target_link_libraries(MultiBackend ${TBB_LIBRARIES})
endif()

@ -0,0 +1,25 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// 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.
//============================================================================
#define BOOST_SP_DISABLE_THREADS
//This file merely exists so that we can simplify the logic for invoking
//nvcc telling that cuda code exists.
#include "MultiBackend.cxx"

@ -0,0 +1,158 @@
//============================================================================
// 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 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// 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 <iostream>
#include <vtkm/Math.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/worklet/DispatcherMapField.h>
#include <vtkm/worklet/WorkletMapField.h>
#include <vtkm/cont/cuda/DeviceAdapterCuda.h>
#include <vtkm/cont/tbb/DeviceAdapterTBB.h>
struct GenerateSurfaceWorklet : public vtkm::worklet::WorkletMapField
{
vtkm::Float32 t;
GenerateSurfaceWorklet(vtkm::Float32 st) : t(st) {}
typedef void ControlSignature( FieldIn<>, FieldOut<>, FieldOut<> );
typedef void ExecutionSignature( _1, _2, _3 );
template<typename T>
VTKM_EXEC_EXPORT
void operator()( const vtkm::Vec< T, 3 > & input,
vtkm::Vec<T, 3> & output,
vtkm::Vec<vtkm::UInt8, 4>& color ) const
{
output[0] = input[0];
output[1] = 0.25f * vtkm::Sin( input[0] * 10.f + t ) * vtkm::Cos( input[2] * 10.f + t );
output[2] = input[2];
color[0] = 0;
color[1] = 160 + static_cast<vtkm::UInt8>(96 * vtkm::Sin( input[0] * 10.f + t ) );
color[2] = 160 + static_cast<vtkm::UInt8>(96 * vtkm::Cos( input[2] * 5.f + t ) );
color[3] = 255;
}
};
template<bool> struct CanRun;
template<typename T, typename DeviceAdapterTag>
void run_if_valid(vtkm::cont::ArrayHandle< vtkm::Vec< T, 3 > > inHandle,
vtkm::cont::ArrayHandle< vtkm::Vec< T, 3 > > outCoords,
vtkm::cont::ArrayHandle< vtkm::Vec< vtkm::UInt8, 4 > > outColors,
DeviceAdapterTag tag)
{
typedef vtkm::cont::internal::DeviceAdapterTraits<DeviceAdapterTag>
DeviceAdapterTraits;
if(DeviceAdapterTraits::Valid)
{
std::cout << "Running a worklet on device adapter: "
<< DeviceAdapterTraits::GetId() << std::endl;
}
else
{
std::cout << "Unable to run a worklet on device adapter: "
<< DeviceAdapterTraits::GetId() << std::endl;
}
CanRun<DeviceAdapterTraits::Valid>::run(inHandle,outCoords,outColors,tag);
}
//Implementation that we call on device adapters we don't have support
//enabled for
template<>
struct CanRun<false>
{
template<typename T, typename DeviceAdapterTag>
static void run(vtkm::cont::ArrayHandle< vtkm::Vec< T, 3 > > vtkmNotUsed(inHandle),
vtkm::cont::ArrayHandle< vtkm::Vec< T, 3 > > vtkmNotUsed(outCoords),
vtkm::cont::ArrayHandle< vtkm::Vec< vtkm::UInt8, 4 > > vtkmNotUsed(outColors),
DeviceAdapterTag)
{
}
};
//Implementation that we call on device adapters we do have support
//enabled for
template<>
struct CanRun<true>
{
template<typename T, typename DeviceAdapterTag>
static void run(vtkm::cont::ArrayHandle< vtkm::Vec< T, 3 > > inHandle,
vtkm::cont::ArrayHandle< vtkm::Vec< T, 3 > > outCoords,
vtkm::cont::ArrayHandle< vtkm::Vec< vtkm::UInt8, 4 > > outColors,
DeviceAdapterTag)
{
typedef vtkm::worklet::DispatcherMapField<GenerateSurfaceWorklet,
DeviceAdapterTag> DispatcherType;
GenerateSurfaceWorklet worklet( 0.05f );
DispatcherType(worklet).Invoke( inHandle,
outCoords,
outColors);
}
};
template<typename T>
std::vector< vtkm::Vec<T, 3> > make_testData(int size)
{
std::vector< vtkm::Vec< T, 3 > > data;
data.reserve( static_cast<std::size_t>(size*size) );
for (int i = 0; i < size; ++i )
{
for (int j = 0; j < size; ++j )
{
data.push_back( vtkm::Vec<T,3>( 2.f * i / size - 1.f,
0.f,
2.f * j / size - 1.f ) );
}
}
return data;
}
int main(int, char**)
{
typedef vtkm::Vec< vtkm::Float32, 3 > FloatVec3;
typedef vtkm::Vec< vtkm::UInt8, 4 > Uint8Vec4;
std::vector< FloatVec3 > data = make_testData<vtkm::Float32>(1024);
typedef ::vtkm::cont::DeviceAdapterTagSerial SerialTag;
typedef ::vtkm::cont::DeviceAdapterTagTBB TBBTag;
typedef ::vtkm::cont::DeviceAdapterTagCuda CudaTag;
//make array handles for the data
vtkm::cont::ArrayHandle< FloatVec3 > in = vtkm::cont::make_ArrayHandle(data);
vtkm::cont::ArrayHandle< FloatVec3 > out;
vtkm::cont::ArrayHandle< Uint8Vec4 > color;
//Run the algorithm on all backends that we have compiled support for.
run_if_valid(in, out, color, SerialTag());
run_if_valid(in, out, color, CudaTag());
run_if_valid(in, out, color, TBBTag());
}

@ -69,12 +69,8 @@ add_subdirectory(arg)
vtkm_declare_headers(${impl_headers} ${headers})
if (VTKm_ENABLE_CUDA)
add_subdirectory(cuda)
endif ()
if (VTKm_ENABLE_TBB)
add_subdirectory(tbb)
endif ()
add_subdirectory(cuda)
add_subdirectory(tbb)
#-----------------------------------------------------------------------------
add_subdirectory(testing)

@ -23,14 +23,18 @@ set(headers
DeviceAdapterCuda.h
)
vtkm_disable_troublesome_thrust_warnings()
#-----------------------------------------------------------------------------
if (VTKm_ENABLE_CUDA)
vtkm_disable_troublesome_thrust_warnings()
CUDA_INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
endif()
#-----------------------------------------------------------------------------
CUDA_INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
add_subdirectory(internal)
vtkm_declare_headers(CUDA ${headers} TESTABLE ${VTKm_ENABLE_CUDA})
#-----------------------------------------------------------------------------
vtkm_declare_headers(CUDA ${headers})
if (VTKm_ENABLE_CUDA)
add_subdirectory(testing)
endif()
add_subdirectory(testing)

@ -21,7 +21,10 @@
#define vtk_m_cont_cuda_DeviceAdapterCuda_h
#include <vtkm/cont/cuda/internal/DeviceAdapterTagCuda.h>
#ifdef VTKM_ENABLE_CUDA
#include <vtkm/cont/cuda/internal/ArrayManagerExecutionCuda.h>
#include <vtkm/cont/cuda/internal/DeviceAdapterAlgorithmCuda.h>
#endif
#endif //vtk_m_cont_cuda_DeviceAdapterCuda_h

@ -28,6 +28,9 @@ set(headers
ThrustExceptionHandler.h
)
vtkm_declare_headers(CUDA ${headers})
vtkm_declare_headers(CUDA ${headers} TESTABLE ${VTKm_ENABLE_CUDA})
add_subdirectory(testing)
#-----------------------------------------------------------------------------
if (VTKm_ENABLE_CUDA)
add_subdirectory(testing)
endif()

@ -22,7 +22,13 @@
#include <vtkm/cont/internal/DeviceAdapterTag.h>
VTKM_CREATE_DEVICE_ADAPTER(Cuda);
//We always create the cuda tag when included, but we only mark it as
//a valid tag when VTKM_ENABLE_CUDA is true. This is for easier development
//of multi-backend systems
#ifdef VTKM_ENABLE_CUDA
VTKM_VALID_DEVICE_ADAPTER(Cuda);
#else
VTKM_INVALID_DEVICE_ADAPTER(Cuda);
#endif
#endif //vtk_m_cont_cuda_internal_DeviceAdapterTagCuda_h

@ -27,6 +27,6 @@
/// point, you have to specify an appropriate DeviceAdapter or else get a
/// compile error.
///
VTKM_CREATE_DEVICE_ADAPTER(Error);
VTKM_VALID_DEVICE_ADAPTER(Error);
#endif //vtk_m_cont_internal_DeviceAdapterError_h

@ -61,7 +61,7 @@ struct DeviceAdapterTagCheck
/// Creates a tag named vtkm::cont::DeviceAdapterTagName and associated MPL
/// structures to use this tag. Always use this macro (in the base namespace)
/// when creating a device adapter.
#define VTKM_CREATE_DEVICE_ADAPTER(Name) \
#define VTKM_VALID_DEVICE_ADAPTER(Name) \
namespace vtkm { \
namespace cont { \
struct DeviceAdapterTag##Name { }; \
@ -71,6 +71,7 @@ struct DeviceAdapterTagCheck
static DeviceAdapterId GetId() { \
return DeviceAdapterId(#Name); \
} \
static const bool Valid = true;\
}; \
template<> \
struct DeviceAdapterTagCheck<vtkm::cont::DeviceAdapterTag##Name> { \
@ -80,6 +81,31 @@ struct DeviceAdapterTagCheck
} \
}
/// Marks the tag named vtkm::cont::DeviceAdapterTagName and associated
/// structures as valid to use. Always use this macro (in the base namespace)
/// when creating a device adapter.
#define VTKM_INVALID_DEVICE_ADAPTER(Name) \
namespace vtkm { \
namespace cont { \
struct DeviceAdapterTag##Name { }; \
namespace internal { \
template<> \
struct DeviceAdapterTraits<vtkm::cont::DeviceAdapterTag##Name> { \
static DeviceAdapterId GetId() { \
return DeviceAdapterId(#Name); \
} \
static const bool Valid = false;\
}; \
template<> \
struct DeviceAdapterTagCheck<vtkm::cont::DeviceAdapterTag##Name> { \
static const bool Valid = false; \
}; \
} \
} \
}
/// Checks that the argument is a proper device adapter tag. This is a handy
/// concept check for functions and classes to make sure that a template
/// argument is actually a device adapter tag. (You can get weird errors

@ -22,6 +22,6 @@
#include <vtkm/cont/internal/DeviceAdapterTag.h>
VTKM_CREATE_DEVICE_ADAPTER(Serial);
VTKM_VALID_DEVICE_ADAPTER(Serial);
#endif //vtk_m_cont_internal_DeviceAdapterTagSerial_h

@ -24,6 +24,9 @@ set(headers
add_subdirectory(internal)
vtkm_declare_headers(${headers})
vtkm_declare_headers(${headers} TESTABLE ${VTKm_ENABLE_TBB})
add_subdirectory(testing)
#-----------------------------------------------------------------------------
if (VTKm_ENABLE_TBB)
add_subdirectory(testing)
endif()

@ -21,7 +21,10 @@
#define vtk_m_cont_tbb_DeviceAdapterTBB_h
#include <vtkm/cont/tbb/internal/DeviceAdapterTagTBB.h>
#ifdef VTKM_ENABLE_TBB
#include <vtkm/cont/tbb/internal/ArrayManagerExecutionTBB.h>
#include <vtkm/cont/tbb/internal/DeviceAdapterAlgorithmTBB.h>
#endif
#endif //vtk_m_cont_tbb_DeviceAdapterTBB_h

@ -31,4 +31,4 @@ if("${TBB_VERSION_MAJOR}.${TBB_VERSION_MINOR}" VERSION_LESS 4.3)
set(headers ${headers} parallel_sort.h)
endif()
vtkm_declare_headers(${headers})
vtkm_declare_headers(${headers} TESTABLE ${VTKm_ENABLE_TBB})

@ -390,7 +390,7 @@ private:
this->Functor.SetErrorMessageBuffer(errorMessage);
}
VTKM_EXEC_EXPORT
VTKM_CONT_EXPORT
void operator()(const ::tbb::blocked_range<vtkm::Id> &range) const {
// The TBB device adapter causes array classes to be shared between
// control and execution environment. This means that it is possible for
@ -462,7 +462,7 @@ private:
this->Functor.SetErrorMessageBuffer(errorMessage);
}
VTKM_EXEC_EXPORT
VTKM_CONT_EXPORT
void operator()(const ::tbb::blocked_range3d<vtkm::Id> &range) const {
try
{
@ -569,7 +569,7 @@ private:
OutputPortal(outputPortal)
{ }
VTKM_EXEC_EXPORT
VTKM_CONT_EXPORT
void operator()(const ::tbb::blocked_range<vtkm::Id> &range) const
{
// The TBB device adapter causes array classes to be shared between

@ -22,7 +22,13 @@
#include <vtkm/cont/internal/DeviceAdapterTag.h>
VTKM_CREATE_DEVICE_ADAPTER(TBB);
//We always create the tbb tag when included, but we only mark it as
//a valid tag when VTKM_ENABLE_TBB is true. This is for easier development
//of multi-backend systems
#ifdef VTKM_ENABLE_TBB
VTKM_VALID_DEVICE_ADAPTER(TBB);
#else
VTKM_INVALID_DEVICE_ADAPTER(TBB);
#endif
#endif //vtk_m_cont_tbb_internal_DeviceAdapterTagTBB_h

@ -33,7 +33,7 @@
#include <vtkm/cont/testing/TestingDeviceAdapter.h>
VTKM_CREATE_DEVICE_ADAPTER(TestAlgorithmGeneral);
VTKM_VALID_DEVICE_ADAPTER(TestAlgorithmGeneral);
namespace vtkm {
namespace cont {

@ -39,9 +39,7 @@ vtkm_declare_headers(${impl_headers} ${headers})
#-----------------------------------------------------------------------------
if (VTKm_ENABLE_CUDA)
add_subdirectory(cuda)
endif ()
add_subdirectory(cuda)
#-----------------------------------------------------------------------------

@ -18,14 +18,5 @@
## this software.
##============================================================================
set(headers
)
#-----------------------------------------------------------------------------
add_subdirectory(internal)
# vtkm_declare_headers(${impl_headers} ${headers})
#-----------------------------------------------------------------------------
# add_subdirectory(testing)

@ -24,13 +24,10 @@ set(headers
WrappedOperators.h
)
vtkm_disable_troublesome_thrust_warnings()
#-----------------------------------------------------------------------------
CUDA_INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
if (VTKm_ENABLE_CUDA)
vtkm_disable_troublesome_thrust_warnings()
CUDA_INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
endif()
vtkm_declare_headers(CUDA ${headers})
#-----------------------------------------------------------------------------
# add_subdirectory(testing)
vtkm_declare_headers(CUDA ${headers} TESTABLE ${VTKm_ENABLE_CUDA})

@ -131,6 +131,15 @@
#define VTKM_THIRDPARTY_POST_INCLUDE
#endif
//Mark if we are building with CUDA enabled
#ifndef VTKM_ENABLE_CUDA
#cmakedefine VTKM_ENABLE_CUDA
#endif
//Mark if we are building with TBB enabled
#ifndef VTKM_ENABLE_TBB
#cmakedefine VTKM_ENABLE_TBB
#endif
//Mark if we are building with interop enabled
#ifndef VTKM_ENABLE_OPENGL_INTEROP
#cmakedefine VTKM_ENABLE_OPENGL_INTEROP