From 9b3fb3b5ffdb77f223e9ed949508905284bfe3f3 Mon Sep 17 00:00:00 2001 From: Erik Lindahl Date: Wed, 17 Jun 2020 18:25:20 +0000 Subject: [PATCH] Simplified uniform GPU selection in CMake GPU selection is now done by setting GMX_GPU to either CUDA or OpenCL, with no other variables required. As part of the overall CMake simplification, the CMake automatic detection of hardware and "auto" settings for GPU acceleration have been removed. This will require the user to explicitly enable GPU support (which is a drawback), but it leads to much simplier and shorter CMake code, similar support for CUDA and OpenCL, and it will make it easier to handle multiple different APIs targeting e.g. NVIDIA GPU hardware in the near future. --- CMakeLists.txt | 63 ++--- admin/gitlab-ci/documentation.gitlab-ci.yml | 4 +- admin/gitlab-ci/global.gitlab-ci.yml | 4 +- admin/gitlab-ci/gromacs.gitlab-ci.yml | 6 +- cmake/gmxDetectGpu.cmake | 223 ------------------ cmake/gmxManageCuda.cmake | 112 +++++++++ cmake/gmxManageGPU.cmake | 222 ----------------- cmake/gmxManageOpenCL.cmake | 16 +- docs/install-guide/index.rst | 14 +- .../2021/major/miscellaneous.rst | 12 + docs/user-guide/mdrun-performance.rst | 2 +- 11 files changed, 168 insertions(+), 510 deletions(-) delete mode 100644 cmake/gmxDetectGpu.cmake create mode 100644 cmake/gmxManageCuda.cmake delete mode 100644 cmake/gmxManageGPU.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7330131e50..0bab6f38b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,37 +198,13 @@ option(GMX_COOL_QUOTES "Enable GROMACS cool quotes" ON) mark_as_advanced(GMX_COOL_QUOTES) gmx_add_cache_dependency(GMX_COOL_QUOTES BOOL "NOT GMX_FAHCORE" OFF) -option(GMX_USE_OPENCL "Enable OpenCL acceleration" OFF) - option(GMX_INSTALL_LEGACY_API "Install legacy headers" OFF) -# The earliest version of the CUDA toolkit that supports c++14 is 9.0 -set(REQUIRED_CUDA_VERSION 9.0) -set(REQUIRED_CUDA_COMPUTE_CAPABILITY 3.0) - -# OpenCL required version: 1.2 or newer -set(REQUIRED_OPENCL_MIN_VERSION_MAJOR 1) -set(REQUIRED_OPENCL_MIN_VERSION_MINOR 2) -set(REQUIRED_OPENCL_MIN_VERSION ${REQUIRED_OPENCL_MIN_VERSION_MAJOR}.${REQUIRED_OPENCL_MIN_VERSION_MINOR}) - -if(NOT GMX_USE_OPENCL) - # CUDA detection is done only if GMX_USE_OPENCL is OFF. - include(gmxManageGPU) - set(GMX_USE_CUDA ${GMX_GPU}) - if(GMX_GPU) - set(GMX_GPU_ACCELERATION_FRAMEWORK "GMX_GPU_CUDA") - else() - set(GMX_GPU_ACCELERATION_FRAMEWORK "GMX_GPU_NONE") - endif() -else() - #Now the OpenCL path (for both AMD and NVIDIA) - if(GMX_GPU) - include(gmxManageOpenCL) - set(GMX_GPU_ACCELERATION_FRAMEWORK "GMX_GPU_OPENCL") - else() - message(FATAL_ERROR "OpenCL requested but GPU option is not enabled (try -DGMX_GPU=on) ") - endif() -endif() +gmx_option_multichoice( + GMX_GPU + "Framework for GPU acceleration" + None + None CUDA OpenCL) gmx_option_multichoice( GMX_SIMD @@ -566,15 +542,24 @@ include(gmxManageTNG) include(gmxManageLmfit) -if(GMX_GPU) - # now that we have detected the dependencies, do the second configure pass - gmx_gpu_setup() - if (GMX_CLANG_CUDA) - list(APPEND GMX_EXTRA_LIBRARIES ${GMX_CUDA_CLANG_LINK_LIBS}) - link_directories("${GMX_CUDA_CLANG_LINK_DIRS}") +string(TOUPPER "${GMX_GPU}" _gmx_gpu_uppercase) +if(NOT ${_gmx_gpu_uppercase} STREQUAL "NONE") + + if(${_gmx_gpu_uppercase} STREQUAL "CUDA") + include(gmxManageCuda) + elseif(${_gmx_gpu_uppercase} STREQUAL "OPENCL") + include(gmxManageOpenCL) + endif() + if(NOT GMX_OPENMP) + message(WARNING "To use GPU acceleration efficiently, mdrun requires OpenMP multi-threading, which is currently not enabled.") endif() + endif() +# Not ideal to set this without the GPU acceleration, but the source presently requires GMX_GPU +# to be set to GMX_GPU_None for a non-GPU build to work. +set(GMX_GPU_ACCELERATION_FRAMEWORK "GMX_GPU_${_gmx_gpu_uppercase}") + if(CYGWIN) set(GMX_CYGWIN 1) endif() @@ -735,7 +720,6 @@ set(GMX_INSTALL_CMAKEDIR ${CMAKE_INSTALL_DATAROOTDIR}/cmake) # TODO: Make GMXRC adapt if this is changed set(GMX_INSTALL_PKGCONFIGDIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig) -set(GMX_INSTALL_OCLDIR ${GMX_INSTALL_GMXDATADIR}/opencl) list(APPEND INSTALLED_HEADER_INCLUDE_DIRS ${CMAKE_INSTALL_INCLUDEDIR}) @@ -814,13 +798,6 @@ endif() gmx_cpack_write_config() -# Issue a warning if NVIDIA GPUs were detected, but CUDA was not found. -# Don't bother the user after the first configure pass. -if ((CUDA_NOTFOUND_AUTO AND GMX_DETECT_GPU_AVAILABLE) AND NOT GMX_GPU_DETECTION_DONE) - message(WARNING "${CUDA_NOTFOUND_MESSAGE}") -endif() -set(GMX_GPU_DETECTION_DONE TRUE CACHE INTERNAL "Whether GPU detection has already been done") - ####################### ## uninstall target ####################### diff --git a/admin/gitlab-ci/documentation.gitlab-ci.yml b/admin/gitlab-ci/documentation.gitlab-ci.yml index 25a4c68133..0e3459d9ef 100644 --- a/admin/gitlab-ci/documentation.gitlab-ci.yml +++ b/admin/gitlab-ci/documentation.gitlab-ci.yml @@ -19,7 +19,7 @@ CMAKE_MPI_OPTIONS: "-DGMX_THREAD_MPI=OFF" CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=OFF" CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug" - CMAKE_GPU_OPTIONS: "-DGMX_GPU=OFF" + CMAKE_GPU_OPTIONS: "-DGMX_GPU=None" CMAKE_GMXAPI_OPTIONS: "-DGMX_PYTHON_PACKAGE=ON" script: - if [[ ! -z $GROMACS_RELEASE && $GROMACS_RELEASE == "true" ]] ; then @@ -86,7 +86,7 @@ CMAKE_MPI_OPTIONS: "-DGMX_THREAD_MPI=ON" CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=OFF" CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug" - CMAKE_GPU_OPTIONS: "-DGMX_GPU=OFF" + CMAKE_GPU_OPTIONS: "-DGMX_GPU=None" CMAKE_GMXAPI_OPTIONS: "-DGMX_PYTHON_PACKAGE=ON" RELEASE_BUILD_DIR: release-doc-builds RELEASE_SOURCE: release-source-from-tarball diff --git a/admin/gitlab-ci/global.gitlab-ci.yml b/admin/gitlab-ci/global.gitlab-ci.yml index 297b82d408..6420cc0b99 100644 --- a/admin/gitlab-ci/global.gitlab-ci.yml +++ b/admin/gitlab-ci/global.gitlab-ci.yml @@ -40,7 +40,7 @@ .use-cuda: variables: CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=OFF" - CMAKE_GPU_OPTIONS: -DGMX_GPU=ON -DGMX_USE_CUDA=ON + CMAKE_GPU_OPTIONS: -DGMX_GPU=CUDA .use-mpi: variables: @@ -49,7 +49,7 @@ .use-opencl: variables: CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=OFF" - CMAKE_GPU_OPTIONS: -DGMX_GPU=ON -DGMX_USE_OPENCL=ON + CMAKE_GPU_OPTIONS: -DGMX_GPU=OpenCL # Base definition for using gcc. .use-gcc:base: diff --git a/admin/gitlab-ci/gromacs.gitlab-ci.yml b/admin/gitlab-ci/gromacs.gitlab-ci.yml index 1deed908a8..13df73910b 100644 --- a/admin/gitlab-ci/gromacs.gitlab-ci.yml +++ b/admin/gitlab-ci/gromacs.gitlab-ci.yml @@ -17,7 +17,7 @@ simple-build: CMAKE_MPI_OPTIONS: "-DGMX_THREAD_MPI=ON" CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=OFF" CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug" - CMAKE_GPU_OPTIONS: "-DGMX_GPU=OFF" + CMAKE_GPU_OPTIONS: "-DGMX_GPU=None" CMAKE_GMXAPI_OPTIONS: "-DGMX_PYTHON_PACKAGE=OFF" COMPILER_MAJOR_VERSION: 9 BUILD_DIR: simple-build @@ -93,7 +93,7 @@ simple-build: CMAKE_MPI_OPTIONS: "-DGMX_THREAD_MPI=ON" CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=OFF" CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=Debug" - CMAKE_GPU_OPTIONS: "-DGMX_GPU=OFF" + CMAKE_GPU_OPTIONS: "-DGMX_GPU=None" script: - echo $CMAKE_COMPILER_SCRIPT - echo $CMAKE_EXTRA_OPTIONS @@ -145,7 +145,7 @@ simple-build: CMAKE_MPI_OPTIONS: "-DGMX_THREAD_MPI=ON" CMAKE_PRECISION_OPTIONS: "-DGMX_DOUBLE=OFF" CMAKE_BUILD_TYPE_OPTIONS: "-DCMAKE_BUILD_TYPE=RelWithAssert" - CMAKE_GPU_OPTIONS: "-DGMX_GPU=OFF" + CMAKE_GPU_OPTIONS: "-DGMX_GPU=None" CMAKE_REGRESSIONTEST_OPTIONS: "-DREGRESSIONTEST_PATH=../\\$RELEASE_REGRESSIONTESTS" RELEASE_BUILD_DIR: release-builds RELEASE_SOURCE: release-source-from-tarball diff --git a/cmake/gmxDetectGpu.cmake b/cmake/gmxDetectGpu.cmake deleted file mode 100644 index 7ccdade281..0000000000 --- a/cmake/gmxDetectGpu.cmake +++ /dev/null @@ -1,223 +0,0 @@ -# -# This file is part of the GROMACS molecular simulation package. -# -# Copyright (c) 2012,2018, 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 -# as published by the Free Software Foundation; either version 2.1 -# of the License, or (at your option) any later version. -# -# GROMACS is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with GROMACS; if not, see -# http://www.gnu.org/licenses, or write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# If you want to redistribute modifications to GROMACS, please -# consider that scientific software is very special. Version -# control is crucial - bugs must be traceable. We will be happy to -# consider code for inclusion in the official distribution, but -# derived work must not be called official GROMACS. Details are found -# in the README & COPYING files - if they are missing, get the -# official version at http://www.gromacs.org. -# -# To help us fund GROMACS development, we humbly ask that you cite -# the research papers on the package. Check out http://www.gromacs.org. - -# The gmx_detect_gpu() macro aims to detect GPUs available in the build machine -# and provide the number, names, and compute-capabilities of these devices. -# -# The current version is limited to checking the availability of NVIDIA GPUs -# without compute-capability information. -# -# The current detection relies on the following checks in the order of listing: -# - output of nvidia-smi (if available); -# - presence and content of of /proc/driver/nvidia/gpus/*/information (Linux) -# - output of lspci (Linux) -# -# If any of the checks succeeds in finding devices, consecutive checks will not -# be carried out. Additionally, when lspci is used and a device with unknown -# PCI ID is encountered, lspci tries to check the online PCI ID database. If -# this is not possible or the device is simply not recognized, no device names -# will be available. -# -# The following advanced variables are defined: -# - GMX_DETECT_GPU_AVAILABLE - TRUE if any GPUs were detected, otherwise FALSE -# - GMX_DETECT_GPU_COUNT - # of GPUs detected -# - GMX_DETECT_GPU_INFO - list of information strings of the detected GPUs -# -# NOTE: The proper solution is to detect hardware compatible with the native -# GPU acceleration. However, this requires checking the compute capability -# of the device which is not possible with the current checks and requires -# interfacing with the CUDA driver API. -# - -# check whether the number of GPUs machetes the number of elements in the GPU info list -macro(check_num_gpu_info NGPU GPU_INFO) - list(LENGTH ${GPU_INFO} _len) - if (NOT NGPU EQUAL _len) - list(APPEND ${GMX_DETECT_GPU_INFO} "NOTE: information about some GPU(s) missing!") - endif() -endmacro() - -macro(gmx_detect_gpu) - - if (NOT DEFINED GMX_DETECT_GPU_AVAILABLE OR - NOT DEFINED GMX_DETECT_GPU_COUNT OR - NOT DEFINED GMX_DETECT_GPU_INFO) - - set(GMX_DETECT_GPU_COUNT 0) - set(GMX_DETECT_GPU_INFO "") - - message(STATUS "Looking for NVIDIA GPUs present in the system") - - # nvidia-smi-based detection. - # Requires the nvidia-smi tool to be installed and available in the path - # or in one of the default search locations - if (NOT DEFINED GMX_DETECT_GPU_COUNT_NVIDIA_SMI) - # try to find the nvidia-smi binary - # TODO add location hints - find_program(_nvidia_smi "nvidia-smi") - if (_nvidia_smi) - set(GMX_DETECT_GPU_COUNT_NVIDIA_SMI 0) - # execute nvidia-smi -L to get a short list of GPUs available - exec_program(${_nvidia_smi_path} ARGS -L - OUTPUT_VARIABLE _nvidia_smi_out - RETURN_VALUE _nvidia_smi_ret) - # process the stdout of nvidia-smi - if (_nvidia_smi_ret EQUAL 0) - # convert string with newlines to list of strings - string(REGEX REPLACE "\n" ";" _nvidia_smi_out "${_nvidia_smi_out}") - foreach(_line ${_nvidia_smi_out}) - if (_line MATCHES "^GPU [0-9]+:") - math(EXPR GMX_DETECT_GPU_COUNT_NVIDIA_SMI "${GMX_DETECT_GPU_COUNT_NVIDIA_SMI}+1") - # the UUID is not very useful for the user, remove it - string(REGEX REPLACE " \\(UUID:.*\\)" "" _gpu_info "${_line}") - if (NOT _gpu_info STREQUAL "") - list(APPEND GMX_DETECT_GPU_INFO "${_gpu_info}") - endif() - endif() - endforeach() - - check_num_gpu_info(${GMX_DETECT_GPU_COUNT_NVIDIA_SMI} GMX_DETECT_GPU_INFO) - set(GMX_DETECT_GPU_COUNT ${GMX_DETECT_GPU_COUNT_NVIDIA_SMI}) - endif() - endif() - - unset(_nvidia_smi CACHE) - unset(_nvidia_smi_ret) - unset(_nvidia_smi_out) - unset(_gpu_name) - unset(_line) - endif() - - if (UNIX AND NOT (APPLE OR CYGWIN)) - # /proc/driver/nvidia/gpus/*/information-based detection. - # Requires the NVDIA closed source driver to be installed and loaded - if (NOT DEFINED GMX_DETECT_GPU_COUNT_PROC AND GMX_DETECT_GPU_COUNT EQUAL 0) - set(GMX_DETECT_GPU_COUNT_PROC 0) - file(GLOB _proc_nv_gpu_info "/proc/driver/nvidia/gpus/*/information") - foreach (_file ${_proc_nv_gpu_info}) - math(EXPR GMX_DETECT_GPU_COUNT_PROC "${GMX_DETECT_GPU_COUNT_PROC}+1") - # assemble information strings similar to the nvidia-smi output - # GPU ID = directory name on /proc/driver/nvidia/gpus/ - string(REGEX REPLACE "/proc/driver/nvidia/gpus.*([0-9]+).*information" "\\1" _gpu_id ${_file}) - # GPU name - file(STRINGS ${_file} _gpu_name LIMIT_COUNT 1 REGEX "^Model:.*" NO_HEX_CONVERSION) - string(REGEX REPLACE "^Model:[ \t]*(.*)" "\\1" _gpu_name "${_gpu_name}") - if (NOT _gpu_id STREQUAL "" AND NOT _gpu_name STREQUAL "") - list(APPEND GMX_DETECT_GPU_INFO "GPU ${_gpu_id}: ${_gpu_name}") - endif() - endforeach() - - check_num_gpu_info(${GMX_DETECT_GPU_COUNT_PROC} GMX_DETECT_GPU_INFO) - set(GMX_DETECT_GPU_COUNT ${GMX_DETECT_GPU_COUNT_PROC}) - - unset(_proc_nv_gpu_info) - unset(_gpu_name) - unset(_gpu_id) - unset(_file) - endif() - - # lspci-based detection (does not provide GPU information). - # Requires lspci and for GPU names to be fetched from the central - # PCI ID db if not available locally. - if (NOT DEFINED GMX_DETECT_GPU_COUNT_LSPCI AND GMX_DETECT_GPU_COUNT EQUAL 0) - set(GMX_DETECT_GPU_COUNT_LSPCI 0) - exec_program(lspci ARGS -q - OUTPUT_VARIABLE _lspci_out - RETURN_VALUE _lspci_ret) - # prehaps -q is not supported, try running without - if (NOT RETURN_VALUE EQUAL 0) - exec_program(lspci - OUTPUT_VARIABLE _lspci_out - RETURN_VALUE _lspci_ret) - endif() - if (_lspci_ret EQUAL 0) - # convert string with newlines to list of strings - STRING(REGEX REPLACE ";" "\\\\;" _lspci_out "${_lspci_out}") - string(REGEX REPLACE "\n" ";" _lspci_out "${_lspci_out}") - foreach(_line ${_lspci_out}) - string(TOUPPER "${_line}" _line_upper) - if (_line_upper MATCHES ".*VGA.*NVIDIA.*" OR _line_upper MATCHES ".*3D.*NVIDIA.*") - math(EXPR GMX_DETECT_GPU_COUNT_LSPCI "${GMX_DETECT_GPU_COUNT_LSPCI}+1") - # Try to parse out the device name which should be - # included in the lspci -q output between []-s - string(REGEX REPLACE ".*\\[(.*)\\].*" "\\1" _gpu_name "${_line}") - if (NOT _gpu_name EQUAL "") - list(APPEND GMX_DETECT_GPU_INFO "${_gpu_name}") - endif() - endif() - endforeach() - - check_num_gpu_info(${GMX_DETECT_GPU_COUNT_LSPCI} GMX_DETECT_GPU_INFO) - set(GMX_DETECT_GPU_COUNT ${GMX_DETECT_GPU_COUNT_LSPCI}) - endif() - - unset(_lspci_ret) - unset(_lspci_out) - unset(_gpu_name) - unset(_line) - unset(_line_upper) - endif() - endif() - - if (GMX_DETECT_GPU_COUNT GREATER 0) - set(GMX_DETECT_GPU_AVAILABLE YES) - else() - set(GMX_DETECT_GPU_AVAILABLE NO) - endif() - set(GMX_DETECT_GPU_AVAILABLE ${GMX_DETECT_GPU_AVAILABLE} CACHE BOOL "Whether any NVIDIA GPU was detected" FORCE) - - set(GMX_DETECT_GPU_COUNT ${GMX_DETECT_GPU_COUNT} - CACHE STRING "Number of NVIDIA GPUs detected") - set(GMX_DETECT_GPU_INFO ${GMX_DETECT_GPU_INFO} - CACHE STRING "basic information on the detected NVIDIA GPUs") - - set(GMX_DETECT_GPU_COUNT_NVIDIA_SMI ${GMX_DETECT_GPU_COUNT_NVIDIA_SMI} - CACHE INTERNAL "Number of NVIDIA GPUs detected using nvidia-smi") - set(GMX_DETECT_GPU_COUNT_PROC ${GMX_DETECT_GPU_COUNT_PROC} - CACHE INTERNAL "Number of NVIDIA GPUs detected in /proc/driver/nvidia/gpus") - set(GMX_DETECT_GPU_COUNT_LSPCI ${GMX_DETECT_GPU_COUNT_LSPCI} - CACHE INTERNAL "Number of NVIDIA GPUs detected using lspci") - - mark_as_advanced(GMX_DETECT_GPU_AVAILABLE - GMX_DETECT_GPU_COUNT - GMX_DETECT_GPU_INFO) - - if (GMX_DETECT_GPU_AVAILABLE) - message(STATUS "Number of NVIDIA GPUs detected: ${GMX_DETECT_GPU_COUNT} ") - else() - message(STATUS "Could not detect NVIDIA GPUs") - endif() - - endif() -endmacro(gmx_detect_gpu) diff --git a/cmake/gmxManageCuda.cmake b/cmake/gmxManageCuda.cmake new file mode 100644 index 0000000000..6d90f0e2e5 --- /dev/null +++ b/cmake/gmxManageCuda.cmake @@ -0,0 +1,112 @@ +# +# This file is part of the GROMACS molecular simulation package. +# +# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team. +# Copyright (c) 2017,2018,2019,2020, 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 +# as published by the Free Software Foundation; either version 2.1 +# of the License, or (at your option) any later version. +# +# GROMACS is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with GROMACS; if not, see +# http://www.gnu.org/licenses, or write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# If you want to redistribute modifications to GROMACS, please +# consider that scientific software is very special. Version +# control is crucial - bugs must be traceable. We will be happy to +# consider code for inclusion in the official distribution, but +# derived work must not be called official GROMACS. Details are found +# in the README & COPYING files - if they are missing, get the +# official version at http://www.gromacs.org. +# +# To help us fund GROMACS development, we humbly ask that you cite +# the research papers on the package. Check out http://www.gromacs.org. + + +# The earliest version of the CUDA toolkit that supports c++14 is 9.0 +set(REQUIRED_CUDA_VERSION 9.0) +set(REQUIRED_CUDA_COMPUTE_CAPABILITY 3.0) + +set(GMX_USE_CUDA ON) + +option(GMX_CLANG_CUDA "Use clang for CUDA" OFF) + +if(GMX_DOUBLE) + message(FATAL_ERROR "CUDA acceleration is not available in double precision") +endif() + +find_package(CUDA ${REQUIRED_CUDA_VERSION} REQUIRED) + +# 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 +# DEVICE_COMPILER_FLAGS - [output variable] device flags for the compiler +# HOST_COMPILER_FLAGS - [output variable] host flags for the compiler, if propagated +# +macro(get_cuda_compiler_info COMPILER_INFO DEVICE_COMPILER_FLAGS HOST_COMPILER_FLAGS) + if(NOT GMX_CLANG_CUDA) + 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) + set(${HOST_COMPILER_FLAGS} BUILD_CXXFLAGS) + else() + set(${HOST_COMPILER_FLAGS} "") + endif() + SET(${DEVICE_COMPILER_FLAGS} "${CUDA_NVCC_FLAGS}${CUDA_NVCC_FLAGS_${_build_type}}") + else() + SET(${COMPILER_INFO} "N/A") + SET(${COMPILER_FLAGS} "N/A") + endif() + endif() + else() + # CXX compiler is the CUDA compiler + set(${COMPILER_INFO} "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") + # there are some extra flags + set(${COMPILER_FLAGS} "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${_build_type}} ${GMX_CUDA_CLANG_FLAGS}") + endif() +endmacro () + +if(GMX_CLANG_CUDA) + include(gmxManageClangCudaConfig) + list(APPEND GMX_EXTRA_LIBRARIES ${GMX_CUDA_CLANG_LINK_LIBS}) + link_directories("${GMX_CUDA_CLANG_LINK_DIRS}") +else() + # Using NVIDIA compiler + if(NOT CUDA_NVCC_EXECUTABLE) + message(FATAL_ERROR "nvcc is required for a CUDA build, please set CUDA_TOOLKIT_ROOT_DIR appropriately") + endif() + # set up nvcc options + include(gmxManageNvccConfig) +endif() + +option(GMX_CUDA_NB_SINGLE_COMPILATION_UNIT "Whether to compile the CUDA non-bonded module using a single compilation unit." OFF) +mark_as_advanced(GMX_CUDA_NB_SINGLE_COMPILATION_UNIT) diff --git a/cmake/gmxManageGPU.cmake b/cmake/gmxManageGPU.cmake deleted file mode 100644 index 9dc1e6caba..0000000000 --- a/cmake/gmxManageGPU.cmake +++ /dev/null @@ -1,222 +0,0 @@ -# -# This file is part of the GROMACS molecular simulation package. -# -# Copyright (c) 2012,2013,2014,2015,2016 by the GROMACS development team. -# Copyright (c) 2017,2018,2019,2020, 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 -# as published by the Free Software Foundation; either version 2.1 -# of the License, or (at your option) any later version. -# -# GROMACS is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with GROMACS; if not, see -# http://www.gnu.org/licenses, or write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -# -# If you want to redistribute modifications to GROMACS, please -# consider that scientific software is very special. Version -# control is crucial - bugs must be traceable. We will be happy to -# consider code for inclusion in the official distribution, but -# derived work must not be called official GROMACS. Details are found -# in the README & COPYING files - if they are missing, get the -# official version at http://www.gromacs.org. -# -# 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 -# - check whether GPUs are present -# - if CUDA is not found but GPUs were detected issue a warning -if (NOT DEFINED GMX_GPU) - set(GMX_GPU_AUTO TRUE CACHE INTERNAL "GPU acceleration will be selected automatically") -else() - set(GMX_GPU_AUTO FALSE CACHE INTERNAL "GPU acceleration will be selected automatically") -endif() -option(GMX_GPU "Enable GPU acceleration" OFF) - -option(GMX_CLANG_CUDA "Use clang for CUDA" OFF) - -if(GMX_GPU AND GMX_DOUBLE) - message(FATAL_ERROR "GPU acceleration is not available in double precision!") -endif() -if(GMX_GPU_AUTO AND GMX_DOUBLE) - message(WARNING "GPU acceleration is not available in double precision, disabled!") - set_property(CACHE GMX_GPU PROPERTY VALUE OFF) - set_property(CACHE GMX_GPU_AUTO PROPERTY VALUE OFF) -endif() - -# detect GPUs in the build host machine -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 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() - - # Cmake tries to use the static cuda runtime by default, - # but this leads to unusable GPU builds on OS X. - if(APPLE) - set(CUDA_USE_STATIC_CUDA_RUNTIME OFF CACHE STRING "Use the static version of the CUDA runtime library if available") - endif() - - find_package(CUDA ${REQUIRED_CUDA_VERSION} ${FIND_CUDA_QUIETLY}) -endif() - -# Depending on the current vale of GMX_GPU and GMX_GPU_AUTO: -# - OFF, FALSE: Will skip this detection/setup. -# - 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 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) - # assemble warning/error message - if (GMX_DETECT_GPU_AVAILABLE) - 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}") - 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") - endif() - - set(CUDA_NOTFOUND_MESSAGE "mdrun supports native GPU acceleration on NVIDIA hardware with compute capability >= ${REQUIRED_CUDA_COMPUTE_CAPABILITY} (Kepler 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}") - unset(_msg) - - if (NOT CUDA_FOUND) - if (GMX_GPU_AUTO) - # Disable GPU acceleration in auto mode - message(STATUS "No compatible CUDA toolkit found (v5.0+), disabling native GPU acceleration") - set_property(CACHE GMX_GPU PROPERTY VALUE OFF) - set(CUDA_NOTFOUND_AUTO ON) - else() - # the user requested CUDA, but it wasn't found - message(FATAL_ERROR "${CUDA_NOTFOUND_MESSAGE}") - endif() - else() - if (GMX_GPU_AUTO) - message(STATUS "Enabling native GPU acceleration") - set_property(CACHE GMX_GPU PROPERTY VALUE ON) - endif() - endif() -endif() - -# Annoyingly enough, FindCUDA leaves a few variables behind as non-advanced. -# We need to mark these advanced outside the conditional, otherwise, if the -# user turns GMX_GPU=OFF after a failed cmake pass, these variables will be -# left behind in the cache. -mark_as_advanced(CUDA_SDK_ROOT_DIR - CUDA_USE_STATIC_CUDA_RUNTIME - CUDA_dl_LIBRARY CUDA_rt_LIBRARY - ) -if(NOT GMX_GPU) - mark_as_advanced(CUDA_TOOLKIT_ROOT_DIR) - mark_as_advanced(CUDA_HOST_COMPILER) -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 -# DEVICE_COMPILER_FLAGS - [output variable] device flags for the compiler -# HOST_COMPILER_FLAGS - [output variable] host flags for the compiler, if propagated -# -macro(get_cuda_compiler_info COMPILER_INFO DEVICE_COMPILER_FLAGS HOST_COMPILER_FLAGS) - if(NOT GMX_CLANG_CUDA) - 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) - set(${HOST_COMPILER_FLAGS} BUILD_CXXFLAGS) - else() - set(${HOST_COMPILER_FLAGS} "") - endif() - SET(${DEVICE_COMPILER_FLAGS} "${CUDA_NVCC_FLAGS}${CUDA_NVCC_FLAGS_${_build_type}}") - else() - SET(${COMPILER_INFO} "N/A") - SET(${COMPILER_FLAGS} "N/A") - endif() - endif() - else() - # CXX compiler is the CUDA compiler - set(${COMPILER_INFO} "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}") - # there are some extra flags - set(${COMPILER_FLAGS} "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${_build_type}} ${GMX_CUDA_CLANG_FLAGS}") - endif() -endmacro () - -macro(enable_multiple_cuda_compilation_units) - message(STATUS "Enabling multiple compilation units for the CUDA non-bonded module.") - set_property(CACHE GMX_CUDA_NB_SINGLE_COMPILATION_UNIT PROPERTY VALUE OFF) -endmacro() - -include(CMakeDependentOption) -include(gmxOptionUtilities) -macro(gmx_gpu_setup) - if(GMX_GPU) - if(NOT GMX_CLANG_CUDA) - if(NOT CUDA_NVCC_EXECUTABLE) - message(FATAL_ERROR "nvcc is required for a CUDA build, please set CUDA_TOOLKIT_ROOT_DIR appropriately") - endif() - # set up nvcc options - include(gmxManageNvccConfig) - else() - include(gmxManageClangCudaConfig) - endif() - - # no OpenMP is no good! - if(NOT GMX_OPENMP) - 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() - endif() # GMX_GPU - - option(GMX_CUDA_NB_SINGLE_COMPILATION_UNIT "Whether to compile the CUDA non-bonded module using a single compilation unit." OFF) - mark_as_advanced(GMX_CUDA_NB_SINGLE_COMPILATION_UNIT) - -endmacro() diff --git a/cmake/gmxManageOpenCL.cmake b/cmake/gmxManageOpenCL.cmake index b6d90abad8..402ecacb45 100644 --- a/cmake/gmxManageOpenCL.cmake +++ b/cmake/gmxManageOpenCL.cmake @@ -33,8 +33,15 @@ # To help us fund GROMACS development, we humbly ask that you cite # the research papers on the package. Check out http://www.gromacs.org. +# OpenCL required version: 1.2 or newer +set(REQUIRED_OPENCL_MIN_VERSION_MAJOR 1) +set(REQUIRED_OPENCL_MIN_VERSION_MINOR 2) +set(REQUIRED_OPENCL_MIN_VERSION ${REQUIRED_OPENCL_MIN_VERSION_MAJOR}.${REQUIRED_OPENCL_MIN_VERSION_MINOR}) + +set(GMX_USE_OPENCL ON) + if(GMX_DOUBLE) - message(FATAL_ERROR "OpenCL not available in double precision - Yet!") + message(FATAL_ERROR "OpenCL acceleration is not available in double precision") endif() # for some reason FindOpenCL checks CUDA_PATH but not CUDA_HOME @@ -75,9 +82,4 @@ endif() set(GMX_OPENCL_NB_CLUSTER_SIZE 8 CACHE STRING "Cluster size used by nonbonded OpenCL kernel. Set to 4 for Intel GPUs.") mark_as_advanced(GMX_OPENCL_NB_CLUSTER_SIZE) -macro(gmx_gpu_setup) - # no OpenMP is no good! - if(NOT GMX_OPENMP) - 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() +set(GMX_INSTALL_OCLDIR ${GMX_INSTALL_GMXDATADIR}/opencl) diff --git a/docs/install-guide/index.rst b/docs/install-guide/index.rst index 4b00aa572b..e89f228388 100644 --- a/docs/install-guide/index.rst +++ b/docs/install-guide/index.rst @@ -72,8 +72,8 @@ appropriate value instead of ``xxx`` : * ``-DCMAKE_C_COMPILER=xxx`` equal to the name of the C99 `Compiler`_ you wish to use (or the environment variable ``CC``) * ``-DCMAKE_CXX_COMPILER=xxx`` equal to the name of the C++98 `compiler`_ you wish to use (or the environment variable ``CXX``) * ``-DGMX_MPI=on`` to build using `MPI support`_ (generally good to combine with `building only mdrun`_) -* ``-DGMX_GPU=on`` to build using nvcc to run using NVIDIA `CUDA GPU acceleration`_ or an OpenCL_ GPU -* ``-DGMX_USE_OPENCL=on`` to build with OpenCL_ support enabled. ``GMX_GPU`` must also be set. +* ``-DGMX_GPU=CUDA`` to build with NVIDIA CUDA support enabled. +* ``-DGMX_GPU=OpenCL`` to build with OpenCL_ support enabled. * ``-DGMX_SIMD=xxx`` to specify the level of `SIMD support`_ of the node on which |Gromacs| will run * ``-DGMX_BUILD_MDRUN_ONLY=on`` for `building only mdrun`_, e.g. for compute cluster back-end nodes * ``-DGMX_DOUBLE=on`` to build |Gromacs| in double precision (slower, and not normally useful) @@ -502,7 +502,7 @@ For example, the following command line :: - cmake .. -DGMX_GPU=ON -DGMX_MPI=ON -DCMAKE_INSTALL_PREFIX=/home/marydoe/programs + cmake .. -DGMX_GPU=CUDA -DGMX_MPI=ON -DCMAKE_INSTALL_PREFIX=/home/marydoe/programs can be used to build with CUDA GPUs, MPI and install in a custom location. You can even save that in a shell script to make it even @@ -650,7 +650,7 @@ If you have the CUDA_ Toolkit installed, you can use ``cmake`` with: :: - cmake .. -DGMX_GPU=ON -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda + cmake .. -DGMX_GPU=CUDA -DCUDA_TOOLKIT_ROOT_DIR=/usr/local/cuda (or whichever path has your installation). In some cases, you might need to specify manually which of your C++ compilers should be used, @@ -725,7 +725,7 @@ To trigger an OpenCL_ build the following CMake flags must be set :: - cmake .. -DGMX_GPU=ON -DGMX_USE_OPENCL=ON + cmake .. -DGMX_GPU=OpenCL To build with support for Intel integrated GPUs, it is required to add ``-DGMX_OPENCL_NB_CLUSTER_SIZE=4`` to the cmake command line, @@ -743,7 +743,7 @@ external library, use :: - cmake .. -DGMX_GPU=ON -DGMX_USE_OPENCL=ON -DclFFT_ROOT_DIR=/path/to/your/clFFT -DGMX_EXTERNAL_CLFFT=TRUE + cmake .. -DGMX_GPU=OpenCL -DclFFT_ROOT_DIR=/path/to/your/clFFT -DGMX_EXTERNAL_CLFFT=TRUE Static linking ~~~~~~~~~~~~~~ @@ -1073,7 +1073,7 @@ directory: cd .. mkdir build-mdrun-only cd build-mdrun-only - cmake .. -DGMX_MPI=ON -DGMX_GPU=ON -DGMX_BUILD_MDRUN_ONLY=ON -DCMAKE_INSTALL_PREFIX=/your/installation/prefix/here + cmake .. -DGMX_MPI=ON -DGMX_GPU=CUDA -DGMX_BUILD_MDRUN_ONLY=ON -DCMAKE_INSTALL_PREFIX=/your/installation/prefix/here make -j 4 make install cd /to/your/unpacked/regressiontests diff --git a/docs/release-notes/2021/major/miscellaneous.rst b/docs/release-notes/2021/major/miscellaneous.rst index 6ba6240673..fa547d4186 100644 --- a/docs/release-notes/2021/major/miscellaneous.rst +++ b/docs/release-notes/2021/major/miscellaneous.rst @@ -7,9 +7,21 @@ Miscellaneous Also, please use the syntax :issue:`number` to reference issues on GitLab, without the a space between the colon and number! +Uniform and manual CMake GPU-support configuration +"""""""""""""""""""""""""""""""""""""""""""""""""" +The GPU accelerations setup has been changed to be uniform for CUDA and OpenCL. Either +option is now enabled by setting GMX_GPU to CUDA or OpenCL in the CMake configuration. +To simplify the CMake code, we have also moved away from automated option selection +based on the build host. In particular, this means that CUDA will not be enabled unless +the GMX_GPU option is explicitly enabled, and CMake will no longer perform the extra +steps of trying to detect hardware and propose to install CUDA if hardware is available. +Apart from the simplification, this should also make it easier to handle multiple +different accelerator APIs targeting e.g. NVIDIA hardware. + Configuration-time trivalue options changed from autodetection to boolean on/off """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" To simplify the CMake configuration and avoid having multiple settings that change outside of the users direct control we have removed the support for automatically setting booleans. GMX_BUILD_HELP and GMX_HWLOC are now disabled by default, while GMX_LOAD_PLUGINS is enabled by default. + diff --git a/docs/user-guide/mdrun-performance.rst b/docs/user-guide/mdrun-performance.rst index 1769f8e4b4..d14e4fe43d 100644 --- a/docs/user-guide/mdrun-performance.rst +++ b/docs/user-guide/mdrun-performance.rst @@ -1359,7 +1359,7 @@ of 2. So it can be useful go through the checklist. * Make sure your compiler supports OpenMP (some versions of Clang don't). * If you have GPUs that support either CUDA or OpenCL, use them. - * Configure with ``-DGMX_GPU=ON`` (add ``-DGMX_USE_OPENCL=ON`` for OpenCL). + * Configure with ``-DGMX_GPU=CUDA `` or ``-DGMX_GPU=OpenCL``. * For CUDA, use the newest CUDA available for your GPU to take advantage of the latest performance enhancements. * Use a recent GPU driver. -- 2.22.0