Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions src/common/itt/include/openvino/itt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ namespace internal {
domain_t domain(const char* name);
handle_t handle(const char* name);
void taskBegin(domain_t d, handle_t t);
void taskBegin(domain_t d, handle_t t, const char* key, uint64_t value);
void taskEnd(domain_t d);
void threadName(const char* name);
void regionBegin(domain_t d, handle_t t);
void regionBegin(domain_t d, handle_t t, const char* key, uint64_t value);
void regionEnd(domain_t d);
} // namespace internal
/**
Expand Down Expand Up @@ -115,6 +117,27 @@ struct ScopedTask {
internal::taskBegin(domain(), taskHandle);
}

/**
* @brief Constructs a scoped task with an associated key-value metadata pair.
*
* Creates an ITT (Intel Tracing Technology) scoped task that will automatically
* begin upon construction and end when the object goes out of scope (RAII pattern).
* This overload allows attaching custom metadata to the task for enhanced profiling.
*
* @param taskHandle Handle identifying the task type for profiling tools.
* @param key String identifier for the metadata attribute (e.g., "InferenceID").
* @param value Numeric value associated with the key (e.g., unique request ID).
*
* @note The task begins immediately upon construction via internal::taskBegin.
* @note The key string must remain valid for the duration of the task scope.
* @note This constructor is noexcept, ensuring exception safety in profiling code.
*
* @see ScopedTask(handle_t) for the basic constructor without metadata.
*/
ScopedTask(handle_t taskHandle, const char* key, uint64_t value) noexcept {
internal::taskBegin(domain(), taskHandle, key, value);
}

/**
* @brief The ScopedTask destructor closes or ends the task scope
*/
Expand Down Expand Up @@ -143,6 +166,20 @@ struct ScopedRegion {
internal::regionBegin(domain(), handle);
}

/**
* @brief Constructs a scoped region with metadata for ITT profiling.
*
* @param handle Region identifier for profiling tools.
* @param key Metadata attribute name (e.g., "RequestID").
* @param value Metadata numeric value associated with the key.
*
* @note Region begins immediately and ends when object goes out of scope (RAII).
* @note The key string must remain valid for the region's lifetime.
*/
ScopedRegion(handle_t handle, const char* key, uint64_t value) noexcept {
internal::regionBegin(domain(), handle, key, value);
}

/**
* @brief The ScopedRegion destructor closes or ends the region scope
*/
Expand Down Expand Up @@ -308,8 +345,15 @@ class TaskChain {
* @ingroup ov_dev_profiling
* @brief Annotate section of code till scope exit for BASE/FULL modes regardless of profiling filter groups.
* @details In case if handle or taskName absent, the current function name is used.
* @note All *_BASE() macros are enabled by default and will be used by supporting toolchains. The strings
* used/provided by these calls should follow the following rules:
* - Should NOT be deleted or modified to ensure correct visible names in profiling tools
* until CVS-179230 is implemented/resolved.
* - Should use string literals or constant strings when possible
* @param domain [in] Known at compile time name of module or library (the domain name).
* @param handleOrTaskName [in] The annotation name or handle for section of code. Parameter is optional.
* @param metadata_key [in] A metadata element's key as a string. Parameter is optional.
* @param metadata_value [in] The metadata value. Parameter is optional.
*/
#define OV_ITT_SCOPED_TASK_BASE(...) OV_PP_OVERLOAD(OV_ITT_SCOPED_TASK_BASE, __VA_ARGS__)

Expand All @@ -321,15 +365,28 @@ class TaskChain {
openvino::itt::ScopedTask<domain> OV_PP_CAT(ittScopedTask, __LINE__)( \
openvino::itt::handle<struct OV_PP_CAT(Task, __LINE__)>(taskOrTaskName));

#define OV_ITT_SCOPED_TASK_BASE_4(domain, taskOrTaskName, metadata_key, metadata_value) \
openvino::itt::ScopedTask<domain> OV_PP_CAT(ittScopedTask, __LINE__)( \
openvino::itt::handle<struct OV_PP_CAT(Task, __LINE__)>(taskOrTaskName), \
metadata_key, \
metadata_value);

/**
* @def OV_ITT_SCOPED_REGION_BASE(domain, handleOrRegionName)
* @ingroup ov_dev_profiling
* @brief Annotate region of code till scope exit for BASE/FULL modes regardless of profiling filter groups.
* @details In case if handle or regionName absent, the current function name is used.
* @note Implements a region scope (single-active per thread; tasks started within
* the region attach as children).
* @note All *_BASE() macros are enabled by default and will be used by supporting toolchains. The strings
* used/provided by these calls should follow the following rules:
* - Should NOT be deleted or modified to ensure correct visible names in profiling tools
* until CVS-179230 is implemented/resolved.
* - Should use string literals or constant strings when possible
* @param domain [in] Known at compile time name of module or library (the domain name).
* @param handleOrRegionName [in] The annotation name or handle for section of code. Parameter is optional.
* @param metadata_key [in] A metadata element's key as a string. Parameter is optional.
* @param metadata_value [in] The metadata value. Parameter is optional.
*/
#define OV_ITT_SCOPED_REGION_BASE(...) OV_PP_OVERLOAD(OV_ITT_SCOPED_REGION_BASE, __VA_ARGS__)

Expand All @@ -341,6 +398,12 @@ class TaskChain {
openvino::itt::ScopedRegion<domain> OV_PP_CAT(ittScopedRegion, __LINE__)( \
openvino::itt::handle<struct OV_PP_CAT(Region, __LINE__)>(regionOrRegionName));

#define OV_ITT_SCOPED_REGION_BASE_4(domain, regionOrRegionName, metadata_key, metadata_value) \
openvino::itt::ScopedRegion<domain> OV_PP_CAT(ittScopedRegion, __LINE__)( \
openvino::itt::handle<struct OV_PP_CAT(Region, __LINE__)>(regionOrRegionName), \
metadata_key, \
metadata_value);

/**
* @def OV_ITT_SCOPED_REGION(group, domain, handleOrRegionName)
* @ingroup ov_dev_profiling
Expand Down
50 changes: 50 additions & 0 deletions src/common/itt/src/itt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,16 @@ static thread_local uint64_t current_region_counter = 0;
static thread_local void* current_region_handle = nullptr;

domain_t domain(const char* name) {
if (!is_initialized() || name == nullptr) {
return nullptr;
}
return reinterpret_cast<domain_t>(__itt_domain_create(name));
}

handle_t handle(const char* name) {
if (!is_initialized() || name == nullptr) {
return nullptr;
}
return reinterpret_cast<handle_t>(__itt_string_handle_create(name));
}

Expand All @@ -64,6 +70,26 @@ void taskBegin(domain_t d, handle_t t) {
}
}

void taskBegin(domain_t d, handle_t t, const char* key, uint64_t value) {
if (!is_initialized() || d == nullptr || t == nullptr || key == nullptr) {
return;
}
if (!callStackDepth() || call_stack_depth++ < callStackDepth()) {
__itt_id parent_id =
current_region_counter != 0 ? __itt_id_make(current_region_handle, current_region_counter) : __itt_null;
__itt_domain* domain = reinterpret_cast<__itt_domain*>(d);
__itt_task_begin(domain, __itt_null, parent_id, reinterpret_cast<__itt_string_handle*>(t));
// The task id to which the metadata is assigned to is not available at this point. It will
// default to the parent task's ID
__itt_metadata_add(domain,
__itt_null,
__itt_string_handle_create(key),
__itt_metadata_u64,
1,
static_cast<void*>(const_cast<uint64_t*>(&value)));
}
}

void taskEnd(domain_t d) {
if (!is_initialized() || d == nullptr) {
return;
Expand Down Expand Up @@ -94,6 +120,26 @@ void regionBegin(domain_t d, handle_t t) {
reinterpret_cast<__itt_string_handle*>(t));
}

void regionBegin(domain_t d, handle_t t, const char* key, uint64_t value) {
if (!is_initialized() || d == nullptr || t == nullptr || key == nullptr) {
return;
}
std::lock_guard<std::mutex> lock(region_mutex);
auto region_counter = nextRegionId();
current_region_counter = region_counter;
current_region_handle = reinterpret_cast<void*>(t);
__itt_domain* domain = reinterpret_cast<__itt_domain*>(d);
__itt_id region_id = __itt_id_make(current_region_handle, current_region_counter);
__itt_region_begin(domain, region_id, __itt_null, reinterpret_cast<__itt_string_handle*>(t));
// Associate the <key-value> pair with the region
__itt_metadata_add(domain,
region_id,
__itt_string_handle_create(key),
__itt_metadata_u64,
1,
static_cast<void*>(const_cast<uint64_t*>(&value)));
}

void regionEnd(domain_t d) {
if (!is_initialized() || d == nullptr) {
return;
Expand All @@ -120,12 +166,16 @@ handle_t handle(const char*) {

void taskBegin(domain_t, handle_t) {}

void taskBegin(domain_t, handle_t, const char*, uint64_t) {}

void taskEnd(domain_t) {}

void threadName(const char*) {}

void regionBegin(domain_t, handle_t) {}

void regionBegin(domain_t, handle_t, const char*, uint64_t) {}

void regionEnd(domain_t) {}

#endif // ENABLE_PROFILING_ITT
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ class OPENVINO_RUNTIME_API IAsyncInferRequest : public IInferRequest {

Pipeline m_pipeline; //!< Pipeline variable that should be filled by inherited class.
Pipeline m_sync_pipeline; //!< Synchronous pipeline variable that should be filled by inherited class.
/**
* Tracks pipeline execution by having the same uniqueID for all stages of the same inference request.
*/
uint64_t m_infer_id;

private:
enum InferState { IDLE, BUSY, CANCELLED, STOP };
Expand Down
2 changes: 2 additions & 0 deletions src/inference/dev_api/openvino/runtime/plugin_itt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ namespace itt {
namespace domains {
OV_ITT_DOMAIN(Plugin)
OV_ITT_DOMAIN(PluginLoadTime)
// Domain to define Inference phase tasks
OV_ITT_DOMAIN(Inference, "ov::phases::inference")
} // namespace domains
} // namespace itt
} // namespace ov
22 changes: 11 additions & 11 deletions src/inference/src/cpp/core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ std::map<std::string, Version> Core::get_versions(const std::string& device_name
std::shared_ptr<ov::Model> Core::read_model(const std::wstring& model_path,
const std::wstring& bin_path,
const ov::AnyMap& properties) const {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Read model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Read model");
OV_CORE_CALL_STATEMENT(return _impl->read_model(ov::util::wstring_to_string(model_path),
ov::util::wstring_to_string(bin_path),
properties););
Expand All @@ -89,44 +89,44 @@ std::shared_ptr<ov::Model> Core::read_model(const std::wstring& model_path,
std::shared_ptr<ov::Model> Core::read_model(const std::string& model_path,
const std::string& bin_path,
const AnyMap& properties) const {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Read model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Read model");
OV_CORE_CALL_STATEMENT(return _impl->read_model(model_path, bin_path, properties););
}

std::shared_ptr<ov::Model> Core::read_model(const std::string& model, const ov::Tensor& weights) const {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Read model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Read model");
OV_CORE_CALL_STATEMENT(return _impl->read_model(model, weights););
}

CompiledModel Core::compile_model(const std::shared_ptr<const ov::Model>& model, const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
return compile_model(model, ov::default_device_name, config);
}

CompiledModel Core::compile_model(const std::shared_ptr<const ov::Model>& model,
const std::string& device_name,
const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
OV_CORE_CALL_STATEMENT({
auto exec = _impl->compile_model(model, device_name, config);
return {exec._ptr, exec._so};
});
}

CompiledModel Core::compile_model(const std::string& model_path, const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
return compile_model(model_path, ov::default_device_name, config);
}

#ifdef OPENVINO_ENABLE_UNICODE_PATH_SUPPORT
CompiledModel Core::compile_model(const std::wstring& model_path, const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
return compile_model(ov::util::wstring_to_string(model_path), config);
}
#endif

CompiledModel Core::compile_model(const std::string& model_path, const std::string& device_name, const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
OV_CORE_CALL_STATEMENT({
auto exec = _impl->compile_model(model_path, device_name, config);
return {exec._ptr, exec._so};
Expand All @@ -137,7 +137,7 @@ CompiledModel Core::compile_model(const std::string& model_path, const std::stri
CompiledModel Core::compile_model(const std::wstring& model_path,
const std::string& device_name,
const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
return compile_model(ov::util::wstring_to_string(model_path), device_name, config);
}
#endif
Expand All @@ -146,7 +146,7 @@ CompiledModel Core::compile_model(const std::string& model,
const ov::Tensor& weights,
const std::string& device_name,
const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
OV_CORE_CALL_STATEMENT({
auto exec = _impl->compile_model(model, weights, device_name, config);
return {exec._ptr, exec._so};
Expand All @@ -156,7 +156,7 @@ CompiledModel Core::compile_model(const std::string& model,
CompiledModel Core::compile_model(const std::shared_ptr<const ov::Model>& model,
const RemoteContext& context,
const AnyMap& config) {
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::OV, "Compile model");
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Phases, "Compile model");
OV_CORE_CALL_STATEMENT({
auto exec = _impl->compile_model(model, ov::SoPtr<ov::IRemoteContext>{context._impl, context._so}, config);
return {exec._ptr, exec._so};
Expand Down
13 changes: 12 additions & 1 deletion src/inference/src/dev/iasync_infer_request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@

#include "openvino/runtime/isync_infer_request.hpp"
#include "openvino/runtime/ivariable_state.hpp"
#include "openvino/runtime/plugin_itt.hpp"
#include "openvino/runtime/threading/immediate_executor.hpp"
#include "openvino/runtime/threading/istreams_executor.hpp"
#include "openvino/runtime/variable_state.hpp"

/// @brief Thread-safe global counter for unique inference request IDs.
static std::atomic<uint64_t> g_uid = {1};

namespace {

struct ImmediateStreamsExecutor : public ov::threading::ITaskExecutor {
Expand Down Expand Up @@ -39,7 +43,8 @@ ov::IAsyncInferRequest::IAsyncInferRequest(const std::shared_ptr<IInferRequest>&
const std::shared_ptr<ov::threading::ITaskExecutor>& callback_executor)
: m_sync_request(request),
m_request_executor(task_executor),
m_callback_executor(callback_executor) {
m_callback_executor(callback_executor),
m_infer_id(0) {
if (m_request_executor && m_sync_request)
m_pipeline = {{m_request_executor, [this] {
m_sync_request->infer();
Expand Down Expand Up @@ -119,6 +124,7 @@ void ov::IAsyncInferRequest::start_async_thread_unsafe() {
void ov::IAsyncInferRequest::run_first_stage(const Pipeline::iterator itBeginStage,
const Pipeline::iterator itEndStage,
const std::shared_ptr<ov::threading::ITaskExecutor> callbackExecutor) {
m_infer_id = g_uid++;
auto& firstStageExecutor = std::get<Stage_e::EXECUTOR>(*itBeginStage);
OPENVINO_ASSERT(nullptr != firstStageExecutor);
firstStageExecutor->run(make_next_stage_task(itBeginStage, itEndStage, std::move(callbackExecutor)));
Expand All @@ -130,6 +136,11 @@ ov::threading::Task ov::IAsyncInferRequest::make_next_stage_task(
const std::shared_ptr<ov::threading::ITaskExecutor> callbackExecutor) {
return std::bind(
[this, itStage, itEndStage](std::shared_ptr<ov::threading::ITaskExecutor>& callbackExecutor) mutable {
// Propagate the inference ID through all subsequent stages for this instance of the pipeline
OV_ITT_SCOPED_REGION_BASE(ov::itt::domains::Inference,
"Inference::pipeline",
"InferenceID",
m_infer_id);
std::exception_ptr currentException = nullptr;
auto& thisStage = *itStage;
auto itNextStage = itStage + 1;
Expand Down
3 changes: 3 additions & 0 deletions src/inference/src/itt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ namespace domains {
OV_ITT_DOMAIN(OV, "ov");
OV_ITT_DOMAIN(ReadTime, "ov::ReadTime");
OV_ITT_DOMAIN(LoadTime, "ov::LoadTime");
// Domain used for marking phases in the runtime
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment is not descriptive. "Phases" of which process are being marked here?

// DO NOT MODIFY OR DELETE!
OV_ITT_DOMAIN(Phases, "ov::phases");
} // namespace domains
} // namespace itt
} // namespace ov
Expand Down
5 changes: 2 additions & 3 deletions src/plugins/intel_cpu/src/infer_request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ SyncInferRequest::SyncInferRequest(CompiledModelHolder compiled_model)
}

void SyncInferRequest::create_infer_request() {
m_profiling_task = openvino::itt::handle("INTEL_CPU_INFER_" + m_compiled_model.name() + "_" +
m_profiling_task = openvino::itt::handle("SyncInferenceCPU::" + m_compiled_model.name() + ":" +
std::to_string(m_compiled_model.id()));

// Alocate memory for each tensor if static shape
Expand Down Expand Up @@ -103,8 +103,7 @@ void SyncInferRequest::update_external_tensor_ptrs() {
}

void SyncInferRequest::infer() {
OV_ITT_SCOPED_REGION_BASE(itt::domains::ov_intel_cpu,
std::string("SyncInferenceRequest:") + m_compiled_model.name());
OV_ITT_SCOPED_REGION_BASE(itt::domains::ov_intel_cpu, m_profiling_task);
auto graphLock = m_compiled_model.lock();
auto&& graph = graphLock._graph;
auto message = ov::threading::message_manager();
Expand Down