#
# This file is part of the GROMACS molecular simulation package.
#
-# Copyright (c) 2012, by the GROMACS development team, led by
-# David van der Spoel, Berk Hess, Erik Lindahl, and including many
-# others, as listed in the AUTHORS file in the top-level source
-# directory and at http://www.gromacs.org.
+# Copyright (c) 2012,2013,2014, by the GROMACS development team, led by
+# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+# and including many others, as listed in the AUTHORS file in the
+# top-level source directory and at http://www.gromacs.org.
#
# GROMACS is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public License
#
# To help us fund GROMACS development, we humbly ask that you cite
# the research papers on the package. Check out http://www.gromacs.org.
-#
+
# If the user did not set GMX_GPU we'll consider this option to be
# in "auto" mode meaning that we will:
# - search for CUDA and set GMX_GPU=ON we find it
endif()
# detect GPUs in the build host machine
-if (GMX_GPU OR GMX_GPU_AUTO AND NOT GMX_GPU_DETECTION_DONE)
+if ((GMX_GPU OR GMX_GPU_AUTO) AND NOT GMX_GPU_DETECTION_DONE)
include(gmxDetectGpu)
gmx_detect_gpu()
endif()
# We need to call find_package even when we've already done the detection/setup
if(GMX_GPU OR GMX_GPU_AUTO)
- if(NOT GMX_GPU AND GMX_GPU_AUTO AND GMX_GPU_DETECTION_DONE)
+ if(NOT GMX_GPU AND NOT GMX_DETECT_GPU_AVAILABLE)
# Stay quiet when detection has occured and found no GPU.
# Noise is acceptable when there is a GPU or the user required one.
set(FIND_CUDA_QUIETLY QUIET)
endif()
- # We support CUDA >=v3.2 on *nix, but <= v4.1 doesn't work with MSVC
- if(MSVC)
- find_package(CUDA 4.1 ${FIND_CUDA_QUIETLY})
- else()
- find_package(CUDA 3.2 ${FIND_CUDA_QUIETLY})
+ find_package(CUDA ${REQUIRED_CUDA_VERSION} ${FIND_CUDA_QUIETLY})
+
+ # Cmake 2.8.12 (and CMake 3.0) introduced a new bug where the cuda
+ # library dir is added twice as an rpath on APPLE, which in turn causes
+ # the install_name_tool to wreck the binaries when it tries to remove this
+ # path. Since this is set inside the cuda module, we remove the extra rpath
+ # added in the library string - an rpath is not a library anyway, and at
+ # least for Gromacs this works on all CMake versions. This should be
+ # reasonably future-proof, since newer versions of CMake appear to handle
+ # the rpath automatically based on the provided library path, meaning
+ # the explicit rpath specification is no longer needed.
+ if(APPLE AND (CMAKE_VERSION VERSION_GREATER 2.8.11))
+ foreach(elem ${CUDA_LIBRARIES})
+ if(elem MATCHES "-Wl,.*")
+ list(REMOVE_ITEM CUDA_LIBRARIES ${elem})
+ endif()
+ endforeach(elem)
endif()
endif()
# - OFF, TRUE : Will keep GMX_GPU=OFF if no CUDA is detected, but will assemble
# a warning message which will be issued at the end of the
# configuration if GPU(s) were found in the build system.
-# - ON , FALSE: The user requested GPU builds, will require CUDA and will fail
-# if it is not available.
+# - ON , FALSE: The user requested GPU build and this requires CUDA, so we will
+# fail if it is not available.
# - ON , TRUE : Can't happen (GMX_GPU=ON can only be user-set at this point)
-if(GMX_GPU OR GMX_GPU_AUTO AND NOT GMX_GPU_DETECTION_DONE)
+if((GMX_GPU OR GMX_GPU_AUTO) AND NOT GMX_GPU_DETECTION_DONE)
if (EXISTS ${CUDA_TOOLKIT_ROOT_DIR})
set(CUDA_FOUND TRUE CACHE INTERNAL "Whether the CUDA toolkit was found" FORCE)
else()
# assemble warning/error message
if (GMX_DETECT_GPU_AVAILABLE)
- set(_msg "
- ${GMX_DETECT_GPU_COUNT} NVIDIA GPU(s) found in the system")
+ set(_msg "${GMX_DETECT_GPU_COUNT} NVIDIA GPU(s) found in the system")
# append GPU names
if (NOT GMX_DETECT_GPU_INFO STREQUAL "")
set(_msg "${_msg}:")
foreach(gpu ${GMX_DETECT_GPU_INFO})
set(_msg "${_msg}
- ${gpu}")
+${gpu}")
endforeach()
endif()
# TODO remove the second part of the message when we'll have compute
# capability information from the detection.
set(_msg "${_msg}
- Compute capability information not available, consult the NVIDIA website:
- https://developer.nvidia.com/cuda-gpus
- ")
+Compute capability information not available, consult the NVIDIA website:
+https://developer.nvidia.com/cuda-gpus")
endif()
- set(CUDA_NOTFOUND_MESSAGE "
- mdrun supports native GPU acceleration on NVIDIA hardware with compute
- capability >=2.0. This requires the NVIDIA CUDA library, which was not
- found; the location can be hinted by setting CUDA_TOOLKIT_ROOT_DIR as
- a CMake option (It does not work as an environment variable).
- The typical location would be /usr/local/cuda[-version].
- Note that CPU or GPU acceleration can be selected at runtime!
+ set(CUDA_NOTFOUND_MESSAGE "mdrun supports native GPU acceleration on NVIDIA hardware with compute capability >= ${REQUIRED_CUDA_COMPUTE_CAPABILITY} (Fermi or later). This requires the NVIDIA CUDA toolkit, which was not found. Its location can be hinted by setting the CUDA_TOOLKIT_ROOT_DIR CMake option (does not work as an environment variable). The typical location would be /usr/local/cuda[-version]. Note that CPU or GPU acceleration can be selected at runtime.
- ${_msg}")
+${_msg}")
unset(_msg)
if (NOT CUDA_FOUND)
if (GMX_GPU_AUTO)
# Disable GPU acceleration in auto mode
- message(STATUS "Disabling native GPU acceleration")
+ message(STATUS "No compatible CUDA toolkit found (v4.0+), disabling native GPU acceleration")
set_property(CACHE GMX_GPU PROPERTY VALUE OFF)
set(CUDA_NOTFOUND_AUTO ON)
- else ()
+ else()
# the user requested CUDA, but it wasn't found
message(FATAL_ERROR "${CUDA_NOTFOUND_MESSAGE}")
endif()
# user turns GMX_GPU=OFF after a failed cmake pass, these variables will be
# left behind in the cache.
mark_as_advanced(CUDA_BUILD_CUBIN CUDA_BUILD_EMULATION CUDA_SDK_ROOT_DIR CUDA_VERBOSE_BUILD)
+if(NOT GMX_GPU)
+ mark_as_advanced(CUDA_TOOLKIT_ROOT_DIR)
+endif()
+
+# Try to execute ${CUDA_NVCC_EXECUTABLE} --version and set the output
+# (or an error string) in the argument variable.
+# Note that semicolon is used as separator for nvcc.
+#
+# Parameters:
+# COMPILER_INFO - [output variable] string with compiler path, ID and
+# some compiler-provided information
+# COMPILER_FLAGS - [output variable] flags for the compiler
+#
+macro(get_cuda_compiler_info COMPILER_INFO COMPILER_FLAGS)
+ if(CUDA_NVCC_EXECUTABLE)
+
+ # Get the nvcc version string. This is multi-line, but since it is only 4 lines
+ # and might change in the future it is better to store than trying to parse out
+ # the version from the current format.
+ execute_process(COMMAND ${CUDA_NVCC_EXECUTABLE} --version
+ RESULT_VARIABLE _nvcc_version_res
+ OUTPUT_VARIABLE _nvcc_version_out
+ ERROR_VARIABLE _nvcc_version_err
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if (${_nvcc_version_res} EQUAL 0)
+ # Fix multi-line mess: Replace newline with ";" so we can use it in a define
+ string(REPLACE "\n" ";" _nvcc_info_singleline ${_nvcc_version_out})
+ SET(${COMPILER_INFO} "${CUDA_NVCC_EXECUTABLE} ${_nvcc_info_singleline}")
+ string(TOUPPER ${CMAKE_BUILD_TYPE} _build_type)
+ SET(_compiler_flags "${CUDA_NVCC_FLAGS_${_build_type}}")
+ if(CUDA_PROPAGATE_HOST_FLAGS)
+ string(REGEX REPLACE "[ ]+" ";" _cxx_flags_nospace "${BUILD_CXXFLAGS}")
+ endif()
+ SET(${COMPILER_FLAGS} "${CUDA_NVCC_FLAGS}${CUDA_NVCC_FLAGS_${_build_type}}; ${_cxx_flags_nospace}")
+ else()
+ SET(${COMPILER_INFO} "N/A")
+ SET(${COMPILER_FLAGS} "N/A")
+ endif()
+ endif()
+endmacro ()
macro(gmx_gpu_setup)
# set up nvcc options
include(gmxManageNvccConfig)
- # Version info (semicolon used as line separator) for nvcc.
- get_nvcc_version_info()
-
# Atomic operations used for polling wait for GPU
# (to avoid the cudaStreamSynchronize + ECC bug).
# ThreadMPI is now always included. Thus, we don't check for Atomics anymore here.
# no OpenMP is no good!
if(NOT GMX_OPENMP)
- message(WARNING "
- To use GPU acceleration efficiently, mdrun requires OpenMP multi-threading.
- With no OpenMP a single CPU core can be used with a GPU which is not optimal.
- Note that with MPI multiple processes can be forced to use a single GPU, but this
- typically inefficient. Note that you need to set both C and C++ compilers that
- support OpenMP (CC and CXX environment variables, respectively) when using GPUs.")
+ message(WARNING "To use GPU acceleration efficiently, mdrun requires OpenMP multi-threading. Without OpenMP a single CPU core can be used with a GPU which is not optimal. Note that with MPI multiple processes can be forced to use a single GPU, but this is typically inefficient. You need to set both C and C++ compilers that support OpenMP (CC and CXX environment variables, respectively) when using GPUs.")
endif()
endmacro()