// 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. #include "../precomp.hpp" #include "parallel.hpp" #include #include #ifdef NDEBUG #define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1 #else #define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1 #endif #include #include "registry_parallel.hpp" #include "registry_parallel.impl.hpp" #include "plugin_parallel_api.hpp" #include "plugin_parallel_wrapper.impl.hpp" namespace cv { namespace parallel { int numThreads = -1; ParallelForAPI::~ParallelForAPI() { // nothing } static std::string& getParallelBackendName() { static std::string g_backendName = toUpperCase(cv::utils::getConfigurationParameterString("OPENCV_PARALLEL_BACKEND", "")); return g_backendName; } static bool g_initializedParallelForAPI = false; static std::shared_ptr createParallelForAPI() { const std::string& name = getParallelBackendName(); bool isKnown = false; const auto& backends = getParallelBackendsInfo(); if (!name.empty()) { CV_LOG_INFO(NULL, "core(parallel): requested backend name: " << name); } for (size_t i = 0; i < backends.size(); i++) { const auto& info = backends[i]; if (!name.empty()) { if (name != info.name) { continue; } isKnown = true; } try { CV_LOG_DEBUG(NULL, "core(parallel): trying backend: " << info.name << " (priority=" << info.priority << ")"); CV_Assert(info.backendFactory); std::shared_ptr backend = info.backendFactory->create(); if (!backend) { CV_LOG_VERBOSE(NULL, 0, "core(parallel): not available: " << info.name); continue; } CV_LOG_INFO(NULL, "core(parallel): using backend: " << info.name << " (priority=" << info.priority << ")"); g_initializedParallelForAPI = true; getParallelBackendName() = info.name; return backend; } catch (const std::exception& e) { CV_LOG_WARNING(NULL, "core(parallel): can't initialize " << info.name << " backend: " << e.what()); } catch (...) { CV_LOG_WARNING(NULL, "core(parallel): can't initialize " << info.name << " backend: Unknown C++ exception"); } } if (name.empty()) { CV_LOG_DEBUG(NULL, "core(parallel): fallback on builtin code"); } else { if (!isKnown) CV_LOG_INFO(NULL, "core(parallel): unknown backend: " << name); } g_initializedParallelForAPI = true; return std::shared_ptr(); } static inline std::shared_ptr createDefaultParallelForAPI() { CV_LOG_DEBUG(NULL, "core(parallel): Initializing parallel backend..."); return createParallelForAPI(); } std::shared_ptr& getCurrentParallelForAPI() { static std::shared_ptr g_currentParallelForAPI = createDefaultParallelForAPI(); return g_currentParallelForAPI; } void setParallelForBackend(const std::shared_ptr& api, bool propagateNumThreads) { getCurrentParallelForAPI() = api; if (propagateNumThreads && api) { setNumThreads(numThreads); } } bool setParallelForBackend(const std::string& backendName, bool propagateNumThreads) { CV_TRACE_FUNCTION(); std::string backendName_u = toUpperCase(backendName); if (g_initializedParallelForAPI) { // ... already initialized if (getParallelBackendName() == backendName_u) { CV_LOG_INFO(NULL, "core(parallel): backend is already activated: " << (backendName.empty() ? "builtin(legacy)" : backendName)); return true; } else { // ... re-create new CV_LOG_DEBUG(NULL, "core(parallel): replacing parallel backend..."); getParallelBackendName() = backendName_u; getCurrentParallelForAPI() = createParallelForAPI(); } } else { // ... no backend exists, just specify the name (initialization is triggered by getCurrentParallelForAPI() call) getParallelBackendName() = backendName_u; } std::shared_ptr api = getCurrentParallelForAPI(); if (!api) { if (!backendName.empty()) { CV_LOG_WARNING(NULL, "core(parallel): backend is not available: " << backendName << " (using builtin legacy code)"); return false; } else { CV_LOG_WARNING(NULL, "core(parallel): switched to builtin code (legacy)"); } } if (!backendName_u.empty()) { CV_Assert(backendName_u == getParallelBackendName()); // data race? } if (propagateNumThreads) { setNumThreads(numThreads); } return true; } }} // namespace