From ae279966c2c2e4d2db4a295b6397cc9aa832c794 Mon Sep 17 00:00:00 2001 From: Yashas Samaga B L Date: Sun, 2 Jun 2019 11:47:15 +0000 Subject: [PATCH] Merge pull request #14660 from YashasSamaga:dnn-cuda-build add cuDNN dependency and setup build for cuda4dnn (#14660) * update cmake for cuda4dnn - Adds FindCUDNN - Adds new options: * WITH_CUDA * OPENCV_DNN_CUDA - Adds CUDA4DNN preprocessor symbol for the DNN module * FIX: append EXCLUDE_CUDA instead of overwrite * remove cuDNN dependency for user apps * fix unused variable warning --- CMakeLists.txt | 11 +++ cmake/FindCUDNN.cmake | 105 +++++++++++++++++++++ cmake/OpenCVDetectCUDA.cmake | 22 ++++- cmake/OpenCVMinDepVersions.cmake | 1 + cmake/OpenCVModule.cmake | 2 +- cmake/OpenCVPackaging.cmake | 7 +- cmake/templates/OpenCVConfig-CUDA.cmake.in | 3 + cmake/templates/cvconfig.h.in | 7 +- modules/dnn/CMakeLists.txt | 17 +++- .../hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake | 14 ++- modules/dnn/src/cuda/test.cu | 18 ++++ modules/dnn/src/cuda4dnn/test.cpp | 18 ++++ modules/dnn/src/precomp.hpp | 14 ++- 13 files changed, 228 insertions(+), 11 deletions(-) create mode 100644 cmake/FindCUDNN.cmake create mode 100644 modules/dnn/src/cuda/test.cu create mode 100644 modules/dnn/src/cuda4dnn/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 70ffb5e..9f09e3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -249,6 +249,9 @@ OCV_OPTION(WITH_CUFFT "Include NVidia Cuda Fast Fourier Transform (FFT) library OCV_OPTION(WITH_CUBLAS "Include NVidia Cuda Basic Linear Algebra Subprograms (BLAS) library support" WITH_CUDA VISIBLE_IF WITH_CUDA VERIFY HAVE_CUBLAS) +OCV_OPTION(WITH_CUDNN "Include NVIDIA CUDA Deep Neural Network (cuDNN) library support" WITH_CUDA + VISIBLE_IF WITH_CUDA + VERIFY HAVE_CUDNN) OCV_OPTION(WITH_NVCUVID "Include NVidia Video Decoding library support" WITH_CUDA VISIBLE_IF WITH_CUDA VERIFY HAVE_NVCUVID) @@ -918,6 +921,9 @@ if(HAVE_CUDA) if(HAVE_CUBLAS) set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_cublas_LIBRARY}) endif() + if(HAVE_CUDNN) + set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDNN_LIBRARIES}) + endif() if(HAVE_CUFFT) set(OPENCV_LINKER_LIBS ${OPENCV_LINKER_LIBS} ${CUDA_cufft_LIBRARY}) endif() @@ -1573,6 +1579,11 @@ if(WITH_CUDA OR HAVE_CUDA) status(" NVIDIA GPU arch:" ${OPENCV_CUDA_ARCH_BIN}) status(" NVIDIA PTX archs:" ${OPENCV_CUDA_ARCH_PTX}) endif() + endif() + + if(WITH_CUDNN OR HAVE_CUDNN) + status("") + status(" cuDNN:" HAVE_CUDNN THEN "YES (ver ${CUDNN_VERSION})" ELSE NO) endif() if(WITH_VULKAN OR HAVE_VULKAN) diff --git a/cmake/FindCUDNN.cmake b/cmake/FindCUDNN.cmake new file mode 100644 index 0000000..e115f80 --- /dev/null +++ b/cmake/FindCUDNN.cmake @@ -0,0 +1,105 @@ +# template taken from https://cmake.org/cmake/help/v3.14/manual/cmake-developer.7.html + +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindCUDNN +--------- + +Finds the cuDNN library. + +Requires: +^^^^^^^^^ + +find_cuda_helper_libs from FindCUDA.cmake +i.e. CUDA module should be found using FindCUDA.cmake before attempting to find cuDNN + +Result Variables +^^^^^^^^^^^^^^^^ + +This will define the following variables: + +``CUDNN_FOUND`` +``CUDNN_INCLUDE_DIRS`` location of cudnn.h +``CUDNN_LIBRARIES`` location of cudnn library + +Cache Variables +^^^^^^^^^^^^^^^ + +The following cache variables will be set if cuDNN was found. They may also be set on failure. + +``CUDNN_LIBRARY`` +``CUDNN_INCLUDE_DIR`` +``CUDNN_VERSION`` + +``CUDNN_VERSION_MAJOR`` INTERNAL +``CUDNN_VERSION_MINOR`` INTERNAL +``CUDNN_VERSION_PATCH`` INTERNAL + +#]=======================================================================] + +# find the library +if(CUDA_FOUND) + find_cuda_helper_libs(cudnn) + set(CUDNN_LIBRARY ${CUDA_cudnn_LIBRARY} CACHE FILEPATH "location of the cuDNN library") + unset(CUDA_cudnn_LIBRARY CACHE) +endif() + +# find the include +if(CUDNN_LIBRARY) + find_path(CUDNN_INCLUDE_DIR + cudnn.h + PATHS ${CUDA_TOOLKIT_INCLUDE} + DOC "location of cudnn.h" + NO_DEFAULT_PATH + ) + + if(NOT CUDNN_INCLUDE_DIR) + find_path(CUDNN_INCLUDE_DIR + cudnn.h + DOC "location of cudnn.h" + ) + endif() +endif() + +# extract version from the include +if(CUDNN_INCLUDE_DIR) + file(READ "${CUDNN_INCLUDE_DIR}/cudnn.h" CUDNN_H_CONTENTS) + + string(REGEX MATCH "define CUDNN_MAJOR ([0-9]+)" _ "${CUDNN_H_CONTENTS}") + set(CUDNN_MAJOR_VERSION ${CMAKE_MATCH_1} CACHE INTERNAL "") + string(REGEX MATCH "define CUDNN_MINOR ([0-9]+)" _ "${CUDNN_H_CONTENTS}") + set(CUDNN_MINOR_VERSION ${CMAKE_MATCH_1} CACHE INTERNAL "") + string(REGEX MATCH "define CUDNN_PATCHLEVEL ([0-9]+)" _ "${CUDNN_H_CONTENTS}") + set(CUDNN_PATCH_VERSION ${CMAKE_MATCH_1} CACHE INTERNAL "") + + set(CUDNN_VERSION + "${CUDNN_MAJOR_VERSION}.${CUDNN_MINOR_VERSION}.${CUDNN_PATCH_VERSION}" + CACHE + STRING + "cuDNN version" + ) + + unset(CUDNN_H_CONTENTS) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CUDNN + FOUND_VAR CUDNN_FOUND + REQUIRED_VARS + CUDNN_LIBRARY + CUDNN_INCLUDE_DIR + VERSION_VAR CUDNN_VERSION +) + +if(CUDNN_FOUND) + set(CUDNN_LIBRARIES ${CUDNN_LIBRARY}) + set(CUDNN_INCLUDE_DIRS ${CUDNN_INCLUDE_DIR}) +endif() + +mark_as_advanced( + CUDNN_LIBRARY + CUDNN_INCLUDE_DIR + CUDNN_VERSION +) diff --git a/cmake/OpenCVDetectCUDA.cmake b/cmake/OpenCVDetectCUDA.cmake index 050ee65..35c5409 100644 --- a/cmake/OpenCVDetectCUDA.cmake +++ b/cmake/OpenCVDetectCUDA.cmake @@ -37,6 +37,16 @@ if(CUDA_FOUND) set(HAVE_CUBLAS 1) endif() + if(WITH_CUDNN) + set(CMAKE_MODULE_PATH "${OpenCV_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) + find_host_package(CUDNN "${MIN_VER_CUDNN}") + list(REMOVE_AT CMAKE_MODULE_PATH 0) + + if(CUDNN_FOUND) + set(HAVE_CUDNN 1) + endif() + endif() + if(WITH_NVCUVID) find_cuda_helper_libs(nvcuvid) if(WIN32) @@ -293,6 +303,13 @@ if(HAVE_CUDA) endforeach() endif() + if(HAVE_CUDNN) + foreach(p ${CUDNN_LIBRARIES}) + get_filename_component(_tmp ${p} PATH) + list(APPEND CUDA_LIBS_PATH ${_tmp}) + endforeach() + endif() + if(HAVE_CUFFT) foreach(p ${CUDA_cufft_LIBRARY}) get_filename_component(_tmp ${p} PATH) @@ -311,7 +328,10 @@ if(HAVE_CUDA) set(CUDA_cublas_LIBRARY_ABS ${CUDA_cublas_LIBRARY}) ocv_convert_to_lib_name(CUDA_cublas_LIBRARY ${CUDA_cublas_LIBRARY}) endif() - + if(HAVE_CUDNN) + set(CUDNN_LIBRARIES_ABS ${CUDNN_LIBRARIES}) + ocv_convert_to_lib_name(CUDNN_LIBRARIES ${CUDNN_LIBRARIES}) + endif() if(HAVE_CUFFT) set(CUDA_cufft_LIBRARY_ABS ${CUDA_cufft_LIBRARY}) ocv_convert_to_lib_name(CUDA_cufft_LIBRARY ${CUDA_cufft_LIBRARY}) diff --git a/cmake/OpenCVMinDepVersions.cmake b/cmake/OpenCVMinDepVersions.cmake index d962780..f4afdf7 100644 --- a/cmake/OpenCVMinDepVersions.cmake +++ b/cmake/OpenCVMinDepVersions.cmake @@ -1,5 +1,6 @@ set(MIN_VER_CMAKE 3.5.1) set(MIN_VER_CUDA 6.5) +set(MIN_VER_CUDNN 6) set(MIN_VER_PYTHON2 2.7) set(MIN_VER_PYTHON3 3.2) set(MIN_VER_ZLIB 1.2.3) diff --git a/cmake/OpenCVModule.cmake b/cmake/OpenCVModule.cmake index 3aef09a..2ac4656 100644 --- a/cmake/OpenCVModule.cmake +++ b/cmake/OpenCVModule.cmake @@ -33,7 +33,7 @@ # The verbose template for OpenCV module: # # ocv_add_module(modname ) -# ocv_glob_module_sources(([EXCLUDE_CUDA] ) +# ocv_glob_module_sources(([EXCLUDE_OPENCL] [EXCLUDE_CUDA] ) # or glob them manually and ocv_set_module_sources(...) # ocv_module_include_directories() # ocv_create_module() diff --git a/cmake/OpenCVPackaging.cmake b/cmake/OpenCVPackaging.cmake index 5db02e1..5784ff3 100644 --- a/cmake/OpenCVPackaging.cmake +++ b/cmake/OpenCVPackaging.cmake @@ -99,10 +99,15 @@ if(HAVE_CUDA) set(CPACK_DEB_libs_PACKAGE_DEPENDS "${CPACK_DEB_libs_PACKAGE_DEPENDS}, cuda-cufft-${cuda_version_suffix}") set(CPACK_DEB_dev_PACKAGE_DEPENDS "${CPACK_DEB_dev_PACKAGE_DEPENDS}, cuda-cufft-dev-${cuda_version_suffix}") endif() - if(HAVE_HAVE_CUBLAS) + if(HAVE_CUBLAS) set(CPACK_DEB_libs_PACKAGE_DEPENDS "${CPACK_DEB_libs_PACKAGE_DEPENDS}, cuda-cublas-${cuda_version_suffix}") set(CPACK_DEB_dev_PACKAGE_DEPENDS "${CPACK_DEB_dev_PACKAGE_DEPENDS}, cuda-cublas-dev-${cuda_version_suffix}") endif() + if(HAVE_CUDNN) + # TODO + #ex: libcudnn7_7.5.1.10-1+cuda10.1_amd64 + #ex: libcudnn7-dev_7.5.1.10-1+cuda10.1_amd64 + endif() endif() set(CPACK_COMPONENT_dev_DEPENDS libs) endif() diff --git a/cmake/templates/OpenCVConfig-CUDA.cmake.in b/cmake/templates/OpenCVConfig-CUDA.cmake.in index b48cfba..e71c9e2 100644 --- a/cmake/templates/OpenCVConfig-CUDA.cmake.in +++ b/cmake/templates/OpenCVConfig-CUDA.cmake.in @@ -6,6 +6,9 @@ set(OpenCV_USE_CUBLAS "@HAVE_CUBLAS@") set(OpenCV_USE_CUFFT "@HAVE_CUFFT@") set(OpenCV_USE_NVCUVID "@HAVE_NVCUVID@") +set(OpenCV_CUDNN_VERSION "@CUDNN_VERSION@") +set(OpenCV_USE_CUDNN "@HAVE_CUDNN@") + if(NOT CUDA_FOUND) find_host_package(CUDA ${OpenCV_CUDA_VERSION} EXACT REQUIRED) else() diff --git a/cmake/templates/cvconfig.h.in b/cmake/templates/cvconfig.h.in index 1f7981c..0bc4a4d 100644 --- a/cmake/templates/cvconfig.h.in +++ b/cmake/templates/cvconfig.h.in @@ -34,11 +34,14 @@ /* Cocoa API */ #cmakedefine HAVE_COCOA +/* NVIDIA CUDA Runtime API*/ +#cmakedefine HAVE_CUDA + /* NVIDIA CUDA Basic Linear Algebra Subprograms (BLAS) API*/ #cmakedefine HAVE_CUBLAS -/* NVIDIA CUDA Runtime API*/ -#cmakedefine HAVE_CUDA +/* NVIDIA CUDA Deep Neural Network (cuDNN) API*/ +#cmakedefine HAVE_CUDNN /* NVIDIA CUDA Fast Fourier Transform (FFT) API*/ #cmakedefine HAVE_CUFFT diff --git a/modules/dnn/CMakeLists.txt b/modules/dnn/CMakeLists.txt index 7682257..f1c2eb7 100644 --- a/modules/dnn/CMakeLists.txt +++ b/modules/dnn/CMakeLists.txt @@ -16,10 +16,16 @@ ocv_option(OPENCV_DNN_OPENCL "Build with OpenCL support" HAVE_OPENCL AND NOT APP if(OPENCV_DNN_OPENCL AND HAVE_OPENCL) add_definitions(-DCV_OCL4DNN=1) -else() - ocv_cmake_hook_append(INIT_MODULE_SOURCES_opencv_dnn "${CMAKE_CURRENT_LIST_DIR}/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake") endif() +ocv_option(OPENCV_DNN_CUDA "Build with CUDA support" HAVE_CUDA AND HAVE_CUBLAS AND HAVE_CUDNN) + +if(OPENCV_DNN_CUDA AND HAVE_CUDA AND HAVE_CUBLAS AND HAVE_CUDNN) + add_definitions(-DCV_CUDA4DNN=1) +endif() + +ocv_cmake_hook_append(INIT_MODULE_SOURCES_opencv_dnn "${CMAKE_CURRENT_LIST_DIR}/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake") + if(MSVC) add_definitions( -D_CRT_SECURE_NO_WARNINGS=1 ) ocv_warnings_disable(CMAKE_CXX_FLAGS /wd4244 /wd4267 /wd4018 /wd4355 /wd4800 /wd4251 /wd4996 /wd4146 @@ -73,12 +79,19 @@ endif() set(include_dirs ${fw_inc}) set(sources_options "") set(libs libprotobuf ${LAPACK_LIBRARIES}) + if(OPENCV_DNN_OPENCL AND HAVE_OPENCL) list(APPEND include_dirs ${OPENCL_INCLUDE_DIRS}) else() set(sources_options EXCLUDE_OPENCL) endif() +if(OPENCV_DNN_CUDA AND HAVE_CUDA AND HAVE_CUBLAS AND HAVE_CUDNN) + list(APPEND include_dirs ${CUDA_TOOLKIT_INCLUDE} ${CUDNN_INCLUDE_DIRS}) +else() + set(sources_options ${sources_options} EXCLUDE_CUDA) +endif() + ocv_module_include_directories(${include_dirs}) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") ocv_append_source_files_cxx_compiler_options(fw_srcs "-Wno-suggest-override") # GCC diff --git a/modules/dnn/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake b/modules/dnn/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake index f19002d..a4d6802 100644 --- a/modules/dnn/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake +++ b/modules/dnn/cmake/hooks/INIT_MODULE_SOURCES_opencv_dnn.cmake @@ -1,3 +1,11 @@ -message(STATUS "opencv_dnn: filter out ocl4dnn source code") -ocv_list_filterout(OPENCV_MODULE_${the_module}_SOURCES "/ocl4dnn/") -ocv_list_filterout(OPENCV_MODULE_${the_module}_HEADERS "/ocl4dnn/") +if(NOT (OPENCV_DNN_OPENCL AND HAVE_OPENCL)) + message(STATUS "opencv_dnn: filter out ocl4dnn source code") + ocv_list_filterout(OPENCV_MODULE_${the_module}_SOURCES "/ocl4dnn/") + ocv_list_filterout(OPENCV_MODULE_${the_module}_HEADERS "/ocl4dnn/") +endif() + +if(NOT (OPENCV_DNN_CUDA AND HAVE_CUDA AND HAVE_CUBLAS AND HAVE_CUDNN)) + message(STATUS "opencv_dnn: filter out cuda4dnn source code") + ocv_list_filterout(OPENCV_MODULE_${the_module}_SOURCES "/cuda4dnn/") + ocv_list_filterout(OPENCV_MODULE_${the_module}_HEADERS "/cuda4dnn/") +endif() diff --git a/modules/dnn/src/cuda/test.cu b/modules/dnn/src/cuda/test.cu new file mode 100644 index 0000000..1a50e97 --- /dev/null +++ b/modules/dnn/src/cuda/test.cu @@ -0,0 +1,18 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// this file is a stub and will be removed once actual code is added + +#include "../precomp.hpp" + +#include + +#ifndef HAVE_CUDA +# error "CUDA files should not be compiled if CUDA was not enabled" +#endif + +__global__ void cuda4dnn_build_test_kernel(float* addr) { + int idx = threadIdx.x; + addr[idx] = 0.0; +} diff --git a/modules/dnn/src/cuda4dnn/test.cpp b/modules/dnn/src/cuda4dnn/test.cpp new file mode 100644 index 0000000..066d919 --- /dev/null +++ b/modules/dnn/src/cuda4dnn/test.cpp @@ -0,0 +1,18 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +// this file is a stub and will be removed once actual code is added + +#include "../precomp.hpp" + +#ifndef HAVE_CUDA +# error "CUDA4DNN should be enabled iff CUDA and cuDNN were found" +#endif + +#include + +void cuda4dnn_build_test_func() { + auto ver = cudnnGetVersion(); + CV_UNUSED(ver); +} diff --git a/modules/dnn/src/precomp.hpp b/modules/dnn/src/precomp.hpp index 6266e1e..00e5522 100644 --- a/modules/dnn/src/precomp.hpp +++ b/modules/dnn/src/precomp.hpp @@ -53,10 +53,22 @@ #else #undef HAVE_OPENCL #endif + +#ifndef CV_CUDA4DNN +#define CV_CUDA4DNN 0 +#endif + +#if CV_CUDA4DNN +#ifndef HAVE_CUDA +#error "Configuration error: re-run CMake from clean build directory" +#endif +#else +#undef HAVE_CUDA +#endif + #include #include - #include #include #include -- 2.7.4