Skip to content

Commit 20d5d1c

Browse files
committed
Merge pull request opencv#19470 from alalek:core_parallel_plugins
2 parents 928d5ae + cc73c36 commit 20d5d1c

35 files changed

+1509
-354
lines changed

cmake/OpenCVCompilerOptions.cmake

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,9 @@ if(MSVC)
304304
endif()
305305
endif()
306306

307-
include(cmake/OpenCVCompilerOptimizations.cmake)
307+
if(PROJECT_NAME STREQUAL "OpenCV")
308+
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVCompilerOptimizations.cmake")
309+
endif()
308310
if(COMMAND ocv_compiler_optimization_options)
309311
ocv_compiler_optimization_options()
310312
endif()

cmake/OpenCVDetectTBB.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Search TBB library (4.1 - 4.4, 2017)
1+
# Search TBB library: 4.1 - 4.4, 2017-2020, 2021+ (oneTBB)
22
#
33
# Own TBB (3rdparty/tbb):
44
# - set cmake option BUILD_TBB to ON

cmake/OpenCVPluginStandalone.cmake

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Standalone OpenCV plugins build scripts
2+
#
3+
# Useful OpenCV common build variables:
4+
# - CMAKE_BUILD_TYPE=Release/Debug
5+
# - BUILD_WITH_DEBUG_INFO=ON
6+
# - ENABLE_BUILD_HARDENING=ON
7+
#
8+
# Plugin configuration variables:
9+
# - OPENCV_PLUGIN_DEPS - set of extra dependencies (modules), used for include dirs, target_link_libraries
10+
# - OPENCV_PLUGIN_SUFFIX
11+
# - OPENCV_PLUGIN_NAME
12+
# - OPENCV_PLUGIN_OUTPUT_NAME_FULL (overrides both OPENCV_PLUGIN_NAME / OPENCV_PLUGIN_SUFFIX)
13+
#
14+
#=============================================
15+
16+
if(NOT OpenCV_SOURCE_DIR)
17+
message(FATAL_ERROR "OpenCV_SOURCE_DIR must be set to build the plugin!")
18+
endif()
19+
20+
if(NOT DEFINED CMAKE_BUILD_TYPE)
21+
set(CMAKE_BUILD_TYPE "Release")
22+
endif()
23+
message(STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
24+
25+
set(BUILD_SHARED_LIBS ON CACHE BOOL "")
26+
if(NOT BUILD_SHARED_LIBS)
27+
message(FATAL_ERROR "Static plugin build does not make sense")
28+
endif()
29+
30+
# re-use OpenCV build scripts
31+
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVUtils.cmake")
32+
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectCXXCompiler.cmake")
33+
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVCompilerOptions.cmake")
34+
35+
function(ocv_create_plugin module default_name dependency_target dependency_target_desc)
36+
37+
set(OPENCV_PLUGIN_NAME ${default_name} CACHE STRING "")
38+
set(OPENCV_PLUGIN_DESTINATION "" CACHE PATH "")
39+
project(${OPENCV_PLUGIN_NAME} LANGUAGES CXX)
40+
41+
if(NOT TARGET ${dependency_target})
42+
message(FATAL_ERROR "${dependency_target_desc} was not found! (missing target ${dependency_target})")
43+
endif()
44+
45+
set(modules_ROOT "${OpenCV_SOURCE_DIR}/modules")
46+
set(module_ROOT "${modules_ROOT}/${module}")
47+
48+
foreach(src ${ARGN})
49+
list(APPEND sources "${module_ROOT}/${src}")
50+
endforeach()
51+
52+
add_library(${OPENCV_PLUGIN_NAME} MODULE
53+
"${sources}"
54+
${OPENCV_PLUGIN_EXTRA_SRC_FILES}
55+
)
56+
57+
if(OPENCV_PLUGIN_DEPS)
58+
foreach(d ${OPENCV_PLUGIN_DEPS})
59+
list(APPEND OPENCV_PLUGIN_EXTRA_INCLUDES "${modules_ROOT}/${d}/include")
60+
endforeach()
61+
endif()
62+
63+
target_include_directories(${OPENCV_PLUGIN_NAME} PRIVATE
64+
"${CMAKE_CURRENT_BINARY_DIR}"
65+
"${module_ROOT}/src"
66+
"${module_ROOT}/include"
67+
${OPENCV_PLUGIN_EXTRA_INCLUDES}
68+
)
69+
target_compile_definitions(${OPENCV_PLUGIN_NAME} PRIVATE "BUILD_PLUGIN=1")
70+
71+
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${dependency_target})
72+
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES
73+
CXX_STANDARD 11
74+
CXX_VISIBILITY_PRESET hidden
75+
)
76+
77+
if(DEFINED OPENCV_PLUGIN_MODULE_PREFIX)
78+
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES PREFIX "${OPENCV_PLUGIN_MODULE_PREFIX}")
79+
endif()
80+
81+
# Hack for Windows only, Linux/MacOS uses global symbol table (without exact .so binding)
82+
if(WIN32)
83+
find_package(OpenCV REQUIRED ${module} ${OPENCV_PLUGIN_DEPS})
84+
target_link_libraries(${OPENCV_PLUGIN_NAME} PRIVATE ${OpenCV_LIBRARIES})
85+
endif()
86+
87+
if(NOT OpenCV_FOUND) # build against sources (Linux)
88+
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/opencv2/opencv_modules.hpp" "#pragma once")
89+
endif()
90+
91+
if(WIN32)
92+
ocv_update(OPENCV_DEBUG_POSTFIX d)
93+
endif()
94+
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES DEBUG_POSTFIX "${OPENCV_DEBUG_POSTFIX}")
95+
96+
if(DEFINED OPENCV_PLUGIN_SUFFIX)
97+
# custom value
98+
else()
99+
if(WIN32)
100+
ocv_update(OPENCV_PLUGIN_VERSION "${OpenCV_VERSION_MAJOR}${OpenCV_VERSION_MINOR}${OpenCV_VERSION_PATCH}")
101+
if(CMAKE_CXX_SIZEOF_DATA_PTR EQUAL 8)
102+
ocv_update(OPENCV_PLUGIN_ARCH "_64")
103+
else()
104+
ocv_update(OPENCV_PLUGIN_ARCH "")
105+
endif()
106+
else()
107+
# empty
108+
endif()
109+
ocv_update(OPENCV_PLUGIN_SUFFIX "${OPENCV_PLUGIN_VERSION}${OPENCV_PLUGIN_ARCH}")
110+
endif()
111+
112+
if(OPENCV_PLUGIN_DESTINATION)
113+
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${OPENCV_PLUGIN_DESTINATION}")
114+
message(STATUS "Output destination: ${OPENCV_PLUGIN_DESTINATION}")
115+
endif()
116+
117+
if(OPENCV_PLUGIN_OUTPUT_NAME_FULL)
118+
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES OUTPUT_NAME "${OPENCV_PLUGIN_OUTPUT_NAME_FULL}")
119+
elseif(OPENCV_PLUGIN_OUTPUT_NAME)
120+
set_target_properties(${OPENCV_PLUGIN_NAME} PROPERTIES OUTPUT_NAME "${OPENCV_PLUGIN_OUTPUT_NAME}${OPENCV_PLUGIN_SUFFIX}")
121+
endif()
122+
123+
install(TARGETS ${OPENCV_PLUGIN_NAME} LIBRARY DESTINATION . COMPONENT plugins)
124+
125+
message(STATUS "Library name: ${OPENCV_PLUGIN_NAME}")
126+
127+
endfunction()

cmake/OpenCVUtils.cmake

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,9 @@ macro(ocv_check_flag_support lang flag varname base_options)
573573
string(REGEX REPLACE "^(/|-)" "HAVE_${_lang}_" ${varname} "${${varname}}")
574574
string(REGEX REPLACE " -|-|=| |\\.|," "_" ${varname} "${${varname}}")
575575

576-
ocv_check_compiler_flag("${_lang}" "${base_options} ${flag}" ${${varname}} ${ARGN})
576+
if(DEFINED CMAKE_${_lang}_COMPILER)
577+
ocv_check_compiler_flag("${_lang}" "${base_options} ${flag}" ${${varname}} ${ARGN})
578+
endif()
577579
endmacro()
578580

579581
macro(ocv_check_runtime_flag flag result)
@@ -1571,6 +1573,30 @@ function(ocv_add_library target)
15711573
endfunction()
15721574

15731575

1576+
function(ocv_add_external_target name inc link def)
1577+
if(BUILD_SHARED_LIBS)
1578+
set(imp IMPORTED)
1579+
endif()
1580+
add_library(ocv.3rdparty.${name} INTERFACE ${imp})
1581+
set_target_properties(ocv.3rdparty.${name} PROPERTIES
1582+
INTERFACE_INCLUDE_DIRECTORIES "${inc}"
1583+
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${inc}"
1584+
INTERFACE_COMPILE_DEFINITIONS "${def}")
1585+
# When cmake version is greater than or equal to 3.11, INTERFACE_LINK_LIBRARIES no longer applies to interface library
1586+
# See https://github.com/opencv/opencv/pull/18658
1587+
if (CMAKE_VERSION VERSION_LESS 3.11)
1588+
set_target_properties(ocv.3rdparty.${name} PROPERTIES
1589+
INTERFACE_LINK_LIBRARIES "${link}")
1590+
else()
1591+
target_link_libraries(ocv.3rdparty.${name} INTERFACE ${link})
1592+
endif()
1593+
#
1594+
if(NOT BUILD_SHARED_LIBS)
1595+
install(TARGETS ocv.3rdparty.${name} EXPORT OpenCVModules)
1596+
endif()
1597+
endfunction()
1598+
1599+
15741600
macro(ocv_get_libname var_name)
15751601
get_filename_component(__libname "${ARGN}" NAME)
15761602
# libopencv_core.so.3.3 -> opencv_core

modules/core/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ ocv_add_dispatched_file_force_all(test_intrin128 TEST SSE2 SSE3 SSSE3 SSE4_1 SSE
1717
ocv_add_dispatched_file_force_all(test_intrin256 TEST AVX2 AVX512_SKX)
1818
ocv_add_dispatched_file_force_all(test_intrin512 TEST AVX512_SKX)
1919

20+
21+
# parallel backends configuration
22+
set(PARALLEL_ENABLE_PLUGINS "ON" CACHE BOOL "Allow building parallel plugin support")
23+
# TODO building plugins with OpenCV is not supported yet
24+
#set(PARALLEL_PLUGIN_LIST "" CACHE STRING "List of parallel backends to be compiled as plugins (tbb, openmp or special value 'all')")
25+
#string(REPLACE "," ";" PARALLEL_PLUGIN_LIST "${PARALLEL_PLUGIN_LIST}") # support comma-separated list (,) too
26+
27+
2028
ocv_add_module(core
2129
OPTIONAL opencv_cudev
2230
WRAP java objc python js)
@@ -117,6 +125,14 @@ elseif(HAVE_CXX11 OR DEFINED OPENCV_ALLOCATOR_STATS_COUNTER_TYPE)
117125
endif()
118126

119127

128+
if(PARALLEL_ENABLE_PLUGINS)
129+
ocv_append_source_file_compile_definitions(${CMAKE_CURRENT_SOURCE_DIR}/src/parallel/parallel.cpp "PARALLEL_ENABLE_PLUGINS=1")
130+
if(OPENCV_DEBUG_POSTFIX)
131+
ocv_append_source_file_compile_definitions("${CMAKE_CURRENT_LIST_DIR}/src/parallel/parallel.cpp" "DEBUG_POSTFIX=${OPENCV_DEBUG_POSTFIX}")
132+
endif()
133+
endif()
134+
135+
120136
ocv_create_module(${extra_libs})
121137

122138
ocv_target_link_libraries(${the_module} PRIVATE
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
if(CMAKE_VERSION VERSION_LESS "3.9")
2+
message(STATUS "OpenMP detection requires CMake 3.9+") # OpenMP::OpenMP_CXX target
3+
endif()
4+
5+
find_package(OpenMP)
6+
if(OpenMP_FOUND)
7+
if(TARGET OpenMP::OpenMP_CXX)
8+
set(HAVE_OPENMP 1)
9+
ocv_add_external_target(openmp "" "OpenMP::OpenMP_CXX" "HAVE_OPENMP=1")
10+
else()
11+
message(WARNING "OpenMP: missing OpenMP::OpenMP_CXX target")
12+
endif()
13+
endif()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
include("${OpenCV_SOURCE_DIR}/cmake/OpenCVDetectTBB.cmake")
2+
3+
if(HAVE_TBB)
4+
ocv_add_external_target(tbb "" "tbb" "HAVE_TBB=1")
5+
endif()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
macro(ocv_add_core_parallel_backend backend_id cond_var)
2+
if(${cond_var})
3+
include("${CMAKE_CURRENT_LIST_DIR}/detect_${backend_id}.cmake")
4+
endif()
5+
endmacro()
6+
7+
ocv_add_core_parallel_backend("tbb" WITH_TBB)
8+
ocv_add_core_parallel_backend("openmp" WITH_OPENMP)

modules/core/include/opencv2/core/llapi/llapi.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ Using this approach OpenCV provides some basic low level functionality for exter
2727
#define CV_API_CALL
2828
#endif
2929

30+
#ifndef CV_PLUGIN_EXPORTS
31+
#if (defined _WIN32 || defined WINCE || defined __CYGWIN__)
32+
# define CV_PLUGIN_EXPORTS __declspec(dllexport)
33+
#elif defined __GNUC__ && __GNUC__ >= 4
34+
# define CV_PLUGIN_EXPORTS __attribute__ ((visibility ("default")))
35+
#endif
36+
#endif
37+
3038
typedef enum cvResult
3139
{
3240
CV_ERROR_FAIL = -1, //!< Some error occurred (TODO Require to fill exception information)

modules/core/include/opencv2/core/parallel/parallel_backend.hpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,33 @@ namespace cv { namespace parallel {
1919
*
2020
* Applications can replace OpenCV `parallel_for()` backend with own implementation (to reuse Application's thread pool).
2121
*
22-
* @note This call is not thread-safe. Consider calling this function from the `main()` before any other OpenCV processing functions (and without any other created threads).
2322
*
24-
* #### Intel TBB usage example:
23+
* ### Backend API usage examples
24+
*
25+
* #### Intel TBB
2526
*
2627
* - include header with simple implementation of TBB backend:
2728
* @snippet parallel_backend/example-tbb.cpp tbb_include
2829
* - execute backend replacement code:
2930
* @snippet parallel_backend/example-tbb.cpp tbb_backend
3031
* - configuration of compiler/linker options is responsibility of Application's scripts
3132
*
32-
* #### OpenMP usage example:
33+
* #### OpenMP
3334
*
3435
* - include header with simple implementation of OpenMP backend:
3536
* @snippet parallel_backend/example-openmp.cpp openmp_include
3637
* - execute backend replacement code:
3738
* @snippet parallel_backend/example-openmp.cpp openmp_backend
3839
* - Configuration of compiler/linker options is responsibility of Application's scripts
40+
*
41+
*
42+
* ### Plugins support
43+
*
44+
* Runtime configuration options:
45+
* - change backend priority: `OPENCV_PARALLEL_PRIORITY_<backend>=9999`
46+
* - disable backend: `OPENCV_PARALLEL_PRIORITY_<backend>=0`
47+
* - specify list of backends with high priority (>100000): `OPENCV_PARALLEL_PRIORITY_LIST=TBB,OPENMP`. Unknown backends are registered as new plugins.
48+
*
3949
*/
4050

4151
/** Interface for parallel_for backends implementations
@@ -68,6 +78,12 @@ class CV_EXPORTS ParallelForAPI
6878
*/
6979
CV_EXPORTS void setParallelForBackend(const std::shared_ptr<ParallelForAPI>& api, bool propagateNumThreads = true);
7080

81+
/** @brief Change OpenCV parallel_for backend
82+
*
83+
* @note This call is not thread-safe. Consider calling this function from the `main()` before any other OpenCV processing functions (and without any other created threads).
84+
*/
85+
CV_EXPORTS_W bool setParallelForBackend(const std::string& backendName, bool propagateNumThreads = true);
86+
7187
//! @}
7288
}} // namespace
7389
#endif // OPENCV_CORE_PARALLEL_BACKEND_HPP

0 commit comments

Comments
 (0)