2 # This file is part of the GROMACS molecular simulation package.
4 # Copyright (c) 2020,2021, by the GROMACS development team, led by
5 # Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 # and including many others, as listed in the AUTHORS file in the
7 # top-level source directory and at http://www.gromacs.org.
9 # GROMACS is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU Lesser General Public License
11 # as published by the Free Software Foundation; either version 2.1
12 # of the License, or (at your option) any later version.
14 # GROMACS is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 # Lesser General Public License for more details.
19 # You should have received a copy of the GNU Lesser General Public
20 # License along with GROMACS; if not, see
21 # http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 # If you want to redistribute modifications to GROMACS, please
25 # consider that scientific software is very special. Version
26 # control is crucial - bugs must be traceable. We will be happy to
27 # consider code for inclusion in the official distribution, but
28 # derived work must not be called official GROMACS. Details are found
29 # in the README & COPYING files - if they are missing, get the
30 # official version at http://www.gromacs.org.
32 # To help us fund GROMACS development, we humbly ask that you cite
33 # the research papers on the package. Check out http://www.gromacs.org.
35 # OpenCL required version: 1.2 or newer
36 set(REQUIRED_SYCL_MIN_VERSION_MAJOR 1)
37 set(REQUIRED_SYCL_MIN_VERSION_MINOR 2)
38 set(REQUIRED_SYCL_MIN_VERSION ${REQUIRED_SYCL_MIN_VERSION_MAJOR}.${REQUIRED_SYCL_MIN_VERSION_MINOR})
42 # CMake issue tracking the efforts to make a universal upstream module:
43 # https://gitlab.kitware.com/cmake/cmake/-/issues/21711
45 option(GMX_SYCL_HIPSYCL "Use hipSYCL instead of Intel/Clang for SYCL compilation" OFF)
48 message(FATAL_ERROR "SYCL acceleration is not available in double precision")
51 include(gmxFindFlagsForSource)
53 # Return all current CMake variables with name starting with "hipsycl" (case-insensitive).
54 # Result is in the form of a list of flags ("-Dfoo=bar;-Dbaz=true").
55 # Semicolons in values are escaped (needed for HIPSYCL_TARGETS).
56 function(_getHipSyclCmakeFlags RETURN_VAR)
57 get_cmake_property(_VARS VARIABLES)
60 foreach (_VARNAME ${_VARS})
61 string(TOLOWER "${_VARNAME}" _VARNAME_LOWER)
62 if (${_VARNAME_LOWER} MATCHES "^hipsycl")
63 # Escape semicolon. The number of backslashes was determined empirically.
64 string(REPLACE ";" "\\\\\\;" _VARVALUE "${${_VARNAME}}")
67 -D${_VARNAME}=${_VARVALUE}
71 set("${RETURN_VAR}" ${RESULT} PARENT_SCOPE)
75 set(HIPSYCL_CLANG "${CMAKE_CXX_COMPILER}")
76 # -Wno-unknown-cuda-version because Clang-11 complains about CUDA 11.0-11.2, despite working fine with them.
77 # -Wno-unknown-attributes because hipSYCL does not support reqd_sub_group_size (because it can only do some sub group sizes).
78 set(HIPSYCL_SYCLCC_EXTRA_ARGS "-Wno-unknown-cuda-version -Wno-unknown-attributes")
80 # Must be called before find_package to capture all user-set CMake variables, but not those set automatically
81 _getHipSyclCmakeFlags(_ALL_HIPSYCL_CMAKE_FLAGS)
83 find_package(hipsycl REQUIRED)
84 # Ensure the try_compile projects below find the same hipsycl)
85 list(APPEND _ALL_HIPSYCL_CMAKE_FLAGS -Dhipsycl_DIR=${hipsycl_DIR})
87 # If the user-set CMake variables change (e.g. because the user
88 # changed HIPSYCL_TARGETS), then the try_compile tests below need
89 # to be re-run. Set and use an internal cache variable to detect
90 # the change and set a flag to rerun the tests.
91 if (DEFINED GMX_ALL_HIPSYCL_CMAKE_FLAGS_COPY AND "${GMX_ALL_HIPSYCL_CMAKE_FLAGS_COPY}" STREQUAL "${_ALL_HIPSYCL_CMAKE_FLAGS}")
92 set(_rerun_hipsycl_try_compile_tests FALSE)
94 # The new value should over-write the previous copy
95 set(GMX_ALL_HIPSYCL_CMAKE_FLAGS_COPY ${_ALL_HIPSYCL_CMAKE_FLAGS} CACHE INTERNAL "Store the list of CMake variables needed for hipSYCL compilation test projects")
96 set(_rerun_hipsycl_try_compile_tests TRUE)
99 # Does the hipSYCL compiler work at all for the given targets?
100 if (NOT DEFINED GMX_HIPSYCL_COMPILATION_WORKS OR _rerun_hipsycl_try_compile_tests)
101 message(STATUS "Checking for valid hipSYCL compiler")
102 try_compile(GMX_HIPSYCL_COMPILATION_WORKS "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest" "${CMAKE_SOURCE_DIR}/cmake/HipSyclTest/" "HipSyclTest"
103 OUTPUT_VARIABLE _HIPSYCL_COMPILATION_OUTPUT
105 ${_ALL_HIPSYCL_CMAKE_FLAGS})
106 file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest")
107 if(GMX_HIPSYCL_COMPILATION_WORKS)
108 message(STATUS "Checking for valid hipSYCL compiler - Success")
111 if (NOT GMX_HIPSYCL_COMPILATION_WORKS)
112 message(FATAL_ERROR "hipSYCL compiler not working:\n${_HIPSYCL_COMPILATION_OUTPUT}")
115 # Does hipSYCL compilation target CUDA devices?
116 if(NOT DEFINED GMX_HIPSYCL_HAVE_CUDA_TARGET OR _rerun_hipsycl_try_compile_tests)
117 message(STATUS "Checking for hipSYCL CUDA target")
118 try_compile(GMX_HIPSYCL_HAVE_CUDA_TARGET "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest" "${CMAKE_SOURCE_DIR}/cmake/HipSyclTest/" "HipSyclTest"
120 -DCHECK_CUDA_TARGET=ON
121 ${_ALL_HIPSYCL_CMAKE_FLAGS})
122 file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest")
123 if(GMX_HIPSYCL_HAVE_CUDA_TARGET)
124 message(STATUS "Checking for hipSYCL CUDA target - Success")
126 message(STATUS "Checking for hipSYCL CUDA target - Failed")
130 # Does hipSYCL compilation target HIP devices?
131 if(NOT DEFINED GMX_HIPSYCL_HAVE_HIP_TARGET OR _rerun_hipsycl_try_compile_tests)
132 message(STATUS "Checking for hipSYCL HIP target")
133 try_compile(GMX_HIPSYCL_HAVE_HIP_TARGET "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest" "${CMAKE_SOURCE_DIR}/cmake/HipSyclTest/" "HipSyclTest"
135 -DCHECK_HIP_TARGET=ON
136 ${_ALL_HIPSYCL_CMAKE_FLAGS})
137 file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest")
138 if(GMX_HIPSYCL_HAVE_HIP_TARGET)
139 message(STATUS "Checking for hipSYCL HIP target - Success")
141 message(STATUS "Checking for hipSYCL HIP target - Failed")
145 # Does hipSYCL compilation target Intel Level0 devices?
146 if(NOT DEFINED GMX_HIPSYCL_HAVE_LEVELZERO_TARGET OR _rerun_hipsycl_try_compile_tests)
147 message(STATUS "Checking for hipSYCL LevelZero target")
148 try_compile(GMX_HIPSYCL_HAVE_LEVELZERO_TARGET "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest" "${CMAKE_SOURCE_DIR}/cmake/HipSyclTest/" "HipSyclTest"
150 -DCHECK_LEVELZERO_TARGET=ON
151 ${_ALL_HIPSYCL_CMAKE_FLAGS})
152 file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/CMakeTmpHipSyclTest")
153 if(GMX_HIPSYCL_HAVE_LEVELZERO_TARGET)
154 message(STATUS "Checking for hipSYCL LevelZero target - Success")
155 message(WARNING "GROMACS does not support LevelZero backend of hipSYCL")
157 message(STATUS "Checking for hipSYCL LevelZero target - Failed")
161 if(NOT GMX_HIPSYCL_HAVE_CUDA_TARGET AND NOT GMX_HIPSYCL_HAVE_HIP_TARGET)
162 message(WARNING "hipSYCL has no GPU targets set! Please, specify target hardware with -DHIPSYCL_TARGETS CMake option")
164 if(GMX_HIPSYCL_HAVE_CUDA_TARGET AND GMX_HIPSYCL_HAVE_HIP_TARGET)
165 message(FATAL_ERROR "hipSYCL cannot have both CUDA and HIP targets active! This would require explicit multipass mode which both decreases performance on NVIDIA devices and has been removed in clang 12. Compile only for either CUDA or HIP targets.")
167 unset(_rerun_hipsycl_try_compile_tests)
169 if(CMAKE_CXX_COMPILER MATCHES "dpcpp")
170 # At least Intel dpcpp defaults to having SYCL enabled for all code. This leads to two problems:
172 # 1. Compiles take ~3x longer, since every file has to be compiled for multiple targets.
173 # 2. We get a ton of warnings for the device-specific pass when the compiler sees our SIMD code.
175 # To avoid this, we attempt to find a flag to disable SYCL for non-SYCL files. Unfortunately,
176 # when using gmx_find_flag_for_source() that includes calling check_cxx_compiler_flag(),
177 # this in turn exposes a bug in dpcpp, where an object file compiles with -fno-sycl leads to
178 # a failed link stage (when the same flag is not used). Since none of this is critical, we handle
179 # it by merely checking if it works to compile a source fils with this flag, and choking if SYCL
182 if(NOT CHECK_DISABLE_SYCL_CXX_FLAGS_QUIETLY)
183 message(STATUS "Checking for flags to disable SYCL")
186 gmx_check_source_compiles_with_flags(
187 "int main() { return 0; }"
190 DISABLE_SYCL_CXX_FLAGS_RESULT)
192 if(DISABLE_SYCL_CXX_FLAGS_RESULT)
193 set(DISABLE_SYCL_CXX_FLAGS "-fno-sycl")
195 if(NOT CHECK_DISABLE_SYCL_CXX_FLAGS_QUIETLY)
196 if(DISABLE_SYCL_CXX_FLAGS_RESULT)
197 message(STATUS "Checking for flags to disable SYCL - -fno-sycl")
199 message(WARNING "Cannot find flags to disable SYCL for non-SYCL hardware-specific C++ code. Expect many warnings, but they are likely benign.")
201 set(CHECK_DISABLE_SYCL_CXX_FLAGS_QUIETLY 1 CACHE INTERNAL "Keep quiet on future calls to detect no-SYCL flags" FORCE)
205 # Find the flags to enable (or re-enable) SYCL with Intel extensions. In case we turned it off above,
206 # it's important that we check the combination of both flags, to make sure the second one re-enables SYCL.
207 if(NOT CHECK_SYCL_CXX_FLAGS_QUIETLY)
208 message(STATUS "Checking for flags to enable SYCL")
210 gmx_find_flag_for_source(SYCL_CXX_FLAGS_RESULT
211 "#include <CL/sycl.hpp>
212 namespace sycl = cl::sycl;
214 sycl::queue q(sycl::default_selector{});
217 " "CXX" DISABLE_SYCL_CXX_FLAGS SYCL_CXX_FLAGS "-fsycl -fsycl-device-code-split=per_kernel")
219 if(NOT CHECK_SYCL_CXX_FLAGS_QUIETLY)
220 if(SYCL_CXX_FLAGS_RESULT)
221 message(STATUS "Checking for flags to enable SYCL - ${SYCL_CXX_FLAGS}")
223 set(CHECK_SYCL_CXX_FLAGS_QUIETLY 1 CACHE INTERNAL "Keep quiet on future calls to detect SYCL flags" FORCE)
226 if(NOT SYCL_CXX_FLAGS_RESULT)
227 message(FATAL_ERROR "Cannot compile with SYCL Intel compiler. Try a different compiler or disable SYCL.")
230 # Add function wrapper similar to the one used by ComputeCPP and hipSYCL
231 function(add_sycl_to_target)
232 cmake_parse_arguments(
233 PARSE_ARGV 0 # No positional arguments
234 ARGS # Prefix for the resulting variables
236 "TARGET" # One-value keyword
237 "SOURCES" # Multi-value keyword
239 set_source_files_properties(${ARGS_SOURCES} PROPERTIES COMPILE_FLAGS "${SYCL_CXX_FLAGS}")
240 target_link_libraries(${ARGS_TARGET} PRIVATE ${SYCL_CXX_FLAGS})
241 endfunction(add_sycl_to_target)