@@ -649,13 +649,144 @@ if (NOT TARGET dlib)
649649
650650
651651 if (DLIB_USE_CUDA)
652- find_package (CUDAToolkit 9.1 )
653- set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR} /cmake_utils)
654- find_package (CUDNN )
655- find_package (OpenMP )
656- set (openmp_libraries ${OpenMP_CXX_FLAGS} )
652+ find_package (CUDAToolkit QUIET )
657653
658- if (CUDAToolkit_FOUND AND CUDNN_FOUND AND OPENMP_FOUND)
654+ if (CUDA_VERSION VERSION_GREATER 9.1 AND CMAKE_VERSION VERSION_LESS 3.12.2)
655+ # This bit of weirdness is to work around a bug in cmake
656+ list (REMOVE_ITEM CUDA_CUBLAS_LIBRARIES "CUDA_cublas_device_LIBRARY-NOTFOUND" )
657+ endif ()
658+
659+
660+ if (CUDAToolkit_FOUND AND MSVC AND NOT TARGET CUDA::cublas AND "${CMAKE_SIZEOF_VOID_P} " EQUAL "4" )
661+ message (WARNING "You have CUDA installed, but we can't use it unless you put visual studio in 64bit mode." )
662+ set (CUDA_FOUND 0)
663+ endif ()
664+
665+ if (CUDAToolkit_FOUND)
666+
667+ # There is some bug in cmake that causes it to mess up the
668+ # -std=c++11 option if you let it propagate it to nvcc in some
669+ # cases. So instead we disable this and manually include
670+ # things from CMAKE_CXX_FLAGS in the CUDA_NVCC_FLAGS list below.
671+ if (APPLE )
672+ set (CUDA_PROPAGATE_HOST_FLAGS OFF )
673+ # Grab all the -D flags from CMAKE_CXX_FLAGS so we can pass them
674+ # to nvcc.
675+ string (REGEX MATCHALL "-D[^ ]*" FLAGS_FOR_NVCC "${CMAKE_CXX_FLAGS} " )
676+
677+ # Check if we are being built as part of a pybind11 module.
678+ if (COMMAND pybind11_add_module)
679+ # Don't export unnecessary symbols.
680+ list (APPEND FLAGS_FOR_NVCC "-Xcompiler=-fvisibility=hidden" )
681+ endif ()
682+ endif ()
683+
684+ set (CUDA_HOST_COMPILATION_CPP ON )
685+ string (REPLACE "," ";" DLIB_CUDA_COMPUTE_CAPABILITIES ${DLIB_USE_CUDA_COMPUTE_CAPABILITIES} )
686+ foreach (CAP ${DLIB_CUDA_COMPUTE_CAPABILITIES} )
687+ list (APPEND CUDA_NVCC_FLAGS "-gencode arch=compute_${CAP} ,code=[sm_${CAP} ,compute_${CAP} ]" )
688+ endforeach ()
689+ # Note that we add __STRICT_ANSI__ to avoid freaking out nvcc with gcc specific
690+ # magic in the standard C++ header files (since nvcc uses gcc headers on linux).
691+ list (APPEND CUDA_NVCC_FLAGS "-D__STRICT_ANSI__;-D_MWAITXINTRIN_H_INCLUDED;-D_FORCE_INLINES;${FLAGS_FOR_NVCC} " )
692+ list (APPEND CUDA_NVCC_FLAGS ${active_preprocessor_switches} )
693+ if (NOT DLIB_IN_PROJECT_BUILD)
694+ LIST (APPEND CUDA_NVCC_FLAGS -DDLIB__CMAKE_GENERATED_A_CONFIG_H_FILE)
695+ endif ()
696+ if (NOT MSVC )
697+ list (APPEND CUDA_NVCC_FLAGS "-std=c++14" )
698+ endif ()
699+ if (CMAKE_POSITION_INDEPENDENT_CODE )
700+ # sometimes this setting isn't propagated to NVCC, which then causes the
701+ # compile to fail. So make sure it's propagated.
702+ if (NOT MSVC ) # Visual studio doesn't have -fPIC so don't do it in that case.
703+ list (APPEND CUDA_NVCC_FLAGS "-Xcompiler -fPIC" )
704+ endif ()
705+ endif ()
706+
707+ include (cmake_utils/test_for_cudnn/find_cudnn.txt )
708+
709+ include (CheckLanguage )
710+ check_language (CUDA )
711+ set (cuda_compiler_found OFF )
712+ if (CMAKE_CUDA_COMPILER)
713+ set (cuda_compiler_found ON )
714+ else ()
715+ message (STATUS " *** Cannot find CUDA compiler. If you are on windows using Visual Studio, make sure to install 'Visual Studio Integration' in the cuda installer." )
716+ endif ()
717+
718+ if (cudnn AND cudnn_include AND cuda_compiler_found AND NOT DEFINED cuda_test_compile_worked AND NOT DEFINED cudnn_test_compile_worked)
719+ # make sure cuda is really working by doing a test compile
720+ enable_language (CUDA )
721+ message (STATUS "Building a CUDA test project to see if your compiler is compatible with CUDA..." )
722+
723+ set (CUDA_TEST_CMAKE_FLAGS
724+ "-DCMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH} "
725+ "-DCMAKE_INCLUDE_PATH=${CMAKE_INCLUDE_PATH} "
726+ "-DCMAKE_LIBRARY_PATH=${CMAKE_LIBRARY_PATH} " )
727+
728+ if (NOT MSVC ) # see https://github.com/davisking/dlib/issues/363
729+ list (APPEND CUDA_TEST_CMAKE_FLAGS "-DCUDA_HOST_COMPILER=${CUDA_HOST_COMPILER} " )
730+ endif ()
731+
732+ try_compile (cuda_test_compile_worked
733+ ${PROJECT_BINARY_DIR} /cuda_test_build
734+ ${PROJECT_SOURCE_DIR} /cmake_utils/test_for_cuda cuda_test
735+ CMAKE_FLAGS ${CUDA_TEST_CMAKE_FLAGS}
736+ OUTPUT_VARIABLE try_compile_output_message
737+ )
738+ if (NOT cuda_test_compile_worked)
739+ string (REPLACE "\n " "\n *** " try_compile_output_message "${try_compile_output_message} " )
740+ message (STATUS "*****************************************************************************************************************" )
741+ message (STATUS "*** CUDA was found but your compiler failed to compile a simple CUDA program so dlib isn't going to use CUDA. " )
742+ message (STATUS "*** The output of the failed CUDA test compile is shown below: " )
743+ message (STATUS "*** " )
744+ message (STATUS "*** ${try_compile_output_message} " )
745+ message (STATUS "*****************************************************************************************************************" )
746+ else ()
747+ message (STATUS "Building a cuDNN test project to check if you have the right version of cuDNN installed..." )
748+ try_compile (cudnn_test_compile_worked
749+ ${PROJECT_BINARY_DIR} /cudnn_test_build
750+ ${PROJECT_SOURCE_DIR} /cmake_utils/test_for_cudnn cudnn_test
751+ CMAKE_FLAGS ${CUDA_TEST_CMAKE_FLAGS}
752+ OUTPUT_VARIABLE try_compile_output_message
753+ )
754+ if (NOT cudnn_test_compile_worked)
755+ string (REPLACE "\n " "\n *** " try_compile_output_message "${try_compile_output_message} " )
756+ message (STATUS "*****************************************************************************************************" )
757+ message (STATUS "*** Found cuDNN, but we failed to compile the dlib/cmake_utils/test_for_cudnn project. " )
758+ message (STATUS "*** You either have an unsupported version of cuDNN or something is wrong with your cudDNN install." )
759+ message (STATUS "*** Since a functional cuDNN is not found DLIB WILL NOT USE CUDA. " )
760+ message (STATUS "*** The output of the failed test_for_cudnn build is: " )
761+ message (STATUS "*** " )
762+ message (STATUS "*** ${try_compile_output_message} " )
763+ message (STATUS "*****************************************************************************************************" )
764+ endif ()
765+ endif ()
766+ endif ()
767+ # Also find OpenMP since cuSOLVER needs it. Importantly, we only
768+ # look for one to link to if our use of BLAS, specifically the
769+ # Intel MKL, hasn't already decided what to use. This is because
770+ # it makes the MKL bug out if you link to another openmp lib other
771+ # than Intel's when you use the MKL. I'm also not really sure when
772+ # explicit linking to openmp became unnecessary, but for
773+ # sufficiently older versions of cuda it was needed. Then in
774+ # versions of cmake newer than 3.11 linking to openmp started to
775+ # mess up the switches passed to nvcc, so you can't just leave
776+ # these "try to link to openmp" statements here going forward. Fun
777+ # times.
778+ if (CUDA_VERSION VERSION_LESS "9.1" AND NOT openmp_libraries AND NOT MSVC AND NOT XCODE AND NOT APPLE )
779+ find_package (OpenMP )
780+ if (OPENMP_FOUND)
781+ set (openmp_libraries ${OpenMP_CXX_FLAGS} )
782+ else ()
783+ message (STATUS "*** Didn't find OpenMP, which is required to use CUDA. ***" )
784+ set (CUDA_FOUND 0)
785+ endif ()
786+ endif ()
787+ endif ()
788+
789+ if (CUDAToolkit_FOUND AND cudnn AND cuda_test_compile_worked AND cudnn_test_compile_worked AND cudnn_include)
659790 set (source_files ${source_files}
660791 cuda/cuda_dlib.cu
661792 cuda/cudnn_dlibapi.cpp
@@ -665,19 +796,22 @@ if (NOT TARGET dlib)
665796 cuda/cuda_data_ptr.cpp
666797 cuda/gpu_data.cpp
667798 )
799+ list (APPEND dlib_needed_private_libraries CUDA::toolkit)
668800 list (APPEND dlib_needed_private_libraries CUDA::cublas)
669- list (APPEND dlib_needed_private_libraries ${CUDNN_LIBRARY_PATH } )
801+ list (APPEND dlib_needed_private_libraries ${cudnn } )
670802 list (APPEND dlib_needed_private_libraries CUDA::curand)
671803 list (APPEND dlib_needed_private_libraries CUDA::cusolver)
672804 list (APPEND dlib_needed_private_libraries CUDA::cudart)
673- list (APPEND dlib_needed_private_libraries ${openmp_libraries} )
805+ if (openmp_libraries)
806+ list (APPEND dlib_needed_private_libraries ${openmp_libraries} )
807+ endif ()
674808
675- include_directories (${CUDAToolkit_INCLUDE_DIRS} ${CUDNN_INCLUDE_PATH } )
809+ include_directories (${cudnn_include } )
676810 message (STATUS "Enabling CUDA support for dlib. DLIB WILL USE CUDA, compute capabilities: ${DLIB_CUDA_COMPUTE_CAPABILITIES} " )
677811 else ()
678812 set (DLIB_USE_CUDA OFF CACHE BOOL ${DLIB_USE_BLAS_STR} FORCE )
679813 toggle_preprocessor_switch (DLIB_USE_CUDA )
680- if (NOT CUDA_FOUND )
814+ if (NOT CUDAToolkit_FOUND )
681815 message (STATUS "DID NOT FIND CUDA" )
682816 endif ()
683817 message (STATUS "Disabling CUDA support for dlib. DLIB WILL NOT USE CUDA" )
@@ -762,6 +896,9 @@ if (NOT TARGET dlib)
762896 target_compile_options (dlib PRIVATE "-DDLIB_CHECK_FOR_VERSION_MISMATCH=${DLIB_CHECK_FOR_VERSION_MISMATCH} " )
763897 endif ()
764898
899+ if (DLIB_USE_CUDA)
900+ set_target_properties (dlib PROPERTIES CUDA_ARCHITECTURES ${DLIB_CUDA_COMPUTE_CAPABILITIES} )
901+ endif ()
765902
766903 # Allow the unit tests to ask us to compile the all/source.cpp file just to make sure it compiles.
767904 if (DLIB_TEST_COMPILE_ALL_SOURCE_CPP)
0 commit comments