mirror of https://github.com/opencv/opencv.git
parent
07aff8e85f
commit
006966e629
58 changed files with 2953 additions and 175 deletions
@ -0,0 +1,13 @@ |
|||||||
|
if(WITH_ITT) |
||||||
|
if(BUILD_ITT) |
||||||
|
add_subdirectory("${OpenCV_SOURCE_DIR}/3rdparty/ittnotify") |
||||||
|
set(ITT_INCLUDE_DIR "${OpenCV_SOURCE_DIR}/3rdparty/ittnotify/include") |
||||||
|
set(ITT_INCLUDE_DIRS "${ITT_INCLUDE_DIR}") |
||||||
|
set(ITT_LIBRARIES "ittnotify") |
||||||
|
set(HAVE_ITT 1) |
||||||
|
else() |
||||||
|
#TODO |
||||||
|
endif() |
||||||
|
endif() |
||||||
|
|
||||||
|
set(OPENCV_TRACE 1) |
@ -0,0 +1,84 @@ |
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef OPENCV_LOGGING_HPP |
||||||
|
#define OPENCV_LOGGING_HPP |
||||||
|
|
||||||
|
#include <iostream> |
||||||
|
#include <sstream> |
||||||
|
#include <limits.h> // INT_MAX |
||||||
|
|
||||||
|
// TODO This file contains just interface part with implementation stubs.
|
||||||
|
|
||||||
|
//! @addtogroup core_logging
|
||||||
|
// This section describes OpenCV logging utilities.
|
||||||
|
//
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace utils { |
||||||
|
namespace logging { |
||||||
|
|
||||||
|
// Supported logging levels and their semantic
|
||||||
|
#define CV_LOG_LEVEL_SILENT 0 //!< for using in setLogVevel() call
|
||||||
|
#define CV_LOG_LEVEL_FATAL 1 //!< Fatal (critical) error (unrecoverable internal error)
|
||||||
|
#define CV_LOG_LEVEL_ERROR 2 //!< Error message
|
||||||
|
#define CV_LOG_LEVEL_WARN 3 //!< Warning message
|
||||||
|
#define CV_LOG_LEVEL_INFO 4 //!< Info message
|
||||||
|
#define CV_LOG_LEVEL_DEBUG 5 //!< Debug message. Disabled in the "Release" build.
|
||||||
|
#define CV_LOG_LEVEL_VERBOSE 6 //!< Verbose (trace) messages. Requires verbosity level. Disabled in the "Release" build.
|
||||||
|
|
||||||
|
//! Supported logging levels and their semantic
|
||||||
|
enum LogLevel { |
||||||
|
LOG_LEVEL_SILENT = 0, //!< for using in setLogVevel() call
|
||||||
|
LOG_LEVEL_FATAL = 1, //!< Fatal (critical) error (unrecoverable internal error)
|
||||||
|
LOG_LEVEL_ERROR = 2, //!< Error message
|
||||||
|
LOG_LEVEL_WARNING = 3, //!< Warning message
|
||||||
|
LOG_LEVEL_INFO = 4, //!< Info message
|
||||||
|
LOG_LEVEL_DEBUG = 5, //!< Debug message. Disabled in the "Release" build.
|
||||||
|
LOG_LEVEL_VERBOSE = 6, //!< Verbose (trace) messages. Requires verbosity level. Disabled in the "Release" build.
|
||||||
|
#ifndef CV_DOXYGEN |
||||||
|
ENUM_LOG_LEVEL_FORCE_INT = INT_MAX |
||||||
|
#endif |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \def CV_LOG_STRIP_LEVEL |
||||||
|
* |
||||||
|
* Define CV_LOG_STRIP_LEVEL=CV_LOG_LEVEL_[DEBUG|INFO|WARN|ERROR|FATAL|DISABLED] to compile out anything at that and before that logging level |
||||||
|
*/ |
||||||
|
#ifndef CV_LOG_STRIP_LEVEL |
||||||
|
# if defined NDEBUG |
||||||
|
# define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG |
||||||
|
# else |
||||||
|
# define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE |
||||||
|
# endif |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
#define CV_LOG_FATAL(tag, ...) for(;;) { std::stringstream ss; ss << "[FATAL:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cerr << ss.str(); break; } |
||||||
|
#define CV_LOG_ERROR(tag, ...) for(;;) { std::stringstream ss; ss << "[ERROR:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cerr << ss.str(); break; } |
||||||
|
#define CV_LOG_WARNING(tag, ...) for(;;) { std::stringstream ss; ss << "[ WARN:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str(); break; } |
||||||
|
#if CV_LOG_STRIP_LEVEL <= CV_LOG_LEVEL_INFO |
||||||
|
#define CV_LOG_INFO(tag, ...) |
||||||
|
#else |
||||||
|
#define CV_LOG_INFO(tag, ...) for(;;) { std::stringstream ss; ss << "[ INFO:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str(); break; } |
||||||
|
#endif |
||||||
|
#if CV_LOG_STRIP_LEVEL <= CV_LOG_LEVEL_DEBUG |
||||||
|
#define CV_LOG_DEBUG(tag, ...) |
||||||
|
#else |
||||||
|
#define CV_LOG_DEBUG(tag, ...) for(;;) { std::stringstream ss; ss << "[DEBUG:" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str(); break; } |
||||||
|
#endif |
||||||
|
#if CV_LOG_STRIP_LEVEL <= CV_LOG_LEVEL_VERBOSE |
||||||
|
#define CV_LOG_VERBOSE(tag, v, ...) |
||||||
|
#else |
||||||
|
#define CV_LOG_VERBOSE(tag, v, ...) for(;;) { std::stringstream ss; ss << "[VERB" << v << ":" << cv::utils::getThreadID() << "] " << __VA_ARGS__ << std::endl; std::cout << ss.str(); break; } |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
}} // namespace
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // OPENCV_LOGGING_HPP
|
@ -0,0 +1,250 @@ |
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef OPENCV_TRACE_HPP |
||||||
|
#define OPENCV_TRACE_HPP |
||||||
|
|
||||||
|
#include <opencv2/core/cvdef.h> |
||||||
|
|
||||||
|
//! @addtogroup core_logging
|
||||||
|
// This section describes OpenCV tracing utilities.
|
||||||
|
//
|
||||||
|
//! @{
|
||||||
|
|
||||||
|
namespace cv { |
||||||
|
namespace utils { |
||||||
|
namespace trace { |
||||||
|
|
||||||
|
//! Macro to trace function
|
||||||
|
#define CV_TRACE_FUNCTION() |
||||||
|
|
||||||
|
#define CV_TRACE_FUNCTION_SKIP_NESTED() |
||||||
|
|
||||||
|
//! Trace code scope.
|
||||||
|
//! @note Dynamic names are not supported in this macro (on stack or heap). Use string literals here only, like "initialize".
|
||||||
|
#define CV_TRACE_REGION(name_as_static_string_literal) |
||||||
|
//! mark completed of the current opened region and create new one
|
||||||
|
//! @note Dynamic names are not supported in this macro (on stack or heap). Use string literals here only, like "step1".
|
||||||
|
#define CV_TRACE_REGION_NEXT(name_as_static_string_literal) |
||||||
|
|
||||||
|
//! Macro to trace argument value
|
||||||
|
#define CV_TRACE_ARG(arg_id) |
||||||
|
|
||||||
|
//! Macro to trace argument value (expanded version)
|
||||||
|
#define CV_TRACE_ARG_VALUE(arg_id, arg_name, value) |
||||||
|
|
||||||
|
//! @cond IGNORED
|
||||||
|
#define CV_TRACE_NS cv::utils::trace |
||||||
|
|
||||||
|
namespace details { |
||||||
|
|
||||||
|
#ifndef __OPENCV_TRACE |
||||||
|
# if defined __OPENCV_BUILD && !defined __OPENCV_TESTS && !defined __OPENCV_APPS |
||||||
|
# define __OPENCV_TRACE 1 |
||||||
|
# else |
||||||
|
# define __OPENCV_TRACE 0 |
||||||
|
# endif |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef CV_TRACE_FILENAME |
||||||
|
# define CV_TRACE_FILENAME __FILE__ |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef CV__TRACE_FUNCTION |
||||||
|
# if defined _MSC_VER |
||||||
|
# define CV__TRACE_FUNCTION __FUNCSIG__ |
||||||
|
# elif defined __GNUC__ |
||||||
|
# define CV__TRACE_FUNCTION __PRETTY_FUNCTION__ |
||||||
|
# else |
||||||
|
# define CV__TRACE_FUNCTION "<unknown>" |
||||||
|
# endif |
||||||
|
#endif |
||||||
|
|
||||||
|
//! Thread-local instance (usually allocated on stack)
|
||||||
|
class CV_EXPORTS Region |
||||||
|
{ |
||||||
|
public: |
||||||
|
struct LocationExtraData; |
||||||
|
struct LocationStaticStorage |
||||||
|
{ |
||||||
|
LocationExtraData** ppExtra; //< implementation specific data
|
||||||
|
const char* name; //< region name (function name or other custom name)
|
||||||
|
const char* filename; //< source code filename
|
||||||
|
int line; //< source code line
|
||||||
|
int flags; //< flags (implementation code path: Plain, IPP, OpenCL)
|
||||||
|
}; |
||||||
|
|
||||||
|
Region(const LocationStaticStorage& location); |
||||||
|
inline ~Region() |
||||||
|
{ |
||||||
|
if (implFlags != 0) |
||||||
|
destroy(); |
||||||
|
CV_DbgAssert(implFlags == 0); |
||||||
|
CV_DbgAssert(pImpl == NULL); |
||||||
|
} |
||||||
|
|
||||||
|
class Impl; |
||||||
|
Impl* pImpl; // NULL if current region is not active
|
||||||
|
int implFlags; // see RegionFlag, 0 if region is ignored
|
||||||
|
|
||||||
|
bool isActive() const { return pImpl != NULL; } |
||||||
|
|
||||||
|
void destroy(); |
||||||
|
private: |
||||||
|
Region(const Region&); // disabled
|
||||||
|
Region& operator= (const Region&); // disabled
|
||||||
|
}; |
||||||
|
|
||||||
|
//! Specify region flags
|
||||||
|
enum RegionLocationFlag { |
||||||
|
REGION_FLAG_FUNCTION = (1 << 0), //< region is function (=1) / nested named region (=0)
|
||||||
|
REGION_FLAG_APP_CODE = (1 << 1), //< region is Application code (=1) / OpenCV library code (=0)
|
||||||
|
REGION_FLAG_SKIP_NESTED = (1 << 2), //< avoid processing of nested regions
|
||||||
|
|
||||||
|
REGION_FLAG_IMPL_IPP = (1 << 16), //< region is part of IPP code path
|
||||||
|
REGION_FLAG_IMPL_OPENCL = (2 << 16), //< region is part of OpenCL code path
|
||||||
|
REGION_FLAG_IMPL_OPENVX = (3 << 16), //< region is part of OpenVX code path
|
||||||
|
|
||||||
|
REGION_FLAG_IMPL_MASK = (15 << 16), |
||||||
|
|
||||||
|
REGION_FLAG_REGION_FORCE = (1 << 30), |
||||||
|
REGION_FLAG_REGION_NEXT = (1 << 31), //< close previous region (see #CV_TRACE_REGION_NEXT macro)
|
||||||
|
|
||||||
|
ENUM_REGION_FLAG_FORCE_INT = INT_MAX |
||||||
|
}; |
||||||
|
|
||||||
|
struct CV_EXPORTS TraceArg { |
||||||
|
public: |
||||||
|
struct ExtraData; |
||||||
|
ExtraData** ppExtra; |
||||||
|
const char* name; |
||||||
|
int flags; |
||||||
|
}; |
||||||
|
/** @brief Add meta information to current region (function)
|
||||||
|
* See CV_TRACE_ARG macro |
||||||
|
* @param arg argument information structure (global static cache) |
||||||
|
* @param value argument value (can by dynamic string literal in case of string, static allocation is not required) |
||||||
|
*/ |
||||||
|
CV_EXPORTS void traceArg(const TraceArg& arg, const char* value); |
||||||
|
//! @overload
|
||||||
|
CV_EXPORTS void traceArg(const TraceArg& arg, int value); |
||||||
|
//! @overload
|
||||||
|
CV_EXPORTS void traceArg(const TraceArg& arg, int64 value); |
||||||
|
//! @overload
|
||||||
|
CV_EXPORTS void traceArg(const TraceArg& arg, double value); |
||||||
|
|
||||||
|
#define CV__TRACE_LOCATION_VARNAME(loc_id) CVAUX_CONCAT(CVAUX_CONCAT(__cv_trace_location_, loc_id), __LINE__) |
||||||
|
#define CV__TRACE_LOCATION_EXTRA_VARNAME(loc_id) CVAUX_CONCAT(CVAUX_CONCAT(__cv_trace_location_extra_, loc_id) , __LINE__) |
||||||
|
|
||||||
|
#define CV__TRACE_DEFINE_LOCATION_(loc_id, name, flags) \ |
||||||
|
static CV_TRACE_NS::details::Region::LocationExtraData* CV__TRACE_LOCATION_EXTRA_VARNAME(loc_id) = 0; \
|
||||||
|
static const CV_TRACE_NS::details::Region::LocationStaticStorage \
|
||||||
|
CV__TRACE_LOCATION_VARNAME(loc_id) = { &(CV__TRACE_LOCATION_EXTRA_VARNAME(loc_id)), name, CV_TRACE_FILENAME, __LINE__, flags}; |
||||||
|
|
||||||
|
#define CV__TRACE_DEFINE_LOCATION_FN(name, flags) CV__TRACE_DEFINE_LOCATION_(fn, name, (flags | CV_TRACE_NS::details::REGION_FLAG_FUNCTION)) |
||||||
|
|
||||||
|
|
||||||
|
#define CV__TRACE_OPENCV_FUNCTION() \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, 0); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
#define CV__TRACE_OPENCV_FUNCTION_NAME(name) \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(name, 0); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
#define CV__TRACE_APP_FUNCTION() \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, CV_TRACE_NS::details::REGION_FLAG_APP_CODE); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
#define CV__TRACE_APP_FUNCTION_NAME(name) \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(name, CV_TRACE_NS::details::REGION_FLAG_APP_CODE); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
|
||||||
|
#define CV__TRACE_OPENCV_FUNCTION_SKIP_NESTED() \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, CV_TRACE_NS::details::REGION_FLAG_SKIP_NESTED); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
#define CV__TRACE_OPENCV_FUNCTION_NAME_SKIP_NESTED(name) \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(name, CV_TRACE_NS::details::REGION_FLAG_SKIP_NESTED); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
#define CV__TRACE_APP_FUNCTION_SKIP_NESTED() \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(CV__TRACE_FUNCTION, CV_TRACE_NS::details::REGION_FLAG_SKIP_NESTED | CV_TRACE_NS::details::REGION_FLAG_APP_CODE); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
|
||||||
|
#define CV__TRACE_REGION_(name_as_static_string_literal, flags) \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_(region, name_as_static_string_literal, flags); \
|
||||||
|
CV_TRACE_NS::details::Region CVAUX_CONCAT(__region_, __LINE__)(CV__TRACE_LOCATION_VARNAME(region)); |
||||||
|
|
||||||
|
#define CV__TRACE_REGION(name_as_static_string_literal) CV__TRACE_REGION_(name_as_static_string_literal, 0) |
||||||
|
#define CV__TRACE_REGION_NEXT(name_as_static_string_literal) CV__TRACE_REGION_(name_as_static_string_literal, CV_TRACE_NS::details::REGION_FLAG_REGION_NEXT) |
||||||
|
|
||||||
|
#define CV__TRACE_ARG_VARNAME(arg_id) CVAUX_CONCAT(__cv_trace_arg_ ## arg_id, __LINE__) |
||||||
|
#define CV__TRACE_ARG_EXTRA_VARNAME(arg_id) CVAUX_CONCAT(__cv_trace_arg_extra_ ## arg_id, __LINE__) |
||||||
|
|
||||||
|
#define CV__TRACE_DEFINE_ARG_(arg_id, name, flags) \ |
||||||
|
static CV_TRACE_NS::details::TraceArg::ExtraData* CV__TRACE_ARG_EXTRA_VARNAME(arg_id) = 0; \
|
||||||
|
static const CV_TRACE_NS::details::TraceArg \
|
||||||
|
CV__TRACE_ARG_VARNAME(arg_id) = { &(CV__TRACE_ARG_EXTRA_VARNAME(arg_id)), name, flags }; |
||||||
|
|
||||||
|
#define CV__TRACE_ARG_VALUE(arg_id, arg_name, value) \ |
||||||
|
CV__TRACE_DEFINE_ARG_(arg_id, arg_name, 0); \
|
||||||
|
CV_TRACE_NS::details::traceArg((CV__TRACE_ARG_VARNAME(arg_id)), value); |
||||||
|
|
||||||
|
#define CV__TRACE_ARG(arg_id) CV_TRACE_ARG_VALUE(arg_id, #arg_id, (arg_id)) |
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#ifndef OPENCV_DISABLE_TRACE |
||||||
|
#undef CV_TRACE_FUNCTION |
||||||
|
#undef CV_TRACE_FUNCTION_SKIP_NESTED |
||||||
|
#if __OPENCV_TRACE |
||||||
|
#define CV_TRACE_FUNCTION CV__TRACE_OPENCV_FUNCTION |
||||||
|
#define CV_TRACE_FUNCTION_SKIP_NESTED CV__TRACE_OPENCV_FUNCTION_SKIP_NESTED |
||||||
|
#else |
||||||
|
#define CV_TRACE_FUNCTION CV__TRACE_APP_FUNCTION |
||||||
|
#define CV_TRACE_FUNCTION_SKIP_NESTED CV__TRACE_APP_FUNCTION_SKIP_NESTED |
||||||
|
#endif |
||||||
|
|
||||||
|
#undef CV_TRACE_REGION |
||||||
|
#define CV_TRACE_REGION CV__TRACE_REGION |
||||||
|
|
||||||
|
#undef CV_TRACE_REGION_NEXT |
||||||
|
#define CV_TRACE_REGION_NEXT CV__TRACE_REGION_NEXT |
||||||
|
|
||||||
|
#undef CV_TRACE_ARG_VALUE |
||||||
|
#define CV_TRACE_ARG_VALUE(arg_id, arg_name, value) \ |
||||||
|
if (__region_fn.isActive()) \
|
||||||
|
{ \
|
||||||
|
CV__TRACE_ARG_VALUE(arg_id, arg_name, value); \
|
||||||
|
} |
||||||
|
|
||||||
|
#undef CV_TRACE_ARG |
||||||
|
#define CV_TRACE_ARG CV__TRACE_ARG |
||||||
|
|
||||||
|
#endif // OPENCV_DISABLE_TRACE
|
||||||
|
|
||||||
|
#ifdef OPENCV_TRACE_VERBOSE |
||||||
|
#define CV_TRACE_FUNCTION_VERBOSE CV_TRACE_FUNCTION |
||||||
|
#define CV_TRACE_REGION_VERBOSE CV_TRACE_REGION |
||||||
|
#define CV_TRACE_REGION_NEXT_VERBOSE CV_TRACE_REGION_NEXT |
||||||
|
#define CV_TRACE_ARG_VALUE_VERBOSE CV_TRACE_ARG_VALUE |
||||||
|
#define CV_TRACE_ARG_VERBOSE CV_TRACE_ARG |
||||||
|
#else |
||||||
|
#define CV_TRACE_FUNCTION_VERBOSE(...) |
||||||
|
#define CV_TRACE_REGION_VERBOSE(...) |
||||||
|
#define CV_TRACE_REGION_NEXT_VERBOSE(...) |
||||||
|
#define CV_TRACE_ARG_VALUE_VERBOSE(...) |
||||||
|
#define CV_TRACE_ARG_VERBOSE(...) |
||||||
|
#endif |
||||||
|
|
||||||
|
//! @endcond
|
||||||
|
|
||||||
|
}}} // namespace
|
||||||
|
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
#endif // OPENCV_TRACE_HPP
|
@ -0,0 +1,419 @@ |
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef OPENCV_TRACE_PRIVATE_HPP |
||||||
|
#define OPENCV_TRACE_PRIVATE_HPP |
||||||
|
|
||||||
|
#ifdef OPENCV_TRACE |
||||||
|
|
||||||
|
#include <opencv2/core/utils/logger.hpp> |
||||||
|
|
||||||
|
#include "trace.hpp" |
||||||
|
|
||||||
|
//! @cond IGNORED
|
||||||
|
|
||||||
|
#include <deque> |
||||||
|
#include <ostream> |
||||||
|
|
||||||
|
#define INTEL_ITTNOTIFY_API_PRIVATE 1 |
||||||
|
#ifdef OPENCV_WITH_ITT |
||||||
|
#include "ittnotify.h" |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef DEBUG_ONLY |
||||||
|
#ifdef _DEBUG |
||||||
|
#define DEBUG_ONLY(...) __VA_ARGS__ |
||||||
|
#else |
||||||
|
#define DEBUG_ONLY(...) (void)0 |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
|
||||||
|
#ifndef DEBUG_ONLY_ |
||||||
|
#ifdef _DEBUG |
||||||
|
#define DEBUG_ONLY_(...) __VA_ARGS__ |
||||||
|
#else |
||||||
|
#define DEBUG_ONLY_(...) |
||||||
|
#endif |
||||||
|
#endif |
||||||
|
|
||||||
|
|
||||||
|
namespace cv { |
||||||
|
namespace utils { |
||||||
|
namespace trace { |
||||||
|
namespace details { |
||||||
|
|
||||||
|
#define CV__TRACE_OPENCV_FUNCTION_NAME_(name, flags) \ |
||||||
|
CV__TRACE_DEFINE_LOCATION_FN(name, flags); \
|
||||||
|
const CV_TRACE_NS::details::Region __region_fn(CV__TRACE_LOCATION_VARNAME(fn)); |
||||||
|
|
||||||
|
|
||||||
|
enum RegionFlag { |
||||||
|
REGION_FLAG__NEED_STACK_POP = (1 << 0), |
||||||
|
REGION_FLAG__ACTIVE = (1 << 1), |
||||||
|
|
||||||
|
ENUM_REGION_FLAG_IMPL_FORCE_INT = INT_MAX |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
class TraceMessage; |
||||||
|
|
||||||
|
class TraceStorage { |
||||||
|
public: |
||||||
|
TraceStorage() {} |
||||||
|
virtual ~TraceStorage() {}; |
||||||
|
|
||||||
|
virtual bool put(const TraceMessage& msg) const = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
struct RegionStatistics |
||||||
|
{ |
||||||
|
int currentSkippedRegions; |
||||||
|
|
||||||
|
int64 duration; |
||||||
|
#ifdef HAVE_IPP |
||||||
|
int64 durationImplIPP; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
int64 durationImplOpenCL; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
int64 durationImplOpenVX; |
||||||
|
#endif |
||||||
|
|
||||||
|
RegionStatistics() : |
||||||
|
currentSkippedRegions(0), |
||||||
|
duration(0) |
||||||
|
#ifdef HAVE_IPP |
||||||
|
,durationImplIPP(0) |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
,durationImplOpenCL(0) |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
,durationImplOpenVX(0) |
||||||
|
#endif |
||||||
|
{} |
||||||
|
|
||||||
|
void grab(RegionStatistics& result) |
||||||
|
{ |
||||||
|
result.currentSkippedRegions = currentSkippedRegions; currentSkippedRegions = 0; |
||||||
|
result.duration = duration; duration = 0; |
||||||
|
#ifdef HAVE_IPP |
||||||
|
result.durationImplIPP = durationImplIPP; durationImplIPP = 0; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
result.durationImplOpenCL = durationImplOpenCL; durationImplOpenCL = 0; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
result.durationImplOpenVX = durationImplOpenVX; durationImplOpenVX = 0; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
void append(RegionStatistics& stat) |
||||||
|
{ |
||||||
|
currentSkippedRegions += stat.currentSkippedRegions; |
||||||
|
duration += stat.duration; |
||||||
|
#ifdef HAVE_IPP |
||||||
|
durationImplIPP += stat.durationImplIPP; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
durationImplOpenCL += stat.durationImplOpenCL; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
durationImplOpenVX += stat.durationImplOpenVX; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
void multiply(const float c) |
||||||
|
{ |
||||||
|
duration = (int64)(duration * c); |
||||||
|
#ifdef HAVE_IPP |
||||||
|
durationImplIPP = (int64)(durationImplIPP * c); |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
durationImplOpenCL = (int64)(durationImplOpenCL * c); |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
durationImplOpenVX = (int64)(durationImplOpenVX * c); |
||||||
|
#endif |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
static inline |
||||||
|
std::ostream& operator<<(std::ostream& out, const RegionStatistics& stat) |
||||||
|
{ |
||||||
|
out << "skip=" << stat.currentSkippedRegions |
||||||
|
<< " duration=" << stat.duration |
||||||
|
#ifdef HAVE_IPP |
||||||
|
<< " durationImplIPP=" << stat.durationImplIPP |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
<< " durationImplOpenCL=" << stat.durationImplOpenCL |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
<< " durationImplOpenVX=" << stat.durationImplOpenVX |
||||||
|
#endif |
||||||
|
; |
||||||
|
return out; |
||||||
|
} |
||||||
|
|
||||||
|
struct RegionStatisticsStatus |
||||||
|
{ |
||||||
|
int _skipDepth; |
||||||
|
#ifdef HAVE_IPP |
||||||
|
int ignoreDepthImplIPP; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
int ignoreDepthImplOpenCL; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
int ignoreDepthImplOpenVX; |
||||||
|
#endif |
||||||
|
|
||||||
|
RegionStatisticsStatus() { reset(); } |
||||||
|
|
||||||
|
void reset() |
||||||
|
{ |
||||||
|
_skipDepth = -1; |
||||||
|
#ifdef HAVE_IPP |
||||||
|
ignoreDepthImplIPP = 0; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
ignoreDepthImplOpenCL = 0; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
ignoreDepthImplOpenVX = 0; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
void propagateFrom(const RegionStatisticsStatus& src) |
||||||
|
{ |
||||||
|
_skipDepth = -1; |
||||||
|
if (src._skipDepth >= 0) |
||||||
|
enableSkipMode(0); |
||||||
|
#ifdef HAVE_IPP |
||||||
|
ignoreDepthImplIPP = src.ignoreDepthImplIPP ? 1 : 0; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
ignoreDepthImplOpenCL = src.ignoreDepthImplOpenCL ? 1 : 0; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
ignoreDepthImplOpenVX = src.ignoreDepthImplOpenVX ? 1 : 0; |
||||||
|
#endif |
||||||
|
} |
||||||
|
|
||||||
|
void enableSkipMode(int depth); |
||||||
|
void checkResetSkipMode(int leaveDepth); |
||||||
|
}; |
||||||
|
|
||||||
|
static inline |
||||||
|
std::ostream& operator<<(std::ostream& out, const RegionStatisticsStatus& s) |
||||||
|
{ |
||||||
|
out << "ignore={"; |
||||||
|
if (s._skipDepth >= 0) |
||||||
|
out << " SKIP=" << s._skipDepth; |
||||||
|
#ifdef HAVE_IPP |
||||||
|
if (s.ignoreDepthImplIPP) |
||||||
|
out << " IPP=" << s.ignoreDepthImplIPP; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENCL |
||||||
|
if (s.ignoreDepthImplOpenCL) |
||||||
|
out << " OpenCL=" << s.ignoreDepthImplOpenCL; |
||||||
|
#endif |
||||||
|
#ifdef HAVE_OPENVX |
||||||
|
if (s.ignoreDepthImplOpenVX) |
||||||
|
out << " OpenVX=" << s.ignoreDepthImplOpenVX; |
||||||
|
#endif |
||||||
|
out << "}"; |
||||||
|
return out; |
||||||
|
} |
||||||
|
|
||||||
|
//! TraceManager for local thread
|
||||||
|
struct TraceManagerThreadLocal |
||||||
|
{ |
||||||
|
const int threadID; |
||||||
|
int region_counter; |
||||||
|
|
||||||
|
size_t totalSkippedEvents; |
||||||
|
|
||||||
|
Region* currentActiveRegion; |
||||||
|
|
||||||
|
struct StackEntry |
||||||
|
{ |
||||||
|
Region* region; |
||||||
|
const Region::LocationStaticStorage* location; |
||||||
|
int64 beginTimestamp; |
||||||
|
StackEntry(Region* region_, const Region::LocationStaticStorage* location_, int64 beginTimestamp_) : |
||||||
|
region(region_), location(location_), beginTimestamp(beginTimestamp_) |
||||||
|
{} |
||||||
|
StackEntry() : region(NULL), location(NULL), beginTimestamp(-1) {} |
||||||
|
}; |
||||||
|
std::deque<StackEntry> stack; |
||||||
|
|
||||||
|
int regionDepth; // functions only (no named regions)
|
||||||
|
int regionDepthOpenCV; // functions from OpenCV library
|
||||||
|
|
||||||
|
RegionStatistics stat; |
||||||
|
RegionStatisticsStatus stat_status; |
||||||
|
|
||||||
|
StackEntry dummy_stack_top; // parallel_for root region
|
||||||
|
RegionStatistics parallel_for_stat; |
||||||
|
RegionStatisticsStatus parallel_for_stat_status; |
||||||
|
size_t parallel_for_stack_size; |
||||||
|
|
||||||
|
|
||||||
|
mutable cv::Ptr<TraceStorage> storage; |
||||||
|
|
||||||
|
TraceManagerThreadLocal() : |
||||||
|
threadID(cv::utils::getThreadID()), |
||||||
|
region_counter(0), totalSkippedEvents(0), |
||||||
|
currentActiveRegion(NULL), |
||||||
|
regionDepth(0), |
||||||
|
regionDepthOpenCV(0), |
||||||
|
parallel_for_stack_size(0) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
~TraceManagerThreadLocal(); |
||||||
|
|
||||||
|
TraceStorage* getStorage() const; |
||||||
|
|
||||||
|
void recordLocation(const Region::LocationStaticStorage& location); |
||||||
|
void recordRegionEnter(const Region& region); |
||||||
|
void recordRegionLeave(const Region& region, const RegionStatistics& result); |
||||||
|
void recordRegionArg(const Region& region, const TraceArg& arg, const char& value); |
||||||
|
|
||||||
|
inline void stackPush(Region* region, const Region::LocationStaticStorage* location, int64 beginTimestamp) |
||||||
|
{ |
||||||
|
stack.push_back(StackEntry(region, location, beginTimestamp)); |
||||||
|
} |
||||||
|
inline Region* stackTopRegion() const |
||||||
|
{ |
||||||
|
if (stack.empty()) |
||||||
|
return dummy_stack_top.region; |
||||||
|
return stack.back().region; |
||||||
|
} |
||||||
|
inline const Region::LocationStaticStorage* stackTopLocation() const |
||||||
|
{ |
||||||
|
if (stack.empty()) |
||||||
|
return dummy_stack_top.location; |
||||||
|
return stack.back().location; |
||||||
|
} |
||||||
|
inline int64 stackTopBeginTimestamp() const |
||||||
|
{ |
||||||
|
if (stack.empty()) |
||||||
|
return dummy_stack_top.beginTimestamp; |
||||||
|
return stack.back().beginTimestamp; |
||||||
|
} |
||||||
|
inline void stackPop() |
||||||
|
{ |
||||||
|
CV_DbgAssert(!stack.empty()); |
||||||
|
stack.pop_back(); |
||||||
|
} |
||||||
|
void dumpStack(std::ostream& out, bool onlyFunctions) const; |
||||||
|
|
||||||
|
inline Region* getCurrentActiveRegion() |
||||||
|
{ |
||||||
|
return currentActiveRegion; |
||||||
|
} |
||||||
|
|
||||||
|
inline int getCurrentDepth() const { return (int)stack.size(); } |
||||||
|
}; |
||||||
|
|
||||||
|
class CV_EXPORTS TraceManager |
||||||
|
{ |
||||||
|
public: |
||||||
|
TraceManager(); |
||||||
|
~TraceManager(); |
||||||
|
|
||||||
|
static bool isActivated(); |
||||||
|
|
||||||
|
Mutex mutexCreate; |
||||||
|
Mutex mutexCount; |
||||||
|
|
||||||
|
TLSData<TraceManagerThreadLocal> tls; |
||||||
|
|
||||||
|
cv::Ptr<TraceStorage> trace_storage; |
||||||
|
private: |
||||||
|
// disable copying
|
||||||
|
TraceManager(const TraceManager&); |
||||||
|
TraceManager& operator=(const TraceManager&); |
||||||
|
}; |
||||||
|
|
||||||
|
CV_EXPORTS TraceManager& getTraceManager(); |
||||||
|
inline Region* getCurrentActiveRegion() { return getTraceManager().tls.get()->getCurrentActiveRegion(); } |
||||||
|
inline Region* getCurrentRegion() { return getTraceManager().tls.get()->stackTopRegion(); } |
||||||
|
|
||||||
|
void parallelForSetRootRegion(const Region& rootRegion, const TraceManagerThreadLocal& root_ctx); |
||||||
|
void parallelForAttachNestedRegion(const Region& rootRegion); |
||||||
|
void parallelForFinalize(const Region& rootRegion); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Region::LocationExtraData |
||||||
|
{ |
||||||
|
int global_location_id; // 0 - region is disabled
|
||||||
|
#ifdef OPENCV_WITH_ITT |
||||||
|
// Special fields for ITT
|
||||||
|
__itt_string_handle* volatile ittHandle_name; |
||||||
|
__itt_string_handle* volatile ittHandle_filename; |
||||||
|
#endif |
||||||
|
LocationExtraData(const LocationStaticStorage& location); |
||||||
|
|
||||||
|
static Region::LocationExtraData* init(const Region::LocationStaticStorage& location); |
||||||
|
}; |
||||||
|
|
||||||
|
class Region::Impl |
||||||
|
{ |
||||||
|
public: |
||||||
|
const LocationStaticStorage& location; |
||||||
|
|
||||||
|
Region& region; |
||||||
|
Region* const parentRegion; |
||||||
|
|
||||||
|
const int threadID; |
||||||
|
const int global_region_id; |
||||||
|
|
||||||
|
const int64 beginTimestamp; |
||||||
|
int64 endTimestamp; |
||||||
|
|
||||||
|
int directChildrenCount; |
||||||
|
|
||||||
|
enum OptimizationPath { |
||||||
|
CODE_PATH_PLAIN = 0, |
||||||
|
CODE_PATH_IPP, |
||||||
|
CODE_PATH_OPENCL, |
||||||
|
CODE_PATH_OPENVX |
||||||
|
}; |
||||||
|
|
||||||
|
#ifdef OPENCV_WITH_ITT |
||||||
|
bool itt_id_registered; |
||||||
|
__itt_id itt_id; |
||||||
|
#endif |
||||||
|
|
||||||
|
Impl(TraceManagerThreadLocal& ctx, Region* parentRegion_, Region& region_, const LocationStaticStorage& location_, int64 beginTimestamp_); |
||||||
|
|
||||||
|
void enterRegion(TraceManagerThreadLocal& ctx); |
||||||
|
void leaveRegion(TraceManagerThreadLocal& ctx); |
||||||
|
|
||||||
|
void registerRegion(TraceManagerThreadLocal& ctx); |
||||||
|
|
||||||
|
void release(); |
||||||
|
protected: |
||||||
|
~Impl(); |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}}}} // namespace
|
||||||
|
|
||||||
|
//! @endcond
|
||||||
|
|
||||||
|
#endif |
||||||
|
|
||||||
|
#endif // OPENCV_TRACE_PRIVATE_HPP
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,435 @@ |
|||||||
|
from __future__ import print_function |
||||||
|
|
||||||
|
import os |
||||||
|
import sys |
||||||
|
import csv |
||||||
|
from pprint import pprint |
||||||
|
from collections import deque |
||||||
|
|
||||||
|
# trace.hpp |
||||||
|
REGION_FLAG_IMPL_MASK = 15 << 16; |
||||||
|
REGION_FLAG_IMPL_IPP = 1 << 16; |
||||||
|
REGION_FLAG_IMPL_OPENCL = 2 << 16; |
||||||
|
|
||||||
|
DEBUG = False |
||||||
|
|
||||||
|
if DEBUG: |
||||||
|
dprint = print |
||||||
|
dpprint = pprint |
||||||
|
else: |
||||||
|
def dprint(args, **kwargs): |
||||||
|
pass |
||||||
|
def dpprint(args, **kwargs): |
||||||
|
pass |
||||||
|
|
||||||
|
def tryNum(s): |
||||||
|
if s.startswith('0x'): |
||||||
|
try: |
||||||
|
return int(s, 16) |
||||||
|
except ValueError: |
||||||
|
pass |
||||||
|
try: |
||||||
|
return int(s) |
||||||
|
except ValueError: |
||||||
|
pass |
||||||
|
if sys.version_info[0] < 3: |
||||||
|
try: |
||||||
|
return long(s) |
||||||
|
except ValueError: |
||||||
|
pass |
||||||
|
return s |
||||||
|
|
||||||
|
def formatTimestamp(t): |
||||||
|
return "%.3f" % (t * 1e-6) |
||||||
|
|
||||||
|
try: |
||||||
|
from statistics import median |
||||||
|
except ImportError: |
||||||
|
def median(lst): |
||||||
|
sortedLst = sorted(lst) |
||||||
|
lstLen = len(lst) |
||||||
|
index = (lstLen - 1) // 2 |
||||||
|
if (lstLen % 2): |
||||||
|
return sortedLst[index] |
||||||
|
else: |
||||||
|
return (sortedLst[index] + sortedLst[index + 1]) * 0.5 |
||||||
|
|
||||||
|
def getCXXFunctionName(spec): |
||||||
|
def dropParams(spec): |
||||||
|
pos = len(spec) - 1 |
||||||
|
depth = 0 |
||||||
|
while pos >= 0: |
||||||
|
if spec[pos] == ')': |
||||||
|
depth = depth + 1 |
||||||
|
elif spec[pos] == '(': |
||||||
|
depth = depth - 1 |
||||||
|
if depth == 0: |
||||||
|
if pos == 0 or spec[pos - 1] in ['#', ':']: |
||||||
|
res = dropParams(spec[pos+1:-1]) |
||||||
|
return (spec[:pos] + res[0], res[1]) |
||||||
|
return (spec[:pos], spec[pos:]) |
||||||
|
pos = pos - 1 |
||||||
|
return (spec, '') |
||||||
|
|
||||||
|
def extractName(spec): |
||||||
|
pos = len(spec) - 1 |
||||||
|
inName = False |
||||||
|
while pos >= 0: |
||||||
|
if spec[pos] == ' ': |
||||||
|
if inName: |
||||||
|
return spec[pos+1:] |
||||||
|
elif spec[pos].isalnum(): |
||||||
|
inName = True |
||||||
|
pos = pos - 1 |
||||||
|
return spec |
||||||
|
|
||||||
|
if spec.startswith('IPP') or spec.startswith('OpenCL'): |
||||||
|
prefix_size = len('IPP') if spec.startswith('IPP') else len('OpenCL') |
||||||
|
prefix = spec[:prefix_size] |
||||||
|
if prefix_size < len(spec) and spec[prefix_size] in ['#', ':']: |
||||||
|
prefix = prefix + spec[prefix_size] |
||||||
|
prefix_size = prefix_size + 1 |
||||||
|
begin = prefix_size |
||||||
|
while begin < len(spec): |
||||||
|
if spec[begin].isalnum() or spec[begin] in ['_', ':']: |
||||||
|
break |
||||||
|
begin = begin + 1 |
||||||
|
if begin == len(spec): |
||||||
|
return spec |
||||||
|
end = begin |
||||||
|
while end < len(spec): |
||||||
|
if not (spec[end].isalnum() or spec[end] in ['_', ':']): |
||||||
|
break |
||||||
|
end = end + 1 |
||||||
|
return prefix + spec[begin:end] |
||||||
|
|
||||||
|
spec = spec.replace(') const', ')') # const methods |
||||||
|
(ret_type_name, params) = dropParams(spec) |
||||||
|
name = extractName(ret_type_name) |
||||||
|
if 'operator' in name: |
||||||
|
return name + params |
||||||
|
if name.startswith('&'): |
||||||
|
return name[1:] |
||||||
|
return name |
||||||
|
|
||||||
|
stack_size = 10 |
||||||
|
|
||||||
|
class Trace: |
||||||
|
def __init__(self, filename=None): |
||||||
|
self.tasks = {} |
||||||
|
self.tasks_list = [] |
||||||
|
self.locations = {} |
||||||
|
self.threads_stack = {} |
||||||
|
self.pending_files = deque() |
||||||
|
if filename: |
||||||
|
self.load(filename) |
||||||
|
|
||||||
|
class TraceTask: |
||||||
|
def __init__(self, threadID, taskID, locationID, beginTimestamp): |
||||||
|
self.threadID = threadID |
||||||
|
self.taskID = taskID |
||||||
|
self.locationID = locationID |
||||||
|
self.beginTimestamp = beginTimestamp |
||||||
|
self.endTimestamp = None |
||||||
|
self.parentTaskID = None |
||||||
|
self.parentThreadID = None |
||||||
|
self.childTask = [] |
||||||
|
self.selfTimeIPP = 0 |
||||||
|
self.selfTimeOpenCL = 0 |
||||||
|
self.totalTimeIPP = 0 |
||||||
|
self.totalTimeOpenCL = 0 |
||||||
|
|
||||||
|
def __repr__(self): |
||||||
|
return "TID={} ID={} loc={} parent={}:{} begin={} end={} IPP={}/{} OpenCL={}/{}".format( |
||||||
|
self.threadID, self.taskID, self.locationID, self.parentThreadID, self.parentTaskID, |
||||||
|
self.beginTimestamp, self.endTimestamp, self.totalTimeIPP, self.selfTimeIPP, self.totalTimeOpenCL, self.selfTimeOpenCL) |
||||||
|
|
||||||
|
|
||||||
|
class TraceLocation: |
||||||
|
def __init__(self, locationID, filename, line, name, flags): |
||||||
|
self.locationID = locationID |
||||||
|
self.filename = os.path.split(filename)[1] |
||||||
|
self.line = line |
||||||
|
self.name = getCXXFunctionName(name) |
||||||
|
self.flags = flags |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
return "{}#{}:{}".format(self.name, self.filename, self.line) |
||||||
|
|
||||||
|
def __repr__(self): |
||||||
|
return "ID={} {}:{}:{}".format(self.locationID, self.filename, self.line, self.name) |
||||||
|
|
||||||
|
def parse_file(self, filename): |
||||||
|
dprint("Process file: '{}'".format(filename)) |
||||||
|
with open(filename) as infile: |
||||||
|
for line in infile: |
||||||
|
line = str(line).strip() |
||||||
|
if line[0] == "#": |
||||||
|
if line.startswith("#thread file:"): |
||||||
|
name = str(line.split(':', 1)[1]).strip() |
||||||
|
self.pending_files.append(os.path.join(os.path.split(filename)[0], name)) |
||||||
|
continue |
||||||
|
self.parse_line(line) |
||||||
|
|
||||||
|
def parse_line(self, line): |
||||||
|
opts = line.split(',') |
||||||
|
dpprint(opts) |
||||||
|
if opts[0] == 'l': |
||||||
|
opts = list(csv.reader([line]))[0] # process quote more |
||||||
|
locationID = int(opts[1]) |
||||||
|
filename = str(opts[2]) |
||||||
|
line = int(opts[3]) |
||||||
|
name = opts[4] |
||||||
|
flags = tryNum(opts[5]) |
||||||
|
self.locations[locationID] = self.TraceLocation(locationID, filename, line, name, flags) |
||||||
|
return |
||||||
|
extra_opts = {} |
||||||
|
for e in opts[5:]: |
||||||
|
if not '=' in e: |
||||||
|
continue |
||||||
|
(k, v) = e.split('=') |
||||||
|
extra_opts[k] = tryNum(v) |
||||||
|
if extra_opts: |
||||||
|
dpprint(extra_opts) |
||||||
|
threadID = None |
||||||
|
taskID = None |
||||||
|
locationID = None |
||||||
|
ts = None |
||||||
|
if opts[0] in ['b', 'e']: |
||||||
|
threadID = int(opts[1]) |
||||||
|
taskID = int(opts[4]) |
||||||
|
locationID = int(opts[3]) |
||||||
|
ts = tryNum(opts[2]) |
||||||
|
thread_stack = None |
||||||
|
currentTask = (None, None) |
||||||
|
if threadID is not None: |
||||||
|
if not threadID in self.threads_stack: |
||||||
|
thread_stack = deque() |
||||||
|
self.threads_stack[threadID] = thread_stack |
||||||
|
else: |
||||||
|
thread_stack = self.threads_stack[threadID] |
||||||
|
currentTask = None if not thread_stack else thread_stack[-1] |
||||||
|
t = (threadID, taskID) |
||||||
|
if opts[0] == 'b': |
||||||
|
assert not t in self.tasks, "Duplicate task: " + str(t) + repr(self.tasks[t]) |
||||||
|
task = self.TraceTask(threadID, taskID, locationID, ts) |
||||||
|
self.tasks[t] = task |
||||||
|
self.tasks_list.append(task) |
||||||
|
thread_stack.append((threadID, taskID)) |
||||||
|
if currentTask: |
||||||
|
task.parentThreadID = currentTask[0] |
||||||
|
task.parentTaskID = currentTask[1] |
||||||
|
if 'parentThread' in extra_opts: |
||||||
|
task.parentThreadID = extra_opts['parentThread'] |
||||||
|
if 'parent' in extra_opts: |
||||||
|
task.parentTaskID = extra_opts['parent'] |
||||||
|
if opts[0] == 'e': |
||||||
|
task = self.tasks[t] |
||||||
|
task.endTimestamp = ts |
||||||
|
if 'tIPP' in extra_opts: |
||||||
|
task.selfTimeIPP = extra_opts['tIPP'] |
||||||
|
if 'tOCL' in extra_opts: |
||||||
|
task.selfTimeOpenCL = extra_opts['tOCL'] |
||||||
|
thread_stack.pop() |
||||||
|
|
||||||
|
def load(self, filename): |
||||||
|
self.pending_files.append(filename) |
||||||
|
if DEBUG: |
||||||
|
with open(filename, 'r') as f: |
||||||
|
print(f.read(), end='') |
||||||
|
while self.pending_files: |
||||||
|
self.parse_file(self.pending_files.pop()) |
||||||
|
|
||||||
|
def getParentTask(self, task): |
||||||
|
return self.tasks.get((task.parentThreadID, task.parentTaskID), None) |
||||||
|
|
||||||
|
def process(self): |
||||||
|
self.tasks_list.sort(key=lambda x: x.beginTimestamp) |
||||||
|
|
||||||
|
parallel_for_location = None |
||||||
|
for (id, l) in self.locations.items(): |
||||||
|
if l.name == 'parallel_for': |
||||||
|
parallel_for_location = l.locationID |
||||||
|
break |
||||||
|
|
||||||
|
for task in self.tasks_list: |
||||||
|
try: |
||||||
|
task.duration = task.endTimestamp - task.beginTimestamp |
||||||
|
task.selfDuration = task.duration |
||||||
|
except: |
||||||
|
task.duration = None |
||||||
|
task.selfDuration = None |
||||||
|
task.totalTimeIPP = task.selfTimeIPP |
||||||
|
task.totalTimeOpenCL = task.selfTimeOpenCL |
||||||
|
|
||||||
|
dpprint(self.tasks) |
||||||
|
dprint("Calculate total times") |
||||||
|
|
||||||
|
for task in self.tasks_list: |
||||||
|
parentTask = self.getParentTask(task) |
||||||
|
if parentTask: |
||||||
|
parentTask.selfDuration = parentTask.selfDuration - task.duration |
||||||
|
parentTask.childTask.append(task) |
||||||
|
timeIPP = task.selfTimeIPP |
||||||
|
timeOpenCL = task.selfTimeOpenCL |
||||||
|
while parentTask: |
||||||
|
if parentTask.locationID == parallel_for_location: # TODO parallel_for |
||||||
|
break |
||||||
|
parentLocation = self.locations[parentTask.locationID] |
||||||
|
if (parentLocation.flags & REGION_FLAG_IMPL_MASK) == REGION_FLAG_IMPL_IPP: |
||||||
|
parentTask.selfTimeIPP = parentTask.selfTimeIPP - timeIPP |
||||||
|
timeIPP = 0 |
||||||
|
else: |
||||||
|
parentTask.totalTimeIPP = parentTask.totalTimeIPP + timeIPP |
||||||
|
if (parentLocation.flags & REGION_FLAG_IMPL_MASK) == REGION_FLAG_IMPL_OPENCL: |
||||||
|
parentTask.selfTimeOpenCL = parentTask.selfTimeOpenCL - timeOpenCL |
||||||
|
timeOpenCL = 0 |
||||||
|
else: |
||||||
|
parentTask.totalTimeOpenCL = parentTask.totalTimeOpenCL + timeOpenCL |
||||||
|
parentTask = self.getParentTask(parentTask) |
||||||
|
|
||||||
|
dpprint(self.tasks) |
||||||
|
dprint("Calculate total times (parallel_for)") |
||||||
|
|
||||||
|
for task in self.tasks_list: |
||||||
|
if task.locationID == parallel_for_location: |
||||||
|
task.selfDuration = 0 |
||||||
|
childDuration = sum([t.duration for t in task.childTask]) |
||||||
|
if task.duration == 0 or childDuration == 0: |
||||||
|
continue |
||||||
|
timeCoef = task.duration / float(childDuration) |
||||||
|
childTimeIPP = sum([t.totalTimeIPP for t in task.childTask]) |
||||||
|
childTimeOpenCL = sum([t.totalTimeOpenCL for t in task.childTask]) |
||||||
|
if childTimeIPP == 0 and childTimeOpenCL == 0: |
||||||
|
continue |
||||||
|
timeIPP = childTimeIPP * timeCoef |
||||||
|
timeOpenCL = childTimeOpenCL * timeCoef |
||||||
|
parentTask = task |
||||||
|
while parentTask: |
||||||
|
parentLocation = self.locations[parentTask.locationID] |
||||||
|
if (parentLocation.flags & REGION_FLAG_IMPL_MASK) == REGION_FLAG_IMPL_IPP: |
||||||
|
parentTask.selfTimeIPP = parentTask.selfTimeIPP - timeIPP |
||||||
|
timeIPP = 0 |
||||||
|
else: |
||||||
|
parentTask.totalTimeIPP = parentTask.totalTimeIPP + timeIPP |
||||||
|
if (parentLocation.flags & REGION_FLAG_IMPL_MASK) == REGION_FLAG_IMPL_OPENCL: |
||||||
|
parentTask.selfTimeOpenCL = parentTask.selfTimeOpenCL - timeOpenCL |
||||||
|
timeOpenCL = 0 |
||||||
|
else: |
||||||
|
parentTask.totalTimeOpenCL = parentTask.totalTimeOpenCL + timeOpenCL |
||||||
|
parentTask = self.getParentTask(parentTask) |
||||||
|
|
||||||
|
dpprint(self.tasks) |
||||||
|
dprint("Done") |
||||||
|
|
||||||
|
def dump(self, max_entries): |
||||||
|
assert isinstance(max_entries, int) |
||||||
|
|
||||||
|
class CallInfo(): |
||||||
|
def __init__(self, callID): |
||||||
|
self.callID = callID |
||||||
|
self.totalTimes = [] |
||||||
|
self.selfTimes = [] |
||||||
|
self.threads = set() |
||||||
|
self.selfTimesIPP = [] |
||||||
|
self.selfTimesOpenCL = [] |
||||||
|
self.totalTimesIPP = [] |
||||||
|
self.totalTimesOpenCL = [] |
||||||
|
|
||||||
|
calls = {} |
||||||
|
|
||||||
|
for currentTask in self.tasks_list: |
||||||
|
task = currentTask |
||||||
|
callID = [] |
||||||
|
for i in range(stack_size): |
||||||
|
callID.append(task.locationID) |
||||||
|
task = self.getParentTask(task) |
||||||
|
if not task: |
||||||
|
break |
||||||
|
callID = tuple(callID) |
||||||
|
if not callID in calls: |
||||||
|
call = CallInfo(callID) |
||||||
|
calls[callID] = call |
||||||
|
else: |
||||||
|
call = calls[callID] |
||||||
|
call.totalTimes.append(currentTask.duration) |
||||||
|
call.selfTimes.append(currentTask.selfDuration) |
||||||
|
call.threads.add(currentTask.threadID) |
||||||
|
call.selfTimesIPP.append(currentTask.selfTimeIPP) |
||||||
|
call.selfTimesOpenCL.append(currentTask.selfTimeOpenCL) |
||||||
|
call.totalTimesIPP.append(currentTask.totalTimeIPP) |
||||||
|
call.totalTimesOpenCL.append(currentTask.totalTimeOpenCL) |
||||||
|
|
||||||
|
dpprint(self.tasks) |
||||||
|
dpprint(self.locations) |
||||||
|
dpprint(calls) |
||||||
|
|
||||||
|
calls_self_sum = {k: sum(v.selfTimes) for (k, v) in calls.items()} |
||||||
|
calls_total_sum = {k: sum(v.totalTimes) for (k, v) in calls.items()} |
||||||
|
calls_median = {k: median(v.selfTimes) for (k, v) in calls.items()} |
||||||
|
calls_sorted = sorted(calls.keys(), key=lambda x: calls_self_sum[x], reverse=True) |
||||||
|
|
||||||
|
calls_self_sum_IPP = {k: sum(v.selfTimesIPP) for (k, v) in calls.items()} |
||||||
|
calls_total_sum_IPP = {k: sum(v.totalTimesIPP) for (k, v) in calls.items()} |
||||||
|
|
||||||
|
calls_self_sum_OpenCL = {k: sum(v.selfTimesOpenCL) for (k, v) in calls.items()} |
||||||
|
calls_total_sum_OpenCL = {k: sum(v.totalTimesOpenCL) for (k, v) in calls.items()} |
||||||
|
|
||||||
|
if max_entries > 0 and len(calls_sorted) > max_entries: |
||||||
|
calls_sorted = calls_sorted[:max_entries] |
||||||
|
|
||||||
|
def formatPercents(p): |
||||||
|
if p is not None: |
||||||
|
return "{:>3d}".format(int(p*100)) |
||||||
|
return '' |
||||||
|
|
||||||
|
name_width = 70 |
||||||
|
timestamp_width = 12 |
||||||
|
def fmtTS(): |
||||||
|
return '{:>' + str(timestamp_width) + '}' |
||||||
|
fmt = "{:>3} {:<"+str(name_width)+"} {:>8} {:>3}"+((' '+fmtTS())*5)+((' '+fmtTS()+' {:>3}')*2) |
||||||
|
fmt2 = "{:>3} {:<"+str(name_width)+"} {:>8} {:>3}"+((' '+fmtTS())*5)+((' '+fmtTS()+' {:>3}')*2) |
||||||
|
print(fmt.format("ID", "name", "count", "thr", "min", "max", "median", "avg", "*self*", "IPP", "%", "OpenCL", "%")) |
||||||
|
print(fmt2.format("", "", "", "", "t-min", "t-max", "t-median", "t-avg", "total", "t-IPP", "%", "t-OpenCL", "%")) |
||||||
|
for (index, callID) in enumerate(calls_sorted): |
||||||
|
call_self_times = calls[callID].selfTimes |
||||||
|
loc0 = self.locations[callID[0]] |
||||||
|
loc_array = [] # [str(callID)] |
||||||
|
for (i, l) in enumerate(callID): |
||||||
|
loc = self.locations[l] |
||||||
|
loc_array.append(loc.name if i > 0 else str(loc)) |
||||||
|
loc_str = '|'.join(loc_array) |
||||||
|
if len(loc_str) > name_width: loc_str = loc_str[:name_width-3]+'...' |
||||||
|
print(fmt.format(index + 1, loc_str, len(call_self_times), |
||||||
|
len(calls[callID].threads), |
||||||
|
formatTimestamp(min(call_self_times)), |
||||||
|
formatTimestamp(max(call_self_times)), |
||||||
|
formatTimestamp(calls_median[callID]), |
||||||
|
formatTimestamp(sum(call_self_times)/float(len(call_self_times))), |
||||||
|
formatTimestamp(sum(call_self_times)), |
||||||
|
formatTimestamp(calls_self_sum_IPP[callID]), |
||||||
|
formatPercents(calls_self_sum_IPP[callID] / float(calls_self_sum[callID])) if calls_self_sum[callID] > 0 else formatPercents(None), |
||||||
|
formatTimestamp(calls_self_sum_OpenCL[callID]), |
||||||
|
formatPercents(calls_self_sum_OpenCL[callID] / float(calls_self_sum[callID])) if calls_self_sum[callID] > 0 else formatPercents(None), |
||||||
|
)) |
||||||
|
call_total_times = calls[callID].totalTimes |
||||||
|
print(fmt2.format("", "", "", "", |
||||||
|
formatTimestamp(min(call_total_times)), |
||||||
|
formatTimestamp(max(call_total_times)), |
||||||
|
formatTimestamp(median(call_total_times)), |
||||||
|
formatTimestamp(sum(call_total_times)/float(len(call_total_times))), |
||||||
|
formatTimestamp(sum(call_total_times)), |
||||||
|
formatTimestamp(calls_total_sum_IPP[callID]), |
||||||
|
formatPercents(calls_total_sum_IPP[callID] / float(calls_total_sum[callID])) if calls_total_sum[callID] > 0 else formatPercents(None), |
||||||
|
formatTimestamp(calls_total_sum_OpenCL[callID]), |
||||||
|
formatPercents(calls_total_sum_OpenCL[callID] / float(calls_total_sum[callID])) if calls_total_sum[callID] > 0 else formatPercents(None), |
||||||
|
)) |
||||||
|
print() |
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
tracefile = sys.argv[1] if len(sys.argv) > 1 else 'OpenCVTrace.txt' |
||||||
|
count = int(sys.argv[2]) if len(sys.argv) > 2 else 10 |
||||||
|
trace = Trace(tracefile) |
||||||
|
trace.process() |
||||||
|
trace.dump(max_entries = count) |
||||||
|
print("OK") |
@ -0,0 +1,92 @@ |
|||||||
|
/* OpenCV Application Tracing support demo. */ |
||||||
|
#include <iostream> |
||||||
|
|
||||||
|
#include <opencv2/opencv.hpp> |
||||||
|
#include <opencv2/core/utils/trace.hpp> |
||||||
|
|
||||||
|
using namespace cv; |
||||||
|
using namespace std; |
||||||
|
|
||||||
|
static void process_frame(const cv::UMat& frame) |
||||||
|
{ |
||||||
|
CV_TRACE_FUNCTION(); // OpenCV Trace macro for function
|
||||||
|
|
||||||
|
imshow("Live", frame); |
||||||
|
|
||||||
|
UMat gray, processed; |
||||||
|
cv::cvtColor(frame, gray, COLOR_BGR2GRAY); |
||||||
|
Canny(gray, processed, 32, 64, 3); |
||||||
|
imshow("Processed", processed); |
||||||
|
} |
||||||
|
|
||||||
|
int main(int argc, char** argv) |
||||||
|
{ |
||||||
|
CV_TRACE_FUNCTION(); |
||||||
|
|
||||||
|
cv::CommandLineParser parser(argc, argv, |
||||||
|
"{help h ? | | help message}" |
||||||
|
"{n | 100 | number of frames to process }" |
||||||
|
"{@video | 0 | video filename or cameraID }" |
||||||
|
); |
||||||
|
if (parser.has("help")) |
||||||
|
{ |
||||||
|
parser.printMessage(); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
VideoCapture capture; |
||||||
|
std::string video = parser.get<string>("@video"); |
||||||
|
if (video.size() == 1 && isdigit(video[0])) |
||||||
|
capture.open(parser.get<int>("@video")); |
||||||
|
else |
||||||
|
capture.open(video); |
||||||
|
int nframes = 0; |
||||||
|
if (capture.isOpened()) |
||||||
|
{ |
||||||
|
nframes = (int)capture.get(CAP_PROP_FRAME_COUNT); |
||||||
|
cout << "Video " << video << |
||||||
|
": width=" << capture.get(CAP_PROP_FRAME_WIDTH) << |
||||||
|
", height=" << capture.get(CAP_PROP_FRAME_HEIGHT) << |
||||||
|
", nframes=" << nframes << endl; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
cout << "Could not initialize video capturing...\n"; |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
int N = parser.get<int>("n"); |
||||||
|
if (nframes > 0 && N > nframes) |
||||||
|
N = nframes; |
||||||
|
|
||||||
|
cout << "Start processing..." << endl |
||||||
|
<< "Press ESC key to terminate" << endl; |
||||||
|
|
||||||
|
UMat frame; |
||||||
|
for (int i = 0; N > 0 ? (i < N) : true; i++) |
||||||
|
{ |
||||||
|
CV_TRACE_REGION("FRAME"); // OpenCV Trace macro for named "scope" region
|
||||||
|
{ |
||||||
|
CV_TRACE_REGION("read"); |
||||||
|
capture.read(frame); |
||||||
|
|
||||||
|
if (frame.empty()) |
||||||
|
{ |
||||||
|
cerr << "Can't capture frame: " << i << std::endl; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
// OpenCV Trace macro for NEXT named region in the same C++ scope
|
||||||
|
// Previous "read" region will be marked complete on this line.
|
||||||
|
// Use this to eliminate unnecessary curly braces.
|
||||||
|
CV_TRACE_REGION_NEXT("process"); |
||||||
|
process_frame(frame); |
||||||
|
|
||||||
|
CV_TRACE_REGION_NEXT("delay"); |
||||||
|
if (waitKey(1) == 27/*ESC*/) |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
} |
Loading…
Reference in new issue