diff --git a/.github/workflows/cmake_ci.yml b/.github/workflows/cmake_ci.yml index d5cf0cd14..9b483ecbf 100644 --- a/.github/workflows/cmake_ci.yml +++ b/.github/workflows/cmake_ci.yml @@ -1,69 +1,52 @@ name: cmake ci linux macos windows -on: - push: - release: - types: [published] + +on: [push, pull_request] jobs: + prepare: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.generate_matrix.outputs.matrix }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Generate matrix + id: generate_matrix + run: | + echo "MACOSX_DEPLOYMENT_TARGET=11.0" >> $GITHUB_ENV + MATRIX=$(python3 ${{ github.workspace }}/.github/workflows/generate_cmake_matrix.py) + echo "matrix=$MATRIX" >> $GITHUB_OUTPUT cmake-ci: runs-on: ${{ matrix.os }} + needs: prepare strategy: fail-fast: false - matrix: - os: - - windows-2022 - - ubuntu-22.04 - - macos-13 - compiler: - - llvm - - gcc-12 - # you can specify the version after `-` like `llvm-13.0.0`. - generator: - - "Ninja" - build_type: - - Release - finufft_static_linking: - - ON - include: - - os: "windows-2022" - compiler: "msvc" - generator: "Ninja" - build_type: "Release" - finufft_static_linking: "OFF" - exclude: - - os: "windows-2022" - compiler: "gcc-12" - generator: "Ninja" - build_type: "Release" + matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }} steps: - - uses: actions/checkout@v4 - - - name: Unlink gcc - if: runner.os == 'macOS' - run: | - brew unlink gcc - continue-on-error: true - + - name: Checkout code + uses: actions/checkout@v4 - name: Setup Cpp uses: aminya/setup-cpp@v1 with: - compiler: ${{ matrix.compiler }} + compiler: ${{ matrix.toolchain }} vcvarsall: ${{ contains(matrix.os, 'windows') }} cmake: true ninja: true vcpkg: false cppcheck: false clangtidy: false - - - name: Install macOS dependencies + - name: Set min macOS version and install fftw if: runner.os == 'macOS' run: | brew install fftw - + - name: Install fftw + if: runner.os == 'linux' + run: | + sudo apt update + sudo apt install -y libfftw3-dev - name: Configure Cmake run: | - cmake -S . -B ./build -G "${{matrix.generator}}" -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DFINUFFT_BUILD_TESTS=ON -DFINUFFT_STATIC_LINKING=${{matrix.finufft_static_linking}} - + cmake -S . -B ./build -G Ninja -DCMAKE_BUILD_TYPE:STRING=${{matrix.build_type}} -DFINUFFT_ARCH_FLAGS=${{ matrix.arch_flags }} -DFINUFFT_BUILD_TESTS=ON -DFINUFFT_STATIC_LINKING=${{matrix.finufft_static_linking}} -DFINUFFT_USE_DUCC0=${{ matrix.ducc_fft }} - name: Build run: | cmake --build ./build --config ${{matrix.build_type}} @@ -71,31 +54,4 @@ jobs: - name: Test working-directory: ./build run: | - ctest -C ${{matrix.build_type}} - - # may change to cpack and action-gh-release later - - name: Upload static and shared lib - uses: actions/upload-artifact@v4 - with: - name: ${{matrix.os}}-${{matrix.compiler}}-finufft-lib - path: ${{runner.workspace}}/finufft/build/*finufft* - - - name: Pack For Release - if: startsWith(github.ref, 'refs/tags/') && github.event_name == 'release' && github.event.action == 'published' - shell: bash - run: | - cd build - if [[ "${{ matrix.os }}" == "windows-2022" ]] - then - 7z a ../${{matrix.os}}-${{matrix.compiler}}-finufft-lib.zip *finufft* - else - tar czvf ../${{matrix.os}}-${{matrix.compiler}}-finufft-lib.tar.gz *finufft* - fi - cd - - - - name: Publish - uses: softprops/action-gh-release@v1 - if: startsWith(github.ref, 'refs/tags/') && github.event_name == 'release' && github.event.action == 'published' - with: - files: | - *-finufft-lib* + ctest -C ${{matrix.build_type}} --output-on-failure diff --git a/.github/workflows/generate_cmake_matrix.py b/.github/workflows/generate_cmake_matrix.py new file mode 100644 index 000000000..3618e2edf --- /dev/null +++ b/.github/workflows/generate_cmake_matrix.py @@ -0,0 +1,76 @@ +import json + +matrix = { + "include": [] +} + +static_linking = ["On", "Off"] + +combinations = [ + ("ubuntu-22.04", { + "build_type": ["Release", "Debug"], + "toolchain": ["llvm", "gcc"], + "arch_flags": ["-march=native", "-march=x86-64", "native"], + "ducc_fft": ["On", "Off"] + }), + ("windows-2022", { + "build_type": ["Release", "Debug"], + "toolchain": ["msvc"], + "arch_flags": ["/arch:AVX2", "/arch:SSE2", "native"], + "ducc_fft": ["On", "Off"] + }), + ("windows-2022", { + "build_type": ["Release"], + "toolchain": ["llvm"], + "arch_flags": ["-march=native", "-march=x86-64", "native"], + "ducc_fft": ["On", "Off"] + }), + ("macos-13", { + "build_type": ["Release", "Debug"], + "toolchain": ["llvm", "gcc-14"], + "arch_flags": ["-march=native", "-march=x86-64", "native"], + "ducc_fft": ["On", "Off"] + }) +] + + +def get_c_compiler(toolchain): + if "gcc" in toolchain: + return "gcc" + elif toolchain == "llvm": + return "clang" + elif toolchain == "msvc": + return "cl" + else: + raise ValueError(f"Unknown toolchain: {toolchain}") + + +def get_cxx_compiler(toolchain): + if "gcc" in toolchain: + return "g++" + elif toolchain == "llvm": + return "clang++" + elif toolchain == "msvc": + return "cl" + else: + raise ValueError(f"Unknown toolchain: {toolchain}") + + +for platform, value in combinations: + for toolchain in value["toolchain"]: + for arch_flag in value["arch_flags"]: + for linking in static_linking: + for build in value["build_type"]: + for ducc in value["ducc_fft"]: + matrix["include"].append({ + "os": platform, + "toolchain": toolchain, + "arch_flags": arch_flag, + "finufft_static_linking": linking, + "build_type": build, + "c_compiler": get_c_compiler(toolchain), + "cxx_compiler": get_cxx_compiler(toolchain), + "ducc_fft": ducc + }) +json_str = json.dumps(matrix, ensure_ascii=False) +print(json_str) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ac25e3f63..1b57288a0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,3 +10,11 @@ repos: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace + - repo: https://github.com/cheshirekow/cmake-format-precommit + rev: v0.6.13 + hooks: + - id: cmake-format + additional_dependencies: [pyyaml] + args: [--line-width=180] + types: [file] + files: (\.cmake|CMakeLists.txt)(.in)?$ diff --git a/CHANGELOG b/CHANGELOG index e7b302c48..ad01f7c9c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -47,6 +47,11 @@ V 2.3.0beta (7/24/24) any 32-bit integers to 64-bit when calling cufinufft(f)_setpts. Note that internally, 32-bit integers are still used, so calling cufinufft with more than 2e9 points will fail. This restriction may be lifted in the future. +* cmake build system revamped completely, more modern practices. + It auto selects compiler flags based on the supported ones on all operating systems. + Added support for Windows (llvm, msvc), Linux (llvm, gcc) and MacOS (llvm, gcc). +* cmake support for both ducc0 and fftw +* cmake adding nvcc and msvc optimization flags V 2.2.0 (12/12/23) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ca851dfe..b20322519 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,313 +1,329 @@ -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.19...3.30) +project( + FINUFFT + VERSION 2.2.0 + LANGUAGES C CXX) -project(FINUFFT VERSION 2.2.0 LANGUAGES C CXX) +# windows MSVC runtime flags policy +cmake_policy(SET CMP0091 NEW) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +include(CMakeDependentOption) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -include(CheckCXXCompilerFlag) - -set(GNU_LIKE_FRONTENDS AppleClang Clang GNU) -if (CMAKE_CXX_COMPILER_ID IN_LIST GNU_LIKE_FRONTENDS) - # Set custom compiler flags for gcc-compatible compilers - set(FINUFFT_CXX_FLAGS_RELEASE -O3 - -funroll-loops - -ffp-contract=fast - -fno-math-errno - -fno-signed-zeros - -fno-trapping-math - -fassociative-math - -freciprocal-math - -fmerge-all-constants - -ftree-vectorize - ) - # if -fimplicit-constexpr is supported, add it to the list of flags - check_cxx_compiler_flag("-fimplicit-constexpr" COMPILER_SUPPORTS_FIMPLICIT_CONSTEXPR) - if (COMPILER_SUPPORTS_FIMPLICIT_CONSTEXPR) - list(APPEND FINUFFT_CXX_FLAGS_RELEASE -fimplicit-constexpr) - endif () - set(FINUFFT_CXX_FLAGS_RELWITHDEBINFO -g ${FINUFFT_CXX_FLAGS_RELEASE}) -endif () - -include(CTest) -# Set default build type to Release -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release CACHE STRING "Set the default build type to Release" FORCE) -endif() - -if (CMAKE_CXX_COMPILER_ID IN_LIST GNU_LIKE_FRONTENDS AND NOT DEFINED FINUFFT_ARCH_FLAGS) - if (CMAKE_SYSTEM_PROCESSOR MATCHES "ppc|ppc64|powerpc|powerpc64" OR (APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc|ppc64")) - # PowerPC arch does not have -march flag. - set(FINUFFT_ARCH_FLAGS "-mtune=native" CACHE STRING "Compiler flags for specifying target architecture.") - else () - set(FINUFFT_ARCH_FLAGS "-march=native" CACHE STRING "Compiler flags for specifying target architecture.") - endif () -endif () -set(FINUFFT_FFTW_SUFFIX "OpenMP" CACHE STRING "Suffix for FFTW libraries (e.g. OpenMP, Threads etc.)") -set(FINUFFT_FFTW_LIBRARIES "DEFAULT" CACHE STRING "Specify a custom FFTW library") - -# All options go here -# sphinx tag (don't remove): @cmake_opts_start -option(FINUFFT_BUILD_EXAMPLES "Whether to build the FINUFFT examples" OFF) -option(FINUFFT_BUILD_TESTS "Whether to build the FINUFFT tests" OFF) +# cmake-format: off +# All options go here sphinx tag (don't remove): @cmake_opts_start option(FINUFFT_BUILD_FORTRAN "Whether to build the FINUFFT Fortran examples" OFF) option(FINUFFT_BUILD_MATLAB "Whether to build the FINUFFT Matlab interface" OFF) option(FINUFFT_BUILD_PYTHON "Whether the Python wrapper should be built." OFF) option(FINUFFT_ENABLE_SANITIZERS "Whether to enable sanitizers, only effective for Debug configuration." ON) option(FINUFFT_USE_OPENMP "Whether to use OpenMP for parallelization. If disabled, the finufft library will be single threaded. This does not affect the choice of FFTW library." ON) -option(FINUFFT_USE_CUDA "Whether to build CUDA accelerated FINUFFT library (libcufinufft). This is completely independent of the main FINUFFT library" OFF) option(FINUFFT_USE_CPU "Whether to build the ordinary FINUFFT library (libfinufft)." ON) +option(FINUFFT_USE_CUDA "Whether to build CUDA accelerated FINUFFT library (libcufinufft). This is completely independent of the main FINUFFT library" OFF) option(FINUFFT_STATIC_LINKING "Whether to build the static FINUFFT library." ON) option(FINUFFT_BUILD_DEVEL "Whether to build development executables" OFF) +option(FINUFFT_BUILD_EXAMPLES "Whether to build the FINUFFT examples" OFF) +option(FINUFFT_BUILD_TESTS "Whether to build the FINUFFT tests" OFF) option(FINUFFT_USE_DUCC0 "Whether to use DUCC0 (instead of FFTW) for CPU FFTs" OFF) -option(FINUFFT_BUILD_DEVEL "Whether to build developement executables" OFF) -option(FINUFFT_ENABLE_INSTALL "Whether to enable installation of FINUFFT library" ON) +# if FINUFFT_USE_DUCC0 is ON, the following options are ignored +set(FINUFFT_FFTW_LIBRARIES "DEFAULT" CACHE STRING "Specify a custom FFTW library") +set(FINUFFT_FFTW_SUFFIX "OpenMP" CACHE STRING "Suffix for FFTW libraries (e.g. OpenMP, Threads etc.)") +# if FINUFFT_USE_CUDA is OFF, the following options are ignored +set(FINUFFT_CUDA_ARCHITECTURES "native" CACHE STRING "CUDA architectures to build for (e.g. 60;70;75;)") +# if FINUFFT_USE_CPU is OFF, the following options are ignored +set(FINUFFT_ARCH_FLAGS "native" CACHE STRING "Compiler flags for specifying target architecture, defaults to -march=native") # sphinx tag (don't remove): @cmake_opts_end +cmake_dependent_option(FINUFFT_ENABLE_INSTALL "Disable installation in the case of python builds" OFF "FINUFFT_BUILD_PYTHON" OFF) +cmake_dependent_option(FINUFFT_STATIC_LINKING "Disable static libraries in the case of python builds" ON "NOT FINUFFT_BUILD_PYTHON" OFF) +cmake_dependent_option(FINUFFT_SHARED_LINKING "Shared should be the opposite of static linking" ON "NOT FINUFFT_STATIC_LINKING" OFF) +# cmake-format: on + +include(cmake/utils.cmake) + +set(FINUFFT_CXX_FLAGS_RELEASE + -funroll-loops + -ffp-contract=fast + -fno-math-errno + -fno-signed-zeros + -fno-trapping-math + -fassociative-math + -freciprocal-math + -fmerge-all-constants + -ftree-vectorize + -fimplicit-constexpr + -fcx-limited-range + -O3 + /Ox + /fp:contract + /fp:except- + /GF + /GY + /GS- + /Ob + /Oi + /Ot + /Oy) + +filter_supported_compiler_flags(FINUFFT_CXX_FLAGS_RELEASE + FINUFFT_CXX_FLAGS_RELEASE) +message(STATUS "FINUFFT Release flags: ${FINUFFT_CXX_FLAGS_RELEASE}") +set(FINUFFT_CXX_FLAGS_RELWITHDEBINFO ${FINUFFT_CXX_FLAGS_RELEASE}) + +set(FINUFFT_CXX_FLAGS_DEBUG + -g + -g3 + -ggdb + -ggdb3 + /Zi + -Wall + -Wno-sign-compare + -Wno-unknown-pragmas) +filter_supported_compiler_flags(FINUFFT_CXX_FLAGS_DEBUG FINUFFT_CXX_FLAGS_DEBUG) +message(STATUS "FINUFFT Debug flags: ${FINUFFT_CXX_FLAGS_DEBUG}") +list(APPEND FINUFFT_CXX_FLAGS_RELWITHDEBINFO ${FINUFFT_CXX_FLAGS_RELEASE} + ${FINUFFT_CXX_FLAGS_DEBUG}) +message( + STATUS "FINUFFT RelWithDebInfo flags: ${FINUFFT_CXX_FLAGS_RELWITHDEBINFO}") + +if(FINUFFT_ARCH_FLAGS STREQUAL "native") + set(FINUFFT_ARCH_FLAGS + -march=native + CACHE STRING "" FORCE) + filter_supported_compiler_flags(FINUFFT_ARCH_FLAGS FINUFFT_ARCH_FLAGS) + if(NOT FINUFFT_ARCH_FLAGS) + set(FINUFFT_ARCH_FLAGS + -mtune=native + CACHE STRING "" FORCE) + filter_supported_compiler_flags(FINUFFT_ARCH_FLAGS FINUFFT_ARCH_FLAGS) + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # -march=native emulation for MSVC + check_arch_support() + endif() + if(NOT FINUFFT_ARCH_FLAGS) + message(WARNING "No architecture flags are supported by the compiler.") + else() + message(STATUS "FINUFFT Arch flags: ${FINUFFT_ARCH_FLAGS}") + endif() +endif() +if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) + include(CTest) +endif() -if (NOT FINUFFT_STATIC_LINKING) - set (FINUFFT_SHARED_LINKING ON) -else () - set (FINUFFT_SHARED_LINKING OFF) -endif () - -if (FINUFFT_USE_CPU) - # suppress Windows warnings about "unsafe" functions - if (WIN32) - add_definitions(-D_CRT_SECURE_NO_WARNINGS) - endif () - - # make apple with gnu use old linker, new linker breaks, see issue #360 - if ((APPLE) AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")) - add_link_options("-ld64") - endif () - - set(CPM_DOWNLOAD_VERSION 0.38.0) - set(FFTW_VERSION 3.3.10) - set(XTL_VERSION 0.7.7) - set(XSIMD_VERSION 13.0.0) - set(DUCC0_VERSION ducc0_0_34_0) - set(FINUFFT_FFTW_LIBRARIES) - include(cmake/setupCPM.cmake) - include(cmake/setupXSIMD.cmake) - if (FINUFFT_USE_DUCC0) - include(cmake/setupDUCC.cmake) - else () - include(cmake/setupFFTW.cmake) - endif () -endif () - -if (FINUFFT_USE_DUCC0) - set (FINUFFT_FFTLIBS ducc0) -else () - set (FINUFFT_FFTLIBS ${FINUFFT_FFTW_LIBRARIES}) -endif () - -if (FINUFFT_BUILD_MATLAB) - # When building for matlab, we will fetch the OpenMP library used by matlab - # instead of system default for compatibility. - find_package(Matlab REQUIRED) - find_library(matlab_iomp5_lib NAMES iomp5 HINTS ${Matlab_ROOT_DIR}/sys/os/ PATH_SUFFIXES glnxa64 maci64) - find_library(pthreads_lib NAMES pthread CMAKE_FIND_ROOT_PATH_BOTH) - - # Create a "fake" imported library pointing to the matlab openmp implementation - add_library(OpenMP::OpenMP_CXX SHARED IMPORTED) - set_target_properties(OpenMP::OpenMP_CXX PROPERTIES IMPORTED_LOCATION ${matlab_iomp5_lib}) - target_link_libraries(OpenMP::OpenMP_CXX INTERFACE ${pthreads_lib}) - # Set the OpenMP flag. - if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - target_compile_options(OpenMP::OpenMP_CXX INTERFACE -Xclang -fopenmp) - else () - target_compile_options(OpenMP::OpenMP_CXX INTERFACE -fopenmp) - endif () -else () - # For non-matlab builds, find system OpenMP - if (FINUFFT_USE_OPENMP) - find_package(OpenMP COMPONENTS CXX REQUIRED) - endif () -endif () - -# This set of sources is compiled twice, once in single precision and once in double precision -# The single precision compilation is done with -DSINGLE -set(FINUFFT_PRECISION_DEPENDENT_SOURCES src/finufft.cpp src/fft.cpp src/simpleinterfaces.cpp src/spreadinterp.cpp src/utils.cpp fortran/finufftfort.cpp) - -# Set of compilers which behave like gcc -set(FINUFFT_GNU_LIKE_COMPILERS AppleClang Clang GNU) +# Set default build type to Release +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE + Release + CACHE STRING "Set the default build type to Release" FORCE) +endif() +# This set of sources is compiled twice, once in single precision and once in +# double precision The single precision compilation is done with -DSINGLE +set(FINUFFT_PRECISION_DEPENDENT_SOURCES + src/finufft.cpp src/fft.cpp src/simpleinterfaces.cpp src/spreadinterp.cpp + src/utils.cpp fortran/finufftfort.cpp) + +# set linker flags for sanitizer +set(FINUFFT_SANITIZER_FLAGS) +if(FINUFFT_ENABLE_SANITIZERS) + set(FINUFFT_SANITIZER_FLAGS -fsanitize=address -fsanitize=undefined + -fsanitize=bounds-strict /fsanitize=address /RTC1) + filter_supported_compiler_flags(FINUFFT_SANITIZER_FLAGS + FINUFFT_SANITIZER_FLAGS) + set(FINUFFT_SANITIZER_FLAGS + $<$:${FINUFFT_SANITIZER_FLAGS}>) +endif() # Utility function to enable ASAN on debug builds function(enable_asan target) - if (NOT FINUFFT_ENABLE_SANITIZERS) - return() - endif () - - if (CMAKE_CXX_COMPILER_ID IN_LIST FINUFFT_GNU_LIKE_COMPILERS) - # Enable only on clang / gcc compilers. - target_compile_options(${target} PRIVATE $<$:-fsanitize=address -fsanitize=undefined -fsanitize=bounds-strict>) - target_link_options(${target} PRIVATE $<$:-fsanitize=address -fsanitize=undefined -fsanitize=bounds-strict>) - endif () - target_compile_options(${target} PRIVATE $<$:-Wall -Wno-sign-compare>) + target_compile_options(${target} PRIVATE ${FINUFFT_SANITIZER_FLAGS}) + if(NOT (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")) + target_link_options(${target} PRIVATE ${FINUFFT_SANITIZER_FLAGS}) + endif() endfunction() +if(FINUFFT_USE_CPU) + # make apple with gnu use old linker, new linker breaks, see issue #360 + if((APPLE) AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")) + add_link_options("-ld_classic") + endif() + + set(CPM_DOWNLOAD_VERSION 0.40.0) + set(FFTW_VERSION 3.3.10) + set(XTL_VERSION 0.7.7) + set(XSIMD_VERSION 13.0.0) + # using latest ducc0 version for now as it fixes MacOS GCC build + set(DUCC0_VERSION b0beb85e03982344a31ebb119758d7aa3ef5d362) + set(FINUFFT_FFTW_LIBRARIES) + include(cmake/setupCPM.cmake) + include(cmake/setupXSIMD.cmake) + if(FINUFFT_USE_DUCC0) + include(cmake/setupDUCC.cmake) + else() + include(cmake/setupFFTW.cmake) + endif() + if(FINUFFT_USE_DUCC0) + set(FINUFFT_FFTLIBS ducc0) + else() + set(FINUFFT_FFTLIBS ${FINUFFT_FFTW_LIBRARIES}) + endif() + if(FINUFFT_USE_OPENMP) + find_package( + OpenMP + COMPONENTS C CXX + REQUIRED) + endif() +endif() + +# check if -Wno-deprecated-declarations is supported +check_cxx_compiler_flag(-Wno-deprecated-declarations + FINUFFT_HAS_NO_DEPRECATED_DECLARATIONS) + # Utility function to link static/dynamic lib function(finufft_link_test target) - if (FINUFFT_USE_DUCC0) - target_compile_definitions(${target} PRIVATE FINUFFT_USE_DUCC0) - endif () - target_link_libraries(${target} PRIVATE finufft ${FINUFFT_FFTLIBS}) - if(FINUFFT_USE_OPENMP) - target_link_libraries(${target} PRIVATE OpenMP::OpenMP_CXX) - if(WIN32) - target_link_options(${target} PRIVATE ${OpenMP_CXX_FLAGS}) - if (FINUFFT_SHARED_LINKING) - target_compile_definitions(${target} PRIVATE FINUFFT_DLL) - endif() - endif() - endif() - enable_asan(${target}) + if(FINUFFT_USE_DUCC0) + target_compile_definitions(${target} PRIVATE FINUFFT_USE_DUCC0) + endif() + target_link_libraries(${target} PRIVATE finufft ${FINUFFT_FFTLIBS}) + if(FINUFFT_USE_OPENMP) + target_link_libraries(${target} PRIVATE OpenMP::OpenMP_CXX) + target_link_options(${target} PRIVATE ${OpenMP_CXX_FLAGS}) + endif() + enable_asan(${target}) + target_compile_features(${target} PRIVATE cxx_std_17) + set_target_properties( + ${target} PROPERTIES MSVC_RUNTIME_LIBRARY + "MultiThreaded$<$:Debug>") + # disable deprecated warnings for tests if supported + if(FINUFFT_HAS_NO_DEPRECATED_DECLARATIONS) + target_compile_options(${target} PRIVATE -Wno-deprecated-declarations) + endif() endfunction() # Utility function to set finufft compilation options. function(set_finufft_options target) - set_property(TARGET ${target} PROPERTY POSITION_INDEPENDENT_CODE ${FINUFFT_SHARED_LINKING}) - target_compile_features(${target} PRIVATE cxx_std_17) - - enable_asan(${target}) - - target_compile_options(${target} PRIVATE SHELL:$<$:${FINUFFT_ARCH_FLAGS}>) - if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # Enable cx-limited-range on supported compilers - target_compile_options(${target} PRIVATE $<$:-fcx-limited-range>) - endif () - target_compile_options(${target} PRIVATE $<$:${FINUFFT_CXX_FLAGS_RELEASE}>) - target_compile_options(${target} PRIVATE $<$:${FINUFFT_CXX_FLAGS_RELWITHDEBINFO}>) - target_include_directories(${target} PUBLIC $) - target_include_directories(${target} SYSTEM INTERFACE $) - if (FINUFFT_USE_OPENMP) - target_link_libraries(${target} PRIVATE OpenMP::OpenMP_CXX) - # there are issues on windows with OpenMP and CMake, so we need to manually add the flags - # otherwise there are link errors - if (WIN32) - target_link_options(${target} PRIVATE ${OpenMP_CXX_FLAGS}) - endif () - else () - if (CMAKE_CXX_COMPILER_ID IN_LIST FINUFFT_GNU_LIKE_COMPILERS) - # OpenMP disabled, suppress unknown pragma warnings to avoid spam. - target_compile_options(${target} PRIVATE "-Wno-unknown-pragmas") - endif () - endif () - - if (FINUFFT_USE_DUCC0) - target_compile_definitions(${target} PRIVATE FINUFFT_USE_DUCC0) - else () - # FFTW CMAKE file includes the APIs only as an install target, so we need to manually - # include them since we need them for build not for install - # trying to include them directly into the fftw and fftwf targets causes issues with - # the latest version of cmake, so we do it here instead. - if ((NOT FFTW_FOUND) OR (FINUFFT_FFTW_LIBRARIES STREQUAL DOWNLOAD)) - list(GET FINUFFT_FFTW_LIBRARIES 0 element) - get_property(FFTW_SOURCE_DIR TARGET ${element} PROPERTY SOURCE_DIR) - set(FFTW_INCLUDE_DIR ${FFTW_SOURCE_DIR}/api) - target_include_directories(${target} PUBLIC ${FFTW_INCLUDE_DIR}) - endif () - endif () + target_compile_features(${target} PRIVATE cxx_std_17) + target_compile_options( + ${target} PRIVATE $<$:${FINUFFT_ARCH_FLAGS}>) + target_compile_options( + ${target} PRIVATE $<$:${FINUFFT_CXX_FLAGS_RELEASE}>) + target_compile_options( + ${target} + PRIVATE $<$:${FINUFFT_CXX_FLAGS_RELWITHDEBINFO}>) + target_compile_options(${target} + PRIVATE $<$:${FINUFFT_CXX_FLAGS_DEBUG}>) + target_include_directories( + ${target} PUBLIC $) + target_include_directories( + ${target} SYSTEM + INTERFACE $) + set_target_properties( + ${target} + PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" + POSITION_INDEPENDENT_CODE ${FINUFFT_SHARED_LINKING}) + enable_asan(${target}) + if(FINUFFT_USE_OPENMP) + target_link_libraries(${target} PRIVATE OpenMP::OpenMP_CXX) + target_link_options(${target} PRIVATE ${OpenMP_CXX_FLAGS}) + endif() + if(FINUFFT_USE_DUCC0) + target_compile_definitions(${target} PRIVATE FINUFFT_USE_DUCC0) + endif() + target_link_libraries(${target} PRIVATE xsimd) + target_link_libraries(${target} PRIVATE ${FINUFFT_FFTLIBS}) endfunction() -if (FINUFFT_USE_CPU) - # Main finufft libraries - if (FINUFFT_USE_DUCC0) - # okay for now, to be cleaned up - set_finufft_options(ducc0) - endif () - - add_library(finufft_f32 OBJECT ${FINUFFT_PRECISION_DEPENDENT_SOURCES}) - target_compile_definitions(finufft_f32 PRIVATE SINGLE) - if (WIN32 AND FINUFFT_SHARED_LINKING) - target_compile_definitions(finufft_f32 PRIVATE dll_EXPORTS FINUFFT_DLL) - endif () - set_finufft_options(finufft_f32) - target_link_libraries(finufft_f32 PUBLIC ${FINUFFT_FFTLIBS}) - target_link_libraries(finufft_f32 PRIVATE xsimd) - - add_library(finufft_f64 OBJECT ${FINUFFT_PRECISION_DEPENDENT_SOURCES}) - target_compile_definitions(finufft_f64 PRIVATE) - if (WIN32 AND FINUFFT_SHARED_LINKING) - target_compile_definitions(finufft_f64 PRIVATE dll_EXPORTS FINUFFT_DLL) - endif () - set_finufft_options(finufft_f64) - target_link_libraries(finufft_f64 PUBLIC ${FINUFFT_FFTLIBS}) - target_link_libraries(finufft_f64 PRIVATE xsimd) - if (FINUFFT_SHARED_LINKING) - add_library(finufft SHARED src/utils_precindep.cpp contrib/legendre_rule_fast.cpp) - if (WIN32) - target_compile_definitions(finufft PRIVATE dll_EXPORTS FINUFFT_DLL) - endif() - else() - add_library(finufft STATIC src/utils_precindep.cpp contrib/legendre_rule_fast.cpp) - endif() - target_link_libraries(finufft PRIVATE finufft_f32 finufft_f64) - set_finufft_options(finufft) - - # windows does not have a math library, so we need to exclude it - if (NOT WIN32) - target_link_libraries(finufft PUBLIC m) - endif () - target_include_directories(finufft PUBLIC $) - target_include_directories(finufft SYSTEM INTERFACE $) - - if (FINUFFT_ENABLE_INSTALL) - file(GLOB FINUFFT_PUBLIC_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/finufft*.h") - set_target_properties(finufft PROPERTIES PUBLIC_HEADER "${FINUFFT_PUBLIC_HEADERS}") - endif() - list(APPEND INSTALL_TARGETS finufft) -endif () +if(FINUFFT_USE_CPU) + # Main finufft libraries + add_library(finufft_f32 OBJECT ${FINUFFT_PRECISION_DEPENDENT_SOURCES}) + target_compile_definitions(finufft_f32 PRIVATE SINGLE) + set_finufft_options(finufft_f32) + + add_library(finufft_f64 OBJECT ${FINUFFT_PRECISION_DEPENDENT_SOURCES}) + set_finufft_options(finufft_f64) + if(NOT FINUFFT_STATIC_LINKING) + add_library(finufft SHARED src/utils_precindep.cpp + contrib/legendre_rule_fast.cpp) + else() + add_library(finufft STATIC src/utils_precindep.cpp + contrib/legendre_rule_fast.cpp) + endif() + target_link_libraries(finufft PRIVATE finufft_f32 finufft_f64) + set_finufft_options(finufft) + + if(WIN32 AND FINUFFT_SHARED_LINKING) + target_compile_definitions(finufft_f32 PRIVATE dll_EXPORTS FINUFFT_DLL) + target_compile_definitions(finufft_f64 PRIVATE dll_EXPORTS FINUFFT_DLL) + target_compile_definitions(finufft PRIVATE dll_EXPORTS FINUFFT_DLL) + endif() + find_library(MATH_LIBRARY m) + if(MATH_LIBRARY) + target_link_libraries(finufft PRIVATE ${MATH_LIBRARY}) + endif() + target_include_directories( + finufft PUBLIC $) + target_include_directories( + finufft SYSTEM + INTERFACE $) + if(FINUFFT_ENABLE_INSTALL) + file(GLOB FINUFFT_PUBLIC_HEADERS + "${CMAKE_CURRENT_SOURCE_DIR}/include/finufft*.h") + set_target_properties(finufft PROPERTIES PUBLIC_HEADER + "${FINUFFT_PUBLIC_HEADERS}") + endif() + list(APPEND INSTALL_TARGETS finufft) +endif() -if (FINUFFT_USE_CUDA) - if (NOT DEFINED CMAKE_CUDA_ARCHITECTURES) - message("FINUFFT WARNING: No CUDA architecture supplied via '-DCMAKE_CUDA_ARCHITECTURES=...', defaulting to '60;70;75;'") - message("See: https://developer.nvidia.com/cuda-gpus for more details on what architecture to supply.") - set(CMAKE_CUDA_ARCHITECTURES "60;70;75" CACHE STRING "" FORCE) - endif () - enable_language(CUDA) - find_package(CUDAToolkit REQUIRED) - add_subdirectory(src/cuda) - if (BUILD_TESTING AND FINUFFT_BUILD_TESTS) - add_subdirectory(perftest/cuda) - endif () +if(FINUFFT_USE_CUDA) + if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) + message( + "FINUFFT WARNING: No CUDA architecture supplied via '-DCMAKE_CUDA_ARCHITECTURES=...', defaulting to 'native'" + ) + message( + "See: https://developer.nvidia.com/cuda-gpus for more details on what architecture to supply." + ) + endif() + enable_language(CUDA) + find_package(CUDAToolkit REQUIRED) + add_subdirectory(src/cuda) + if(BUILD_TESTING AND FINUFFT_BUILD_TESTS) + add_subdirectory(perftest/cuda) + add_subdirectory(test/cuda) + endif() - list(APPEND INSTALL_TARGETS cufinufft) -endif () + list(APPEND INSTALL_TARGETS cufinufft) +endif() # Add tests defined in their own directory -if (BUILD_TESTING AND FINUFFT_BUILD_TESTS AND FINUFFT_USE_CPU) - add_subdirectory(test) - add_subdirectory(perftest) -endif () +if(BUILD_TESTING + AND FINUFFT_USE_CPU + AND FINUFFT_BUILD_TESTS) + add_subdirectory(test) + add_subdirectory(perftest) +endif() -if (BUILD_TESTING AND FINUFFT_BUILD_TESTS AND FINUFFT_USE_CUDA) - add_subdirectory(test/cuda) -endif () +if(FINUFFT_BUILD_EXAMPLES AND FINUFFT_USE_CPU) + add_subdirectory(examples) +endif() -if (FINUFFT_BUILD_EXAMPLES) - add_subdirectory(examples) -endif () +if(FINUFFT_BUILD_EXAMPLES AND FINUFFT_USE_CUDA) + add_subdirectory(examples/cuda) +endif() -if (FINUFFT_BUILD_FORTRAN) - enable_language(Fortran) - add_subdirectory(fortran) -endif () +if(FINUFFT_BUILD_FORTRAN) + enable_language(Fortran) + add_subdirectory(fortran) +endif() -if (FINUFFT_BUILD_MATLAB) - add_subdirectory(matlab) -endif () +if(FINUFFT_BUILD_MATLAB) + add_subdirectory(matlab) +endif() -if (FINUFFT_BUILD_DEVEL) - add_subdirectory(devel) -endif () +if(FINUFFT_BUILD_DEVEL) + add_subdirectory(devel) +endif() -if (FINUFFT_BUILD_PYTHON) - add_subdirectory(python) -endif () +if(FINUFFT_BUILD_PYTHON) + add_subdirectory(python) +endif() message(STATUS " CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") message(STATUS "FINUFFT configuration summary:") @@ -325,38 +341,32 @@ message(STATUS " FINUFFT_ENABLE_SANITIZERS: ${FINUFFT_ENABLE_SANITIZERS}") message(STATUS " FINUFFT_FFTW_SUFFIX: ${FINUFFT_FFTW_SUFFIX}") message(STATUS " FINUFFT_FFTW_LIBRARIES: ${FINUFFT_FFTW_LIBRARIES}") message(STATUS " FINUFFT_ARCH_FLAGS: ${FINUFFT_ARCH_FLAGS}") - -if (FINUFFT_USE_CPU) - get_target_property(FINUFFT_COMPILE_OPTIONS finufft COMPILE_OPTIONS) - message("Compile options for finufft: ${MY_COMPILE_OPTIONS}") -endif () - -if (FINUFFT_ENABLE_INSTALL) - include(GNUInstallDirs) - install(TARGETS ${INSTALL_TARGETS} PUBLIC_HEADER) - install(FILES ${PROJECT_SOURCE_DIR}/LICENSE - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses/finufft) - if (FINUFFT_USE_CPU) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/examples - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/finufft - PATTERN "CMakeLists.txt" EXCLUDE - PATTERN "README" EXCLUDE - PATTERN "examples/cuda" EXCLUDE - ) - if (FINUFFT_BUILD_FORTRAN) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/fortran/examples - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/finufft/fortran - ) - install(FILES ${PROJECT_SOURCE_DIR}/include/finufft.fh - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - ) - endif() - endif () - if (FINUFFT_USE_CUDA) - install(DIRECTORY ${PROJECT_SOURCE_DIR}/examples/cuda - DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/finufft/examples - PATTERN "README" EXCLUDE - PATTERN "CMakeLists.txt" EXCLUDE - ) +message(STATUS " FINUFFT_USE_DUCC0: ${FINUFFT_USE_DUCC0}") + +if(FINUFFT_ENABLE_INSTALL) + include(GNUInstallDirs) + install(TARGETS ${INSTALL_TARGETS} PUBLIC_HEADER) + install(FILES ${PROJECT_SOURCE_DIR}/LICENSE + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/licenses/finufft) + if(FINUFFT_USE_CPU) + install( + DIRECTORY ${PROJECT_SOURCE_DIR}/examples + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/finufft + PATTERN "CMakeLists.txt" EXCLUDE + PATTERN "README" EXCLUDE + PATTERN "examples/cuda" EXCLUDE) + if(FINUFFT_BUILD_FORTRAN) + install(DIRECTORY ${PROJECT_SOURCE_DIR}/fortran/examples + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/finufft/fortran) + install(FILES ${PROJECT_SOURCE_DIR}/include/finufft.fh + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) endif() -endif () + endif() + if(FINUFFT_USE_CUDA) + install( + DIRECTORY ${PROJECT_SOURCE_DIR}/examples/cuda + DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/finufft/examples + PATTERN "README" EXCLUDE + PATTERN "CMakeLists.txt" EXCLUDE) + endif() +endif() diff --git a/cmake/CheckAVX.cpp b/cmake/CheckAVX.cpp new file mode 100644 index 000000000..553a5c35f --- /dev/null +++ b/cmake/CheckAVX.cpp @@ -0,0 +1,48 @@ +#include +#include +#include + +bool is_sse2_supported() { + std::array cpui; + __cpuid(cpui.data(), 1); + return (cpui[3] & (1 << 26)) != 0; +} + +bool is_avx_supported() { + std::array cpui; + __cpuid(cpui.data(), 1); + bool osUsesXSAVE_XRSTORE = (cpui[2] & (1 << 27)) != 0; + bool cpuAVXSupport = (cpui[2] & (1 << 28)) != 0; + if (osUsesXSAVE_XRSTORE && cpuAVXSupport) { + unsigned long long xcrFeatureMask = _xgetbv(_XCR_XFEATURE_ENABLED_MASK); + return (xcrFeatureMask & 0x6) == 0x6; + } + return false; +} + +bool is_avx2_supported() { + std::array cpui; + __cpuid(cpui.data(), 7); + return (cpui[1] & (1 << 5)) != 0; +} + +bool is_avx512_supported() { + std::array cpui; + __cpuidex(cpui.data(), 7, 0); + return (cpui[1] & (1 << 16)) != 0; +} + +int main() { + if (is_avx512_supported()) { + std::cout << "AVX512"; + } else if (is_avx2_supported()) { + std::cout << "AVX2"; + } else if (is_avx_supported()) { + std::cout << "AVX"; + } else if (is_sse2_supported()) { + std::cout << "SSE2"; + } else { + std::cout << "NONE"; + } + return 0; +} diff --git a/cmake/setupDUCC.cmake b/cmake/setupDUCC.cmake index 7a59fb874..440031b2c 100644 --- a/cmake/setupDUCC.cmake +++ b/cmake/setupDUCC.cmake @@ -1,25 +1,46 @@ -CPMAddPackage( - NAME ducc0 - GIT_REPOSITORY https://gitlab.mpcdf.mpg.de/mtr/ducc.git - GIT_TAG ${DUCC0_VERSION} - DOWNLOAD_ONLY YES -) - +cpmaddpackage( + NAME + ducc0 + GIT_REPOSITORY + https://gitlab.mpcdf.mpg.de/mtr/ducc.git + GIT_TAG + ${DUCC0_VERSION} + DOWNLOAD_ONLY + YES) if(ducc0_ADDED) - add_library(ducc0 STATIC - ${ducc0_SOURCE_DIR}/src/ducc0/infra/string_utils.cc - ${ducc0_SOURCE_DIR}/src/ducc0/infra/threading.cc - ${ducc0_SOURCE_DIR}/src/ducc0/infra/mav.cc - ${ducc0_SOURCE_DIR}/src/ducc0/math/gridding_kernel.cc - ${ducc0_SOURCE_DIR}/src/ducc0/math/gl_integrator.cc - ) - target_include_directories(ducc0 PUBLIC ${ducc0_SOURCE_DIR}/src/) + add_library( + ducc0 STATIC + ${ducc0_SOURCE_DIR}/src/ducc0/infra/string_utils.cc + ${ducc0_SOURCE_DIR}/src/ducc0/infra/threading.cc + ${ducc0_SOURCE_DIR}/src/ducc0/infra/mav.cc + ${ducc0_SOURCE_DIR}/src/ducc0/math/gridding_kernel.cc + ${ducc0_SOURCE_DIR}/src/ducc0/math/gl_integrator.cc) + target_include_directories(ducc0 PUBLIC ${ducc0_SOURCE_DIR}/src/) + target_compile_options( + ducc0 PRIVATE $<$:${FINUFFT_ARCH_FLAGS}>) + target_compile_options( + ducc0 PRIVATE $<$:${FINUFFT_CXX_FLAGS_RELEASE}>) + target_compile_options( + ducc0 + PRIVATE $<$:${FINUFFT_CXX_FLAGS_RELWITHDEBINFO}>) + target_compile_features(ducc0 PRIVATE cxx_std_17) + # private because we do not want to propagate this requirement + set_target_properties( + ducc0 + PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" + POSITION_INDEPENDENT_CODE ${FINUFFT_SHARED_LINKING}) + check_cxx_compiler_flag(-ffast-math HAS_FAST_MATH) + if(HAS_FAST_MATH) target_compile_options(ducc0 PRIVATE -ffast-math) - target_compile_features(ducc0 PRIVATE cxx_std_17) # private because we do not want to propagate this requirement - - if (NOT OpenMP_CXX_FOUND) - find_package(Threads REQUIRED) - target_link_libraries(ducc0 PRIVATE Threads::Threads) - endif () -endif () + endif() + check_cxx_compiler_flag(/fp:fast HAS_FP_FAST) + if(HAS_FP_FAST) + target_compile_options(ducc0 PRIVATE /fp:fast) + endif() + if(NOT OpenMP_CXX_FOUND) + find_package(Threads REQUIRED) + target_link_libraries(ducc0 PRIVATE Threads::Threads) + endif() + enable_asan(ducc0) +endif() diff --git a/cmake/setupFFTW.cmake b/cmake/setupFFTW.cmake index bade5f322..3a26593c2 100644 --- a/cmake/setupFFTW.cmake +++ b/cmake/setupFFTW.cmake @@ -1,61 +1,86 @@ -CPMAddPackage( - NAME findfftw - GIT_REPOSITORY "https://github.com/egpbos/findFFTW.git" - GIT_TAG "master" - EXCLUDE_FROM_ALL YES - GIT_SHALLOW YES -) +cpmaddpackage( + NAME + findfftw + GIT_REPOSITORY + "https://github.com/egpbos/findFFTW.git" + GIT_TAG + "master" + EXCLUDE_FROM_ALL + YES + GIT_SHALLOW + YES) list(APPEND CMAKE_MODULE_PATH "${findfftw_SOURCE_DIR}") -if (FINUFFT_FFTW_LIBRARIES STREQUAL DEFAULT OR FINUFFT_FFTW_LIBRARIES STREQUAL DOWNLOAD) - find_package(FFTW) - if ( (NOT FFTW_FOUND ) OR (FINUFFT_FFTW_LIBRARIES STREQUAL DOWNLOAD)) - if (FINUFFT_FFTW_SUFFIX STREQUAL THREADS) - set(FINUFFT_USE_THREADS ON) - else() - set(FINUFFT_USE_THREADS OFF) - endif() - CPMAddPackage( - NAME fftw3 - OPTIONS - "ENABLE_AVX2 ON" - "BUILD_TESTS OFF" - "BUILD_SHARED_LIBS OFF" - "ENABLE_THREADS ${FINUFFT_USE_THREADS}" - "ENABLE_OPENMP ${FINUFFT_USE_OPENMP}" - URL "http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz" - URL_HASH "MD5=8ccbf6a5ea78a16dbc3e1306e234cc5c" - EXCLUDE_FROM_ALL YES - GIT_SHALLOW YES - ) +if(FINUFFT_FFTW_LIBRARIES STREQUAL DEFAULT OR FINUFFT_FFTW_LIBRARIES STREQUAL + DOWNLOAD) + find_package(FFTW) + if((NOT FFTW_FOUND) OR (FINUFFT_FFTW_LIBRARIES STREQUAL DOWNLOAD)) + if(FINUFFT_FFTW_SUFFIX STREQUAL THREADS) + set(FINUFFT_USE_THREADS ON) + else() + set(FINUFFT_USE_THREADS OFF) + endif() + cpmaddpackage( + NAME + fftw3 + OPTIONS + "ENABLE_SSE2 ON" + "ENABLE_AVX ON" + "ENABLE_AVX2 ON" + "BUILD_TESTS OFF" + "BUILD_SHARED_LIBS OFF" + "ENABLE_THREADS ${FINUFFT_USE_THREADS}" + "ENABLE_OPENMP ${FINUFFT_USE_OPENMP}" + URL + "http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz" + URL_HASH + "MD5=8ccbf6a5ea78a16dbc3e1306e234cc5c" + EXCLUDE_FROM_ALL + YES + GIT_SHALLOW + YES) - CPMAddPackage( - NAME fftw3f - OPTIONS - "ENABLE_AVX2 ON" - "BUILD_TESTS OFF" - "BUILD_SHARED_LIBS OFF" - "ENABLE_FLOAT ON" - "ENABLE_THREADS ${FINUFFT_USE_THREADS}" - "ENABLE_OPENMP ${FINUFFT_USE_OPENMP}" - URL "http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz" - URL_HASH "MD5=8ccbf6a5ea78a16dbc3e1306e234cc5c" - EXCLUDE_FROM_ALL YES - GIT_SHALLOW YES - ) - set(FINUFFT_FFTW_LIBRARIES fftw3 fftw3f) - if (FINUFFT_USE_THREADS) - list(APPEND FINUFFT_FFTW_LIBRARIES fftw3_threads fftw3f_threads) - elseif (FINUFFT_USE_OPENMP) - list(APPEND FINUFFT_FFTW_LIBRARIES fftw3_omp fftw3f_omp) - endif () - - foreach (element IN LISTS FINUFFT_FFTW_LIBRARIES) - set_property(TARGET ${element} PROPERTY POSITION_INDEPENDENT_CODE ${FINUFFT_SHARED_LINKING}) - endforeach () + cpmaddpackage( + NAME + fftw3f + OPTIONS + "ENABLE_SSE2 ON" + "ENABLE_AVX ON" + "ENABLE_AVX2 ON" + "ENABLE_FLOAT ON" + "BUILD_TESTS OFF" + "BUILD_SHARED_LIBS OFF" + "ENABLE_THREADS ${FINUFFT_USE_THREADS}" + "ENABLE_OPENMP ${FINUFFT_USE_OPENMP}" + URL + "http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz" + URL_HASH + "MD5=8ccbf6a5ea78a16dbc3e1306e234cc5c" + EXCLUDE_FROM_ALL + YES + GIT_SHALLOW + YES) + set(FINUFFT_FFTW_LIBRARIES fftw3 fftw3f) + if(FINUFFT_USE_THREADS) + list(APPEND FINUFFT_FFTW_LIBRARIES fftw3_threads fftw3f_threads) + elseif(FINUFFT_USE_OPENMP) + list(APPEND FINUFFT_FFTW_LIBRARIES fftw3_omp fftw3f_omp) + endif() - else () - set(FINUFFT_FFTW_LIBRARIES "FFTW::Float" "FFTW::Double" "FFTW::Float${FINUFFT_FFTW_SUFFIX}" "FFTW::Double${FINUFFT_FFTW_SUFFIX}") - endif () -endif () \ No newline at end of file + foreach(element IN LISTS FINUFFT_FFTW_LIBRARIES) + set_target_properties( + ${element} + PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>" + POSITION_INDEPENDENT_CODE ${FINUFFT_SHARED_LINKING}) + endforeach() + + target_include_directories( + fftw3 PUBLIC $) + + else() + set(FINUFFT_FFTW_LIBRARIES + "FFTW::Float" "FFTW::Double" "FFTW::Float${FINUFFT_FFTW_SUFFIX}" + "FFTW::Double${FINUFFT_FFTW_SUFFIX}") + endif() +endif() diff --git a/cmake/utils.cmake b/cmake/utils.cmake new file mode 100644 index 000000000..4a1e57956 --- /dev/null +++ b/cmake/utils.cmake @@ -0,0 +1,90 @@ +include(CheckCXXCompilerFlag) +# Define the function +function(filter_supported_compiler_flags input_flags_var output_flags_var) + # Create an empty list to store supported flags + set(supported_flags) + + # Iterate over each flag in the input list + foreach(flag ${${input_flags_var}}) + string(REPLACE "=" "_" flag_var ${flag}) # Convert flag to a valid variable + # name + string(REPLACE "-" "" flag_var ${flag_var}) # Remove '-' for the variable + # name + + # Append the test linker flag to the existing flags + list(APPEND CMAKE_EXE_LINKER_FLAGS ${flag}) + check_cxx_compiler_flag(${flag} ${flag_var}) + if(${flag_var}) + # If supported, append the flag to the list of supported flags + list(APPEND supported_flags ${flag}) + else() + message(STATUS "Flag ${flag} is not supported") + endif() + unset(${flag_var} CACHE) + # remove last flag from linker flags + list(REMOVE_ITEM CMAKE_EXE_LINKER_FLAGS ${flag}) + endforeach() + # Set the output variable to the list of supported flags + set(${output_flags_var} + ${supported_flags} + PARENT_SCOPE) +endfunction() + +function(check_arch_support) + message(STATUS "Checking for AVX, AVX512 and SSE support") + try_run( + RUN_RESULT_VAR COMPILE_RESULT_VAR ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckAVX.cpp + COMPILE_OUTPUT_VARIABLE COMPILE_OUTPUT + RUN_OUTPUT_VARIABLE RUN_OUTPUT) + if(RUN_OUTPUT MATCHES "AVX512") + set(FINUFFT_ARCH_FLAGS + "/arch:AVX512" + CACHE STRING "" FORCE) + elseif(RUN_OUTPUT MATCHES "AVX2") + set(FINUFFT_ARCH_FLAGS + "/arch:AVX2" + CACHE STRING "" FORCE) + elseif(RUN_OUTPUT MATCHES "AVX") + set(FINUFFT_ARCH_FLAGS + "/arch:AVX" + CACHE STRING "" FORCE) + elseif(RUN_OUTPUT MATCHES "SSE") + set(FINUFFT_ARCH_FLAGS + "/arch:SSE" + CACHE STRING "" FORCE) + else() + set(FINUFFT_ARCH_FLAGS + "" + CACHE STRING "" FORCE) + endif() + message(STATUS "CPU supports: ${RUN_OUTPUT}") + message(STATUS "Using MSVC flags: ${FINUFFT_ARCH_FLAGS}") +endfunction() + +function(copy_dll source_target destination_target) + if(NOT WIN32) + return() + endif() + # Get the binary directory of the destination target + get_target_property(DESTINATION_DIR ${destination_target} BINARY_DIR) + set(DESTINATION_FILE ${DESTINATION_DIR}/$) + if(NOT EXISTS ${DESTINATION_FILE}) + message( + STATUS + "Copying ${source_target} to ${DESTINATION_DIR} directory for ${destination_target}" + ) + # Define the custom command to copy the source target to the destination + # directory + add_custom_command( + TARGET ${destination_target} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ + ${DESTINATION_FILE} + COMMENT "Copying ${source_target} to ${destination_target} directory") + endif() + # Unset the variables to leave a clean state + unset(DESTINATION_DIR) + unset(SOURCE_FILE) + unset(DESTINATION_FILE) +endfunction() diff --git a/docs/install.rst b/docs/install.rst index bb0bd22cc..a30bea36c 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -13,9 +13,19 @@ a precompiled binary for your platform under Assets for various Please post an `Issue `_ to document your installation problem. +.. warning:: + + finufft builds with no issues on Linux using any compiler, in our experience GCC-13 gives best performance. + On MacOS both GCC and clang are fine. + On Windows MSVC works fine. The llvm toolchain included in Visual Studio does not seem to have OpenMP. + The official LLVM distribution builds finufft but debug builds using sanitizers break. + .. note:: - Python-only users can simply install via ``pip install finufft`` which downloads a generic binary from PyPI. Only if you prefer a custom compilation, see :ref:`below`. + On windows finufft built with MSVC requires ``VCOMP140D.DLL`` which is part of the `Microsoft Visual C++ Redistributable `_. + If the library is built with LLVM it requires ``libomp140.x86.64.dll``, more information `here `_. + + Python-only users can simply install via ``pip install finufft`` which downloads a generic binary from PyPI. Only if you prefer a custom compilation, see :ref:`below`. CMake CPM Based Installation ---------------------------- @@ -24,27 +34,47 @@ This is the easiest way to install ``finufft`` if you are using CMake in your ow First include `CPM `_ to your project. The easiest way is to follow the `instructions `_ to automatically add CPM to cmake. - + Then add the following to your ``CMakeLists.txt``: .. code-block:: cmake CPMAddPackage( NAME Finufft - GIT_REPOSITORY https://github.com/flatironinstitute/finufft.git + GIT_REPOSITORY https://github.com/flatironinstitute/finufft.git GIT_TAG master GIT_SHALLOW Yes GIT_PROGRESS Yes - EXCLUDE_FROM_ALL Yes + EXCLUDE_FROM_ALL Yes SYSTEM ) - target_link_library(your_executable [PUBLIC|PRIVATE|INTERFACE] finufft_static) - # or for shared linking target_link_library(your_executable [PUBLIC|PRIVATE|INTERFACE] finufft) Then cmake will automatically download the library and link it to your executable. +CMake FetchContent Based Installation +---------------------------- + +Another way to include finufft in the project is to use FetchContent +which is provided directly by cmake. +To do so add the following to your ``CMakeLists.txt``: + +.. code-block:: cmake + include(FetchContent) + + # Define the finufft library + FetchContent_Declare( + finufft + GIT_REPOSITORY https://github.com/flatironinstitute/finufft.git + GIT_TAG 2.3 + ) + + # Make the content available + FetchContent_MakeAvailable(finufft) + + # Optionally, link the finufft library to your target + target_link_libraries(your_executable [PUBLIC|PRIVATE|INTERFACE] finufft) CMake Based Installation ------------------------ @@ -57,10 +87,8 @@ The basic quick download, building, and test is then: git clone https://github.com/flatironinstitute/finufft.git cd finufft - mkdir build - cd build - cmake .. -D FINUFFT_BUILD_TESTS=ON --install-prefix /path/to/install - cmake --build . -j + cmake -S . -B build -DFINUFFT_BUILD_TESTS=ON --install-prefix /path/to/install + cmake --build build ctest cmake --install . @@ -90,7 +118,7 @@ Here are all our build options, showing name, explanatory text, and default valu :language: cmake :start-after: @cmake_opts_start :end-before: @cmake_opts_end - + For convenience we also provide a number of `cmake presets `_ for various options and compilers, in ``CMakePresets.json`` (this will grow to replace the old ``make.inc.*`` site files). @@ -98,8 +126,8 @@ For example, to configure, build and test the development preset (which builds t .. code-block:: bash - cmake --preset dev .. - cmake --build . -j + cmake -S . -B build --preset dev # dev is the preset name + cmake --build build ctest .. warning:: @@ -116,7 +144,7 @@ From other CMake projects, to use ``finufft`` as a library, simply add this repo Classic GNU make based route ---------------------------- - + Below we deal with the three standard OSes in order: 1) **linux**, 2) **Mac OSX**, 3) **Windows**. We have some users contributing settings for other OSes, for instance PowerPC. The general procedure to download, then compile for such a special setup is, illustrating with the PowerPC case:: @@ -131,11 +159,11 @@ Have a look for ``make.inc.*`` to see what is available, and/or edit your ``make make.inc.macosx_clang make.inc.macosx_gcc-10 make.inc.windows_msys - + If there is an error in testing on what you consider a standard set-up, please file a detailed bug report as a New Issue at https://github.com/flatironinstitute/finufft/issues - + Quick linux install instructions -------------------------------- @@ -183,7 +211,7 @@ Optional: On a Fedora/CentOS linux system, the base dependencies can be installed by:: sudo yum install make gcc gcc-c++ fftw-devel libgomp - + To add Fortran and Octave language interfaces also do:: sudo yum install gcc-gfortran octave octave-devel @@ -205,7 +233,7 @@ In older distros you may have to compile ``octave`` from source to get the neede You should then compile and test the library via various ``make`` tasks, eg:: make test -j - + then checking you got ``0 fails``. This compiles the main libraries then runs double- and single-precision tests, each of which should report zero segfaults and zero fails. @@ -240,7 +268,7 @@ option. **Testing**. The initial test is ``test/basicpassfail`` which is the most basic double-precision smoke test, producing the exit code 0 if success, nonzero if fail. You can check the exit code thus:: - + test/basicpassfail; echo $? The single-precision version is ``test/basicpassfailf``. @@ -276,7 +304,7 @@ and print a bunch of errors around ``1e-6``. or appropriate to your MATLAB version. You'll want to check this shared object exists. Then ``make clean`` and ``make test -j``, finally ``make matlab`` again. - + ``make octave`` to compile and test the MEX-like interface to Octave. @@ -299,7 +327,7 @@ Here are some other settings that you may need to adjust in ``make.inc``: - + 2) Mac OSX: tips for installing dependencies and compiling ----------------------------------------------------------- @@ -314,7 +342,7 @@ If you don't have Xcode, install Command Line Tools by opening a terminal (from ``/Applications/Utilities/``) and typing:: xcode-select --install - + You will be asked for an administrator password. Then, also as an administrator, install Homebrew by pasting the installation command from @@ -331,7 +359,7 @@ If you are python-only, use:: brew install python3 pip3 install finufft - + Or, for experts to compile python interfaces locally using either clang or gcc, see :ref:`below`. @@ -343,7 +371,7 @@ will allow fortran linking with ``gfortran``, but currently fails with octave. The clang route (default) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once you have downloaded FINUFFT from github, go to its top directory. You now need to decide if you will be wanting to call FINUFFT from @@ -372,7 +400,7 @@ To test, open MATLAB, ``addpath matlab``, Unfortunately OSX+MATLAB+mex is notoriously poorly supported, and you may need to search the web for help on that, then `check you are able to compile a simple mex file first `_. For instance, on Catalina (10.15.6), ``make matlab`` fails with a warning involving Xcode ``license has not been accepted``, and then an error with ``no supported compiler was found``. Eventually `this property file hack worked `_, which simply requires typing ``/usr/libexec/PlistBuddy -c 'Add :IDEXcodeVersionForAgreedToGMLicense string 10.0' ~/Library/Preferences/com.apple.dt.Xcode.plist`` Please also read our https://github.com/flatironinstitute/finufft/issues and if you *are* able to mex compile, but ``make matlab`` fails, post a new Issue. - + Octave interfaces work out of the box (this also runs a self-test):: brew install octave @@ -418,8 +446,8 @@ section of ``mexopts.sh``. 3) Windows: tips for compiling -------------------------------- - +------------------------------- + We have users who have adjusted the makefile to work - at least to some extent - on Windows 10. If you are only interested in calling from Octave (which already comes with MinGW-w64 and FFTW), then we have been told this can be done very simply: from within Octave, go to the ``finufft`` directory and do ``system('make octave')``. You may have to tweak ``OCTAVE`` in your ``make.inc`` in a similar fashion to below. More generally, please make sure to have a recent version of Mingw at hand, preferably with a 64bit version of gnu-make like the WinLibs standalone build of GCC and MinGW-w64 for Windows. Note that most MinGW-w64 distributions, such as TDM-GCC, do not feature the 64bit gnu-make. Fortunately, this limitation is only relevant to run the tests. To prepare the build of the static and dynamic libraries run:: @@ -428,7 +456,7 @@ More generally, please make sure to have a recent version of Mingw at hand, pref Subsequently, open this ``make.inc`` file with the text editor of your choice and assign the parent directories of the FFTW header file to ``FFTW_H_DIR``, of the FFTW libraries to ``FFTW_LIB_DIR``, and of the GCC OpenMP library lgomp.dll to ``LGOMP_DIR``. Note that you need the last-mentioned only if you plan to build the MEX-interface for MATLAB. Now, you should be able to run:: - make lib + make lib If the command ``make`` cannot be found and the MinGW binaries are part of your system PATH: Keep in mind that the MinGW installation contains only a file called mingw32-make.exe, not make.exe. Create a copy of this file, call it make.exe, and make sure the corresponding parent folder is part of your system PATH. If the library is compiled successfully, you can try to run the tests. Note that your system has to fulfill the following prerequisites to this end: A Linux distribution set up via WSL (has been tested with Ubuntu 20.04 LTS from the Windows Store) and the 64bit gnu-make mentioned before. Further, make sure that the directory containing the FFTW-DLLs is part of your system PATH. Otherwise the executables built will not run. As soon as you have everything set up, run the following command:: @@ -478,7 +506,7 @@ or via:: cmake .. cmake --build . -j cd .. - + You may then run:: pip3 install -e python/finufft @@ -503,7 +531,7 @@ An additional performance test you could then do is:: .. note:: As of v2.0.1, our python interface is quite different from Dan Foreman-Mackey's original repo that wrapped finufft: `python-finufft `_, or Jeremy Magland's wrapper. The interface is simpler, and the existing shared binary is linked to (no recompilation). Under the hood we achieve this via ``ctypes`` instead of ``pybind11``. - + A few words about python environments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index af6f067bc..35ac5662c 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -1,17 +1,24 @@ -set(EXAMPLES guru1d1 guru1d1f guru2d1 many1d1 simple1d1 simple1d1f simulplans1d1) +set(EXAMPLES + guru1d1 + guru1d1f + guru2d1 + many1d1 + simple1d1 + simple1d1f + simulplans1d1) set(EXAMPLES_OPENMP threadsafe1d1 threadsafe2d2f) set(EXAMPLES_C guru1d1c simple1d1c simple1d1cf) foreach(EXAMPLE ${EXAMPLES}) - add_executable(${EXAMPLE} ${EXAMPLE}.cpp) - target_link_libraries(${EXAMPLE} PRIVATE finufft) - enable_asan(${EXAMPLE}) + add_executable(${EXAMPLE} ${EXAMPLE}.cpp) + target_link_libraries(${EXAMPLE} PRIVATE finufft) + enable_asan(${EXAMPLE}) endforeach() foreach(EXAMPLE ${EXAMPLES_C}) - add_executable(${EXAMPLE} ${EXAMPLE}.c) - target_link_libraries(${EXAMPLE} PRIVATE finufft) - enable_asan(${EXAMPLE}) + add_executable(${EXAMPLE} ${EXAMPLE}.c) + target_link_libraries(${EXAMPLE} PRIVATE finufft) + enable_asan(${EXAMPLE}) endforeach() if(FINUFFT_USE_OPENMP) @@ -21,7 +28,3 @@ if(FINUFFT_USE_OPENMP) enable_asan(${EXAMPLE}) endforeach() endif() - -if (FINUFFT_USE_CUDA) - add_subdirectory(cuda) -endif() diff --git a/perftest/cuda/CMakeLists.txt b/perftest/cuda/CMakeLists.txt index 9d817d5f6..5f1079fde 100644 --- a/perftest/cuda/CMakeLists.txt +++ b/perftest/cuda/CMakeLists.txt @@ -1,3 +1,4 @@ add_executable(cuperftest cuperftest.cu) target_include_directories(cuperftest PUBLIC ${CUFINUFFT_INCLUDE_DIRS}) target_link_libraries(cuperftest PUBLIC cufinufft) +#file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/bench.sh DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/python/cufinufft/pyproject.toml b/python/cufinufft/pyproject.toml index 4dc0711ea..6839934da 100644 --- a/python/cufinufft/pyproject.toml +++ b/python/cufinufft/pyproject.toml @@ -41,7 +41,7 @@ build-dir = "build/{wheel_tag}" # Tell skbuild to look for the CMakeLists.txt file two directories up. cmake.source-dir = "../../" cmake.targets = ["cufinufft"] -cmake.define = {"FINUFFT_BUILD_PYTHON" = "ON", "FINUFFT_USE_CUDA" = "ON", "FINUFFT_USE_CPU" = "OFF", "FINUFFT_ENABLE_INSTALL" = "OFF", "FINUFFT_STATIC_LINKING" = "OFF"} +cmake.define = {"FINUFFT_BUILD_PYTHON" = "ON", "FINUFFT_USE_CUDA" = "ON", "FINUFFT_USE_CPU" = "OFF"} wheel.packages = ["cufinufft"] diff --git a/python/finufft/pyproject.toml b/python/finufft/pyproject.toml index 822c5cafd..be6cc5809 100644 --- a/python/finufft/pyproject.toml +++ b/python/finufft/pyproject.toml @@ -41,7 +41,7 @@ build-dir = "build/{wheel_tag}" # Tell skbuild to look for the CMakeLists.txt file two directories up. cmake.source-dir = "../../" cmake.targets = ["finufft"] -cmake.define = {"FINUFFT_BUILD_PYTHON" = "ON", "FINUFFT_ENABLE_INSTALL" = "OFF", "FINUFFT_STATIC_LINKING" = "OFF"} +cmake.define = {"FINUFFT_BUILD_PYTHON" = "ON"} wheel.packages = ["finufft"] diff --git a/src/cuda/CMakeLists.txt b/src/cuda/CMakeLists.txt index c9f13344d..77b86ae77 100644 --- a/src/cuda/CMakeLists.txt +++ b/src/cuda/CMakeLists.txt @@ -1,60 +1,89 @@ - set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CUDA_SEPARABLE_COMPILATION ON) -set(PRECISION_INDEPENDENT_SRC precision_independent.cu utils.cpp - ${PROJECT_SOURCE_DIR}/contrib/legendre_rule_fast.cpp) +set(PRECISION_INDEPENDENT_SRC + precision_independent.cu utils.cpp + ${PROJECT_SOURCE_DIR}/contrib/legendre_rule_fast.cpp) set(PRECISION_DEPENDENT_SRC - spreadinterp.cpp - 1d/cufinufft1d.cu 1d/spread1d_wrapper.cu 1d/interp1d_wrapper.cu - 2d/cufinufft2d.cu 2d/spread2d_wrapper.cu 2d/interp2d_wrapper.cu - 3d/spread3d_wrapper.cu 3d/interp3d_wrapper.cu 3d/cufinufft3d.cu - memtransfer_wrapper.cu deconvolve_wrapper.cu cufinufft.cu common.cu -) + spreadinterp.cpp + 1d/cufinufft1d.cu + 1d/spread1d_wrapper.cu + 1d/interp1d_wrapper.cu + 2d/cufinufft2d.cu + 2d/spread2d_wrapper.cu + 2d/interp2d_wrapper.cu + 3d/spread3d_wrapper.cu + 3d/interp3d_wrapper.cu + 3d/cufinufft3d.cu + memtransfer_wrapper.cu + deconvolve_wrapper.cu + cufinufft.cu + common.cu) set(CUFINUFFT_INCLUDE_DIRS - ${PROJECT_SOURCE_DIR}/include - ${PROJECT_SOURCE_DIR}/contrib - $ - $ - $ -) -set(CUFINUFFT_INCLUDE_DIRS ${CUFINUFFT_INCLUDE_DIRS} PARENT_SCOPE) + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/contrib + $ + $ + $) +set(CUFINUFFT_INCLUDE_DIRS + ${CUFINUFFT_INCLUDE_DIRS} + PARENT_SCOPE) + +# flush denormals to zero and enable verbose PTXAS output +set(FINUFFT_CUDA_FLAGS + -ftz=true + -fmad=true + -restrict + --extra-device-vectorization + $<$:-G + -maxrregcount + 32>) add_library(cufinufft_common_objects OBJECT ${PRECISION_INDEPENDENT_SRC}) -target_include_directories(cufinufft_common_objects PUBLIC ${CUFINUFFT_INCLUDE_DIRS}) -set_property(TARGET cufinufft_common_objects PROPERTY POSITION_INDEPENDENT_CODE ON) +target_include_directories(cufinufft_common_objects + PUBLIC ${CUFINUFFT_INCLUDE_DIRS}) +set_target_properties( + cufinufft_common_objects + PROPERTIES POSITION_INDEPENDENT_CODE ${FINUFFT_SHARED_LINKING} + CUDA_ARCHITECTURES ${FINUFFT_CUDA_ARCHITECTURES}) + +target_compile_options( + cufinufft_common_objects + PRIVATE $<$:${FINUFFT_CUDA_FLAGS}>) add_library(cufinufft_objects OBJECT ${PRECISION_DEPENDENT_SRC}) target_include_directories(cufinufft_objects PUBLIC ${CUFINUFFT_INCLUDE_DIRS}) -set_property(TARGET cufinufft_objects PROPERTY POSITION_INDEPENDENT_CODE ON) - -if (FINUFFT_SHARED_LINKING) - add_library(cufinufft SHARED - $ - $ - ) - set_target_properties( - cufinufft PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - ) -else () - add_library(cufinufft STATIC - $ - $ - ) - set_target_properties( - cufinufft PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" - ) -endif () - -if (WIN32) - target_link_libraries(cufinufft PUBLIC CUDA::cudart CUDA::cufft CUDA::nvToolsExt) -else () - target_link_libraries(cufinufft PUBLIC CUDA::cudart_static CUDA::cufft_static CUDA::nvToolsExt) -endif () +set_target_properties( + cufinufft_objects + PROPERTIES POSITION_INDEPENDENT_CODE ${FINUFFT_SHARED_LINKING} + CUDA_ARCHITECTURES ${FINUFFT_CUDA_ARCHITECTURES}) +target_compile_options( + cufinufft_objects PRIVATE $<$:${FINUFFT_CUDA_FLAGS}>) + +if(FINUFFT_SHARED_LINKING) + add_library(cufinufft SHARED $ + $) + set_target_properties( + cufinufft PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + CUDA_ARCHITECTURES ${FINUFFT_CUDA_ARCHITECTURES}) +else() + add_library(cufinufft STATIC $ + $) + set_target_properties( + cufinufft PROPERTIES ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" + CUDA_ARCHITECTURES ${FINUFFT_CUDA_ARCHITECTURES}) +endif() + +if(WIN32) + target_link_libraries(cufinufft PUBLIC CUDA::cudart CUDA::cufft + CUDA::nvToolsExt) +else() + target_link_libraries(cufinufft PUBLIC CUDA::cudart_static CUDA::cufft_static + CUDA::nvToolsExt) +endif() file(GLOB CUFINUFFT_PUBLIC_HEADERS "${CMAKE_SOURCE_DIR}/include/cufinufft*.h") -set_target_properties(cufinufft PROPERTIES PUBLIC_HEADER "${CUFINUFFT_PUBLIC_HEADERS}") +set_target_properties(cufinufft PROPERTIES PUBLIC_HEADER + "${CUFINUFFT_PUBLIC_HEADERS}") diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 5fff14ccb..37050876b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,5 +1,14 @@ # Each of these source test files is instantiated in single and double precision -set(TESTS basicpassfail dumbinputs finufft1d_test finufft1dmany_test finufft2d_test finufft2dmany_test finufft3d_test finufft3dmany_test finufft3dkernel_test) +set(TESTS + basicpassfail + dumbinputs + finufft1d_test + finufft1dmany_test + finufft2d_test + finufft2dmany_test + finufft3d_test + finufft3dmany_test + finufft3dkernel_test) foreach(TEST ${TESTS}) add_executable(${TEST} ${TEST}.cpp) @@ -12,54 +21,73 @@ foreach(TEST ${TESTS}) finufft_link_test(${TEST}f) endforeach() +# copy the DLLs to the build directory so that the tests can find them there fix +# for windows +copy_dll(finufft basicpassfail) + # Add ctest definitions not for both precisions... add_executable(testutils testutils.cpp) -if (FINUFFT_USE_DUCC0) +if(FINUFFT_USE_DUCC0) target_compile_definitions(testutils PRIVATE -DFINUFFT_USE_DUCC0) -endif () +endif() finufft_link_test(testutils) -add_test(NAME run_testutils COMMAND testutils WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +add_test( + NAME run_testutils + COMMAND testutils + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) # Add ctest definitions that run at both precisions... function(add_tests_with_prec PREC REQ_TOL CHECK_TOL SUFFIX) - # All of the following should be run at OMP_NUM_THREADS=4 or something small, as in makefile. - # This prevents them taking a huge time on a, say, 128-core Rome node. - #... but I don't know platform-indep way to do that! Does anyone? - -add_test( - NAME run_basic_pass_fail_${PREC} - COMMAND basicpassfail${SUFFIX} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + # All of the following should be run at OMP_NUM_THREADS=4 or something small, + # as in makefile. This prevents them taking a huge time on a, say, 128-core + # Rome node. ... but I don't know platform-indep way to do that! Does anyone? -add_test( - NAME run_finufft1d_test_${PREC} - COMMAND finufft1d_test${SUFFIX} 1e2 2e2 ${REQ_TOL} 0 2 0.0 ${CHECK_TOL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test( + NAME run_basic_pass_fail_${PREC} + COMMAND basicpassfail${SUFFIX} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -add_test( - NAME run_finufft1dmany_test_${PREC} - COMMAND finufft1dmany_test${SUFFIX} 3 1e2 2e2 ${REQ_TOL} 0 0 0 2 0.0 ${CHECK_TOL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test( + NAME run_finufft1d_test_${PREC} + COMMAND finufft1d_test${SUFFIX} 1e2 2e2 ${REQ_TOL} 0 2 0.0 ${CHECK_TOL} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -add_test( - NAME run_finufft2d_test_${PREC} - COMMAND finufft2d_test${SUFFIX} 1e2 1e1 1e3 ${REQ_TOL} 0 2 0.0 ${CHECK_TOL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test( + NAME run_finufft1dmany_test_${PREC} + COMMAND finufft1dmany_test${SUFFIX} 3 1e2 2e2 ${REQ_TOL} 0 0 0 2 0.0 + ${CHECK_TOL} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -add_test( - NAME run_finufft2dmany_test_${PREC} - COMMAND finufft2dmany_test${SUFFIX} 3 1e2 1e1 1e3 ${REQ_TOL} 0 0 0 2 0.0 ${CHECK_TOL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test( + NAME run_finufft2d_test_${PREC} + COMMAND finufft2d_test${SUFFIX} 1e2 1e1 1e3 ${REQ_TOL} 0 2 0.0 ${CHECK_TOL} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -add_test( - NAME run_finufft3d_test_${PREC} - COMMAND finufft3d_test${SUFFIX} 5 10 20 1e2 ${REQ_TOL} 0 2 0.0 ${CHECK_TOL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test( + NAME run_finufft2dmany_test_${PREC} + COMMAND finufft2dmany_test${SUFFIX} 3 1e2 1e1 1e3 ${REQ_TOL} 0 0 0 2 0.0 + ${CHECK_TOL} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -add_test( - NAME run_finufft3dmany_test_${PREC} - COMMAND finufft3dmany_test${SUFFIX} 2 5 10 20 1e2 ${REQ_TOL} 0 0 0 2 0.0 ${CHECK_TOL} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test( + NAME run_finufft3d_test_${PREC} + COMMAND finufft3d_test${SUFFIX} 5 10 20 1e2 ${REQ_TOL} 0 2 0.0 ${CHECK_TOL} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) -add_test( - NAME run_dumbinputs_${PREC} - COMMAND dumbinputs${SUFFIX} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test( + NAME run_finufft3dmany_test_${PREC} + COMMAND finufft3dmany_test${SUFFIX} 2 5 10 20 1e2 ${REQ_TOL} 0 0 0 2 0.0 + ${CHECK_TOL} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + + add_test( + NAME run_dumbinputs_${PREC} + COMMAND dumbinputs${SUFFIX} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) endfunction() -# use above function to actually add the tests, with certain requested and check tols +# use above function to actually add the tests, with certain requested and check +# tols add_tests_with_prec(float 1e-5 2e-4 f) add_tests_with_prec(double 1e-12 1e-11 "") diff --git a/test/cuda/CMakeLists.txt b/test/cuda/CMakeLists.txt index 23b3346da..8d77d9fdc 100644 --- a/test/cuda/CMakeLists.txt +++ b/test/cuda/CMakeLists.txt @@ -7,6 +7,14 @@ foreach(srcfile ${test_src}) add_executable(${executable} ${srcfile}) target_include_directories(${executable} PUBLIC ${CUFINUFFT_INCLUDE_DIRS}) target_link_libraries(${executable} PUBLIC cufinufft m) + set_target_properties(${executable} PROPERTIES + LINKER_LANGUAGE CUDA + CUDA_ARCHITECTURES ${FINUFFT_CUDA_ARCHITECTURES} + ) + message(STATUS "Adding test ${executable}" + " with CUDA_ARCHITECTURES=${FINUFFT_CUDA_ARCHITECTURES}" + " and INCLUDE=${CUFINUFFT_INCLUDE_DIRS}" + ) endforeach() function(add_tests PREC REQ_TOL CHECK_TOL)