Commit d9270e40 authored by Robert Maynard's avatar Robert Maynard
Browse files

Adding a cuda device adapter to vtkm.

Porting the dax device adapter over to vtkm. Unlike the dax version, doesn't
use the thrust::device_vector, but instead uses thrust::system calls so that
we can support multiple thrust based backends.

Also this has Texture Memory support for input array handles. Some more work
will need to be done to ArrayHandle so that everything works when using an
ArrayHandle inplace with texture memory bindings.
parent e2eb901b
##============================================================================
## 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.
##============================================================================
#
# FindThrust
#
# This module finds the Thrust header files and extrats their version. It
# sets the following variables.
#
# THRUST_INCLUDE_DIR - Include directory for thrust header files. (All header
# files will actually be in the thrust subdirectory.)
# THRUST_VERSION - Version of thrust in the form "major.minor.patch".
#
find_path( THRUST_INCLUDE_DIR
HINTS
/usr/include/cuda
/usr/local/include
/usr/local/cuda/include
${CUDA_INCLUDE_DIRS}
NAMES thrust/version.h
DOC "Thrust headers"
)
if( THRUST_INCLUDE_DIR )
list( REMOVE_DUPLICATES THRUST_INCLUDE_DIR )
endif( THRUST_INCLUDE_DIR )
# Find thrust version
file( STRINGS ${THRUST_INCLUDE_DIR}/thrust/version.h
version
REGEX "#define THRUST_VERSION[ \t]+([0-9x]+)"
)
string( REGEX REPLACE
"#define THRUST_VERSION[ \t]+"
""
version
"${version}"
)
string( REGEX MATCH "^[0-9]" major ${version} )
string( REGEX REPLACE "^${major}00" "" version "${version}" )
string( REGEX MATCH "^[0-9]" minor ${version} )
string( REGEX REPLACE "^${minor}0" "" version "${version}" )
set( THRUST_VERSION "${major}.${minor}.${version}")
set( THRUST_MAJOR_VERSION "${major}")
set( THRUST_MINOR_VERSION "${minor}")
# Check for required components
include( FindPackageHandleStandardArgs )
find_package_handle_standard_args( Thrust
REQUIRED_VARS THRUST_INCLUDE_DIR
VERSION_VAR THRUST_VERSION
)
set(THRUST_INCLUDE_DIRS ${THRUST_INCLUDE_DIR})
mark_as_advanced(THRUST_INCLUDE_DIR)
\ No newline at end of file
##============================================================================
## 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.
##============================================================================
if (VTKm_Cuda_initialize_complete)
return()
endif (VTKm_Cuda_initialize_complete)
set(VTKm_Cuda_FOUND ${VTKm_ENABLE_CUDA})
if (NOT VTKm_Cuda_FOUND)
message(STATUS "This build of VTKm does not include Cuda.")
endif (NOT VTKm_Cuda_FOUND)
# Find the Boost library.
if (VTKm_Cuda_FOUND)
if(NOT Boost_FOUND)
find_package(BoostHeaders ${VTKm_REQUIRED_BOOST_VERSION})
endif()
if (NOT Boost_FOUND)
message(STATUS "Boost not found")
set(VTKm_Cuda_FOUND)
endif (NOT Boost_FOUND)
endif (VTKm_Cuda_FOUND)
# Find the Thrust library.
if (VTKm_Cuda_FOUND)
find_package(Thrust)
if (NOT THRUST_FOUND)
message(STATUS "Thrust not found")
set(VTKm_Cuda_FOUND)
endif (NOT THRUST_FOUND)
endif (VTKm_Cuda_FOUND)
# Find Cuda support.
if (VTKm_Cuda_FOUND)
find_package(CUDA)
mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_VERBOSE_BUILD)
if (NOT CUDA_FOUND)
message(STATUS "CUDA not found")
set(VTKm_Cuda_FOUND)
endif (NOT CUDA_FOUND)
endif (VTKm_Cuda_FOUND)
# Set up all these dependent packages (if they were all found).
if (VTKm_Cuda_FOUND)
cuda_include_directories(
${Boost_INCLUDE_DIRS}
${THRUST_INCLUDE_DIRS}
${VTKm_INCLUDE_DIRS}
)
set(VTKm_Cuda_initialize_complete TRUE)
endif (VTKm_Cuda_FOUND)
##============================================================================
## 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.
##============================================================================
if (VTKm_Serial_initialize_complete)
return()
endif (VTKm_Serial_initialize_complete)
# Find the Boost library.
if (NOT VTKm_Serial_FOUND)
if(NOT Boost_FOUND)
find_package(BoostHeaders ${VTKm_REQUIRED_BOOST_VERSION})
endif()
if (NOT Boost_FOUND)
message(STATUS "Boost not found")
set(VTKm_Serial_FOUND FALSE)
else(NOT Boost_FOUND)
set(VTKm_Serial_FOUND TRUE)
endif (NOT Boost_FOUND)
endif (NOT VTKm_Serial_FOUND)
# Set up all these dependent packages (if they were all found).
if (VTKm_Serial_FOUND)
include_directories(
${Boost_INCLUDE_DIRS}
${VTKm_INCLUDE_DIRS}
)
set(VTKm_Serial_initialize_complete TRUE)
endif (VTKm_Serial_FOUND)
......@@ -368,3 +368,14 @@ macro(vtkm_disable_troublesome_thrust_warnings_var flags_var)
string(REPLACE "-Wall" "" new_flags "${new_flags}")
set(${flags_var} "${new_flags}")
endmacro(vtkm_disable_troublesome_thrust_warnings_var)
# Set up configuration for a given device.
macro(vtkm_configure_device device)
string(TOUPPER "${device}" device_uppercase)
set(VTKm_ENABLE_${device_uppercase} ON)
include("${VTKm_SOURCE_DIR}/CMake/UseVTKm${device}.cmake")
if(NOT VTKm_${device}_FOUND)
message(SEND_ERROR "Could not configure for using VTKm with ${device}")
endif(NOT VTKm_${device}_FOUND)
endmacro(vtkm_configure_device)
......@@ -53,6 +53,7 @@ include(CMake/VTKmCompilerExtras.cmake)
#-----------------------------------------------------------------------------
# Configurable Options
option(VTKm_ENABLE_CUDA "Enable Cuda support" ON)
option(VTKm_ENABLE_TESTING "Enable VTKm Testing" ON)
option(VTKm_USE_DOUBLE_PRECISION
......@@ -66,6 +67,13 @@ if (VTKm_ENABLE_TESTING)
include(CTest)
endif()
#-----------------------------------------------------------------------------
# Set up devices selected.
vtkm_configure_device(Serial)
if (VTKm_ENABLE_CUDA)
vtkm_configure_device(Cuda)
endif (VTKm_ENABLE_CUDA)
#-----------------------------------------------------------------------------
## Set the directory where the binaries will be stored
......@@ -122,12 +130,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/vtkm/internal/Configure.h.in
vtkm_install_headers(
vtkm/internal ${CMAKE_CURRENT_BINARY_DIR}/vtkm/internal/Configure.h)
# List of Boost features used:
# * Smart Ptr
# * Meta programming language
find_package(BoostHeaders ${VTKm_REQUIRED_BOOST_VERSION} REQUIRED)
find_package(Pyexpander)
#-----------------------------------------------------------------------------
......@@ -183,6 +185,15 @@ install(
DESTINATION ${VTKm_INSTALL_CMAKE_MODULE_DIR}
)
# Install Use files.
install(
FILES
${VTKm_SOURCE_DIR}/CMake/UseVTKmSerial.cmake
${VTKm_SOURCE_DIR}/CMake/UseVTKmCuda.cmake
DESTINATION ${VTKm_INSTALL_CMAKE_MODULE_DIR}
)
# Enable CPack packaging
set(CPACK_PACKAGE_DESCRIPTION_FILE ${VTKm_SOURCE_DIR}/README.md)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The VTKm Toolkit")
......
......@@ -1172,6 +1172,18 @@ VTK_M_SCALAR_DOT(vtkm::UInt64)
VTK_M_SCALAR_DOT(vtkm::Float32)
VTK_M_SCALAR_DOT(vtkm::Float64)
/// Predicate that takes a single argument \c x, and returns
/// True if it isn't the identity of the Type \p T.
template<typename T>
struct not_default_constructor
{
VTKM_EXEC_CONT_EXPORT bool operator()(const T &x)
{
return (x != T());
}
};
} // End of namespace vtkm
// Declared outside of vtkm namespace so that the operator works with all code.
......
......@@ -57,6 +57,9 @@ add_subdirectory(arg)
vtkm_declare_headers(${impl_headers} ${headers})
if (VTKm_ENABLE_CUDA)
add_subdirectory(cuda)
endif (VTKm_ENABLE_CUDA)
#-----------------------------------------------------------------------------
add_subdirectory(testing)
......@@ -395,8 +395,8 @@ public:
#if VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_SERIAL
#include <vtkm/cont/internal/DeviceAdapterAlgorithmSerial.h>
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_CUDA
// #include <vtkm/cuda/cont/internal/DeviceAdapterAlgorithmCuda.h>
#elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_CUDA
#include <vtkm/cont/cuda/internal/DeviceAdapterAlgorithmCuda.h>
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_OPENMP
// #include <vtkm/openmp/cont/internal/DeviceAdapterAlgorithmOpenMP.h>
// #elif VTKM_DEVICE_ADAPTER == VTKM_DEVICE_ADAPTER_TBB
......
##============================================================================
## 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.
##============================================================================
set(headers
ChooseCudaDevice.h
DeviceAdapterCuda.h
)
vtkm_disable_troublesome_thrust_warnings()
#-----------------------------------------------------------------------------
CUDA_INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
add_subdirectory(internal)
#-----------------------------------------------------------------------------
vtkm_declare_headers(CUDA ${headers})
add_subdirectory(testing)
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_cuda_ChooseCudaDevice_h
#define vtk_m_cont_cuda_ChooseCudaDevice_h
#include <vtkm/cont/ErrorExecution.h>
#include <cuda.h>
#include <algorithm>
#include <vector>
namespace vtkm{
namespace cuda{
namespace cont {
namespace {
struct compute_info
{
compute_info(cudaDeviceProp prop, int index)
{
this->Index = index;
this->Major = prop.major;
this->MemorySize = prop.totalGlobalMem;
this->Performance = prop.multiProcessorCount *
prop.maxThreadsPerMultiProcessor *
(prop.clockRate / 100000.0f);
//9999 is equal to emulation make sure it is a super bad device
if(this->Major >= 9999)
{
this->Major = -1;
this->Performance = -1;
}
}
//sort from fastest to slowest
bool operator<(const compute_info other) const
{
//if we are both SM2 or greater check performance
//if we both the same SM level check performance
if( (this->Major >= 2 && other.Major >= 2) ||
(this->Major == other.Major) )
{
return betterPerfomance(other);
}
//prefer the greater SM otherwise
return this->Major > other.Major;
}
bool betterPerfomance(const compute_info other) const
{
if ( this->Performance == other.Performance)
{
if( this->MemorySize == other.MemorySize )
{
//prefer first device over second device
//this will be subjective I bet
return this->Index < other.Index;
}
return this->MemorySize > other.MemorySize;
}
return this->Performance > other.Performance;
}
int GetIndex() const { return Index; }
private:
int Index;
int Major;
int MemorySize;
int Performance;
};
}
///Returns the fastest cuda device id that the current system has
///A result of zero means no cuda device has been found
static int FindFastestDeviceId()
{
//get the number of devices and store information
int numberOfDevices=0;
cudaGetDeviceCount(&numberOfDevices);
std::vector<compute_info> devices;
for(int i=0; i < numberOfDevices; ++i)
{
cudaDeviceProp properties;
cudaGetDeviceProperties(&properties, i);
if(properties.computeMode != cudaComputeModeProhibited)
{
//only add devices that have compute mode allowed
devices.push_back( compute_info(properties,i) );
}
}
//sort from fastest to slowest
std::sort(devices.begin(),devices.end());
int device=0;
if(devices.size()> 0)
{
device = devices.front().GetIndex();
}
return device;
}
//choose a cuda compute device. This can't be used if you are setting
//up open gl interop
static void SetCudaDevice(int id)
{
cudaError_t cError = cudaSetDevice(id);
if(cError != cudaSuccess)
{
std::string cuda_error_msg(
"Unable to bind to the given cuda device. Error: ");
cuda_error_msg.append(cudaGetErrorString(cError));
throw vtkm::cont::ErrorExecution(cuda_error_msg);
}
}
}
}
} //namespace
#endif
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_cuda_DeviceAdapterCuda_h
#define vtk_m_cont_cuda_DeviceAdapterCuda_h
#include <vtkm/cont/cuda/internal/DeviceAdapterTagCuda.h>
#include <vtkm/cont/cuda/internal/ArrayManagerExecutionCuda.h>
#include <vtkm/cont/cuda/internal/DeviceAdapterAlgorithmCuda.h>
#endif //vtk_m_cont_cuda_DeviceAdapterCuda_h
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_cuda_internal_ArrayManagerExecutionCuda_h
#define vtk_m_cont_cuda_internal_ArrayManagerExecutionCuda_h
#include <vtkm/cont/cuda/internal/SetThrustForCuda.h>
#include <vtkm/cont/cuda/internal/DeviceAdapterTagCuda.h>
#include <vtkm/cont/Storage.h>
#include <vtkm/cont/internal/ArrayManagerExecution.h>
#include <vtkm/cont/cuda/internal/ArrayManagerExecutionThrustDevice.h>
// These must be placed in the vtkm::cont::internal namespace so that
// the template can be found.
namespace vtkm {
namespace cont {
namespace internal {
template <typename T, class StorageTag>
class ArrayManagerExecution
<T, StorageTag, vtkm::cont::DeviceAdapterTagCuda>
: public vtkm::cont::cuda::internal::ArrayManagerExecutionThrustDevice
<T, StorageTag>
{
public:
typedef vtkm::cont::cuda::internal::ArrayManagerExecutionThrustDevice
<T, StorageTag> Superclass;
typedef typename Superclass::ValueType ValueType;
typedef typename Superclass::PortalType PortalType;
typedef typename Superclass::PortalConstType PortalConstType;
template<class PortalControl>
VTKM_CONT_EXPORT void LoadDataForInput(PortalControl arrayPortal)
{
try
{
this->Superclass::LoadDataForInput(arrayPortal);
}
catch (vtkm::cont::ErrorControlOutOfMemory error)
{
// Thrust does not seem to be clearing the CUDA error, so do it here.
cudaError_t cudaError = cudaPeekAtLastError();
if (cudaError == cudaErrorMemoryAllocation)
{
cudaGetLastError();
}
throw error;
}
}
VTKM_CONT_EXPORT void AllocateArrayForOutput(
vtkm::cont::internal::Storage<ValueType,StorageTag>
&container,
vtkm::Id numberOfValues)
{
try
{
this->Superclass::AllocateArrayForOutput(container, numberOfValues);
}
catch (vtkm::cont::ErrorControlOutOfMemory error)
{
// Thrust does not seem to be clearing the CUDA error, so do it here.
cudaError_t cudaError = cudaPeekAtLastError();
if (cudaError == cudaErrorMemoryAllocation)
{
cudaGetLastError();
}
throw error;
}
}
};
}
}
} // namespace vtkm::cont::internal
#endif //vtk_m_cont_cuda_internal_ArrayManagerExecutionCuda_h
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even