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