1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #29542 from intel-staging:ipp/enable_instrumentation_fix

Implemented a check to enable instrumentation for IPP HAL #29542

To enable instrumentation for IPP HAL correctly it needed to generalize a part of `private.hpp` and put it to the separate file that can be included in `private.hpp` and `ipp_utils.hpp` both to avoid duplication.

Built with `-DENABLE_INSTRUMENTATION=ON` and ran `opencv_perf_imgproc --perf_instrument=1`:

  | Test | IPP weight before | IPP weight after |
  |---|---|---|
  | `distanceTransform` (8U->32F) | 0.0% | ~76% |
  | `ippSobel` | 0.0% | ~98% |
  | `scharrViaSobelFilter` | 0.0% | ~90% |

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Andrei Fedorov
2026-07-26 14:01:24 +02:00
committed by GitHub
parent 19ef7e6e16
commit 664f59e750
4 changed files with 113 additions and 55 deletions
+7
View File
@@ -46,6 +46,13 @@ if(WITH_IPP_CALLS_ENFORCED)
message("WITH_IPP_CALLS_ENFORCED=${WITH_IPP_CALLS_ENFORCED}: enforced IPP calls are enabled in IPP HAL")
endif()
# Enable cv::instr tracing of IPP calls inside the HAL so they show up in the
# instrumentation trace / IPP weight. Reuses the engine exported from
# opencv_core (symbols resolved at link time as ipphal is archived into core).
if(ENABLE_INSTRUMENTATION)
target_compile_definitions(ipphal PRIVATE ENABLE_INSTRUMENTATION)
endif()
target_include_directories(ipphal PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
ocv_warnings_disable(CMAKE_CXX_FLAGS -Wno-suggest-override)
+16
View File
@@ -1,6 +1,7 @@
// 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
// Copyright (C) 2026, Intel Corporation, all rights reserved.
#ifndef __IPP_HAL_UTILS_HPP__
#define __IPP_HAL_UTILS_HPP__
@@ -23,7 +24,22 @@
# include "ipp.h"
#endif
// IPP call instrumentation for the standalone IPP HAL.
//
// The HAL is built as a separate static library that does not include the
// internal core/private.hpp, so by default its IPP calls never appear in the
// cv::instr trace (reported IPP weight = 0%). When the parent build enables
// ENABLE_INSTRUMENTATION, the shared instrumentation.private.hpp provides the
// exact same CV_INSTRUMENT_FUN_IPP macro used by core (backed by symbols exported
// from libopencv_core, resolved at link time), so HAL IPP calls are traced
// identically to in-module ones. Otherwise the no-op passthrough is used.
#if !defined(CV_INSTRUMENT_FUN_IPP)
#if defined(ENABLE_INSTRUMENTATION)
#include "opencv2/core/utils/instrumentation.private.hpp"
#else
#define CV_INSTRUMENT_FUN_IPP(FUN, ...) ((FUN)(__VA_ARGS__))
#endif // defined(ENABLE_INSTRUMENTATION)
#endif // !defined(CV_INSTRUMENT_FUN_IPP)
#define CV_HAL_CHECK_USE_IPP() if(!cv::ipp::useIPP()) return CV_HAL_ERROR_NOT_IMPLEMENTED;
+2 -55
View File
@@ -690,23 +690,13 @@ public:
TLSData<InstrTLSStruct> tlsStruct;
};
class CV_EXPORTS IntrumentationRegion
{
public:
IntrumentationRegion(const char* funName, const char* fileName, int lineNum, void *retAddress, bool alwaysExpand, TYPE instrType = TYPE_GENERAL, IMPL implType = IMPL_PLAIN);
~IntrumentationRegion();
private:
bool m_disabled; // region status
uint64 m_regionTicks;
};
CV_EXPORTS InstrStruct& getInstrumentStruct();
InstrTLSStruct& getInstrumentTLSStruct();
CV_EXPORTS InstrNode* getCurrentNode();
}
}
#include "opencv2/core/utils/instrumentation.private.hpp"
#ifdef _WIN32
#define CV_INSTRUMENT_GET_RETURN_ADDRESS _ReturnAddress()
#else
@@ -718,45 +708,6 @@ CV_EXPORTS InstrNode* getCurrentNode();
#define CV_INSTRUMENT_REGION_CUSTOM_META(NAME, ALWAYS_EXPAND, TYPE, IMPL)\
void *CVAUX_CONCAT(__curr_address__, __LINE__) = [&]() {return CV_INSTRUMENT_GET_RETURN_ADDRESS;}();\
::cv::instr::IntrumentationRegion CVAUX_CONCAT(__instr_region__, __LINE__) (NAME, __FILE__, __LINE__, CVAUX_CONCAT(__curr_address__, __LINE__), false, ::cv::instr::TYPE_GENERAL, ::cv::instr::IMPL_PLAIN);
// Instrument functions with non-void return type
#define CV_INSTRUMENT_FUN_RT_META(TYPE, IMPL, ERROR_COND, FUN, ...) ([&]()\
{\
if(::cv::instr::useInstrumentation()){\
::cv::instr::IntrumentationRegion __instr__(#FUN, __FILE__, __LINE__, NULL, false, TYPE, IMPL);\
try{\
auto instrStatus = ((FUN)(__VA_ARGS__));\
if(ERROR_COND){\
::cv::instr::getCurrentNode()->m_payload.m_funError = true;\
CV_INSTRUMENT_MARK_META(IMPL, #FUN " - BadExit");\
}\
return instrStatus;\
}catch(...){\
::cv::instr::getCurrentNode()->m_payload.m_funError = true;\
CV_INSTRUMENT_MARK_META(IMPL, #FUN " - BadExit");\
throw;\
}\
}else{\
return ((FUN)(__VA_ARGS__));\
}\
}())
// Instrument functions with void return type
#define CV_INSTRUMENT_FUN_RV_META(TYPE, IMPL, FUN, ...) ([&]()\
{\
if(::cv::instr::useInstrumentation()){\
::cv::instr::IntrumentationRegion __instr__(#FUN, __FILE__, __LINE__, NULL, false, TYPE, IMPL);\
try{\
(FUN)(__VA_ARGS__);\
}catch(...){\
::cv::instr::getCurrentNode()->m_payload.m_funError = true;\
CV_INSTRUMENT_MARK_META(IMPL, #FUN "- BadExit");\
throw;\
}\
}else{\
(FUN)(__VA_ARGS__);\
}\
}())
// Instrumentation information marker
#define CV_INSTRUMENT_MARK_META(IMPL, NAME, ...) {::cv::instr::IntrumentationRegion __instr_mark__(NAME, __FILE__, __LINE__, NULL, false, ::cv::instr::TYPE_MARKER, IMPL);}
///// General instrumentation
// General OpenCV region instrumentation macro
@@ -769,10 +720,6 @@ CV_EXPORTS InstrNode* getCurrentNode();
///// IPP instrumentation
// Wrapper region instrumentation macro
#define CV_INSTRUMENT_REGION_IPP(); CV_INSTRUMENT_REGION_META(__FUNCTION__, false, ::cv::instr::TYPE_WRAPPER, ::cv::instr::IMPL_IPP)
// Function instrumentation macro
#define CV_INSTRUMENT_FUN_IPP(FUN, ...) CV_INSTRUMENT_FUN_RT_META(::cv::instr::TYPE_FUN, ::cv::instr::IMPL_IPP, instrStatus < 0, FUN, __VA_ARGS__)
// Diagnostic markers
#define CV_INSTRUMENT_MARK_IPP(NAME) CV_INSTRUMENT_MARK_META(::cv::instr::IMPL_IPP, NAME)
///// OpenCL instrumentation
// Wrapper region instrumentation macro
@@ -0,0 +1,88 @@
// 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.
// Copyright (C) 2026, Intel Corporation, all rights reserved.
#ifndef OPENCV_CORE_UTILS_INSTRUMENTATION_PRIVATE_HPP
#define OPENCV_CORE_UTILS_INSTRUMENTATION_PRIVATE_HPP
#include "opencv2/core/utils/instrumentation.hpp"
// Region-based function-instrumentation primitives.
//
// Only meaningful when the build was configured with ENABLE_INSTRUMENTATION;
// otherwise this header contributes nothing and each includer provides its own
// no-op fallbacks. The IntrumentationRegion / getCurrentNode() definitions are
// compiled into and exported (CV_EXPORTS) from the core library, so the HAL only
// needs these declarations and resolves the symbols at link time.
#ifdef ENABLE_INSTRUMENTATION
namespace cv { namespace instr {
// Scoped region: records one instrumentation node on construction and closes it
// on destruction. Defined in modules/core/src/system.cpp.
class CV_EXPORTS IntrumentationRegion
{
public:
IntrumentationRegion(const char* funName, const char* fileName, int lineNum, void *retAddress,
bool alwaysExpand, TYPE instrType = TYPE_GENERAL, IMPL implType = IMPL_PLAIN);
~IntrumentationRegion();
private:
bool m_disabled; // region status
uint64 m_regionTicks;
};
CV_EXPORTS InstrNode* getCurrentNode();
}} // namespace cv::instr
// Instrumentation information marker
#define CV_INSTRUMENT_MARK_META(IMPL, NAME, ...) {::cv::instr::IntrumentationRegion __instr_mark__(NAME, __FILE__, __LINE__, NULL, false, ::cv::instr::TYPE_MARKER, IMPL);}
// Instrument functions with non-void return type
#define CV_INSTRUMENT_FUN_RT_META(TYPE, IMPL, ERROR_COND, FUN, ...) ([&]() \
{ \
if(::cv::instr::useInstrumentation()){ \
::cv::instr::IntrumentationRegion __instr__(#FUN, __FILE__, __LINE__, NULL, false, TYPE, IMPL); \
try{ \
auto instrStatus = ((FUN)(__VA_ARGS__)); \
if(ERROR_COND){ \
::cv::instr::getCurrentNode()->m_payload.m_funError = true; \
CV_INSTRUMENT_MARK_META(IMPL, #FUN " - BadExit"); \
} \
return instrStatus; \
}catch(...){ \
::cv::instr::getCurrentNode()->m_payload.m_funError = true; \
CV_INSTRUMENT_MARK_META(IMPL, #FUN " - BadExit"); \
throw; \
} \
}else{ \
return ((FUN)(__VA_ARGS__)); \
} \
}())
// Instrument functions with void return type
#define CV_INSTRUMENT_FUN_RV_META(TYPE, IMPL, FUN, ...) ([&]() \
{ \
if(::cv::instr::useInstrumentation()){ \
::cv::instr::IntrumentationRegion __instr__(#FUN, __FILE__, __LINE__, NULL, false, TYPE, IMPL); \
try{ \
(FUN)(__VA_ARGS__); \
}catch(...){ \
::cv::instr::getCurrentNode()->m_payload.m_funError = true; \
CV_INSTRUMENT_MARK_META(IMPL, #FUN " - BadExit"); \
throw; \
} \
}else{ \
(FUN)(__VA_ARGS__); \
} \
}())
// IPP function instrumentation macros
#define CV_INSTRUMENT_FUN_IPP(FUN, ...) CV_INSTRUMENT_FUN_RT_META(::cv::instr::TYPE_FUN, ::cv::instr::IMPL_IPP, instrStatus < 0, FUN, __VA_ARGS__)
#define CV_INSTRUMENT_MARK_IPP(NAME) CV_INSTRUMENT_MARK_META(::cv::instr::IMPL_IPP, NAME)
#endif // ENABLE_INSTRUMENTATION
#endif // OPENCV_CORE_UTILS_INSTRUMENTATION_PRIVATE_HPP