diff --git a/level_zero/tools/source/metrics/linux/os_metric_query_imp_linux.cpp b/level_zero/tools/source/metrics/linux/os_metric_query_imp_linux.cpp index 9d066e4375..1951a8b3a2 100644 --- a/level_zero/tools/source/metrics/linux/os_metric_query_imp_linux.cpp +++ b/level_zero/tools/source/metrics/linux/os_metric_query_imp_linux.cpp @@ -44,4 +44,12 @@ bool MetricsLibrary::deactivateConfiguration(const ConfigurationHandle_1_0 confi return result; } +void MetricsLibrary::cacheConfiguration(zet_metric_group_handle_t metricGroup, ConfigurationHandle_1_0 configurationHandle) { + // Linux does not support configuration cache. + // Any previous configuration should be deleted. + deleteAllConfigurations(); + + // Cache only a single configuration. + configurations[metricGroup] = configurationHandle; +} } // namespace L0 diff --git a/level_zero/tools/source/metrics/metric.cpp b/level_zero/tools/source/metrics/metric.cpp index 086621077e..b7a3a72ace 100644 --- a/level_zero/tools/source/metrics/metric.cpp +++ b/level_zero/tools/source/metrics/metric.cpp @@ -357,9 +357,8 @@ ze_result_t metricGroupGet(zet_device_handle_t hDevice, uint32_t *pCount, zet_me ze_result_t metricTracerOpen(zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup, zet_metric_tracer_desc_t *pDesc, ze_event_handle_t hNotificationEvent, zet_metric_tracer_handle_t *phMetricTracer) { - *phMetricTracer = MetricTracer::open(hDevice, hMetricGroup, *pDesc, hNotificationEvent); - return (*phMetricTracer != nullptr) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN; + return MetricTracer::open(hDevice, hMetricGroup, *pDesc, hNotificationEvent, phMetricTracer); } } // namespace L0 diff --git a/level_zero/tools/source/metrics/metric.h b/level_zero/tools/source/metrics/metric.h index 6651373d87..21835a92a7 100644 --- a/level_zero/tools/source/metrics/metric.h +++ b/level_zero/tools/source/metrics/metric.h @@ -104,8 +104,8 @@ struct MetricTracer : _zet_metric_tracer_handle_t { uint8_t *pRawData) = 0; virtual ze_result_t close() = 0; - static MetricTracer *open(zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup, - zet_metric_tracer_desc_t &desc, ze_event_handle_t hNotificationEvent); + static ze_result_t open(zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup, + zet_metric_tracer_desc_t &desc, ze_event_handle_t hNotificationEvent, zet_metric_tracer_handle_t *phMetricTracer); static MetricTracer *fromHandle(zet_metric_tracer_handle_t handle) { return static_cast(handle); } diff --git a/level_zero/tools/source/metrics/metric_query_imp.cpp b/level_zero/tools/source/metrics/metric_query_imp.cpp index 259591b9bd..9169f85b7f 100644 --- a/level_zero/tools/source/metrics/metric_query_imp.cpp +++ b/level_zero/tools/source/metrics/metric_query_imp.cpp @@ -28,20 +28,7 @@ MetricsLibrary::MetricsLibrary(MetricContext &metricContextInput) : metricContext(metricContextInput) {} MetricsLibrary::~MetricsLibrary() { - // Delete all metric group configurations. - for (auto &configuration : configurations) { - if (configuration.second.IsValid()) { - api.ConfigurationDelete(configuration.second); - } - } - - configurations.clear(); - - // Destroy context. - if (context.IsValid() && contextDeleteFunction) { - contextDeleteFunction(context); - context = {}; - } + release(); } bool MetricsLibrary::isInitialized() { @@ -55,6 +42,8 @@ bool MetricsLibrary::isInitialized() { bool MetricsLibrary::createMetricQuery(const uint32_t slotsCount, QueryHandle_1_0 &query, NEO::GraphicsAllocation *&pAllocation) { + std::lock_guard lock(mutex); + // Validate metrics library state. if (!isInitialized()) { DEBUG_BREAK_IF(true); @@ -99,14 +88,36 @@ bool MetricsLibrary::createMetricQuery(const uint32_t slotsCount, QueryHandle_1_ return false; } + // Register created query. + queries.push_back(query); + return true; } +uint32_t MetricsLibrary::getMetricQueryCount() { + std::lock_guard lock(mutex); + return static_cast(queries.size()); +} + bool MetricsLibrary::destroyMetricQuery(QueryHandle_1_0 &query) { + std::lock_guard lock(mutex); DEBUG_BREAK_IF(!query.IsValid()); const bool result = isInitialized() && (api.QueryDelete(query) == StatusCode::Success); - DEBUG_BREAK_IF(!result); + auto iter = std::find_if(queries.begin(), queries.end(), [&](const QueryHandle_1_0 &element) { return element.data == query.data; }); + + // Unregister query. + if (iter != queries.end()) { + queries.erase(iter); + } + + // Unload metrics library if there are no active queries. + // It will allow to open metric tracer. Query and tracer cannot be used + // simultaneously since they use the same exclusive resource (oa buffer). + if (queries.size() == 0) { + release(); + } + return result; } @@ -151,6 +162,23 @@ void MetricsLibrary::initialize() { DEBUG_BREAK_IF(initializationState != ZE_RESULT_SUCCESS); } +void MetricsLibrary::release() { + + // Delete metric group configurations. + deleteAllConfigurations(); + + // Destroy context. + if (context.IsValid() && contextDeleteFunction) { + contextDeleteFunction(context); + } + + // Reset metric query state to not initialized. + api = {}; + callbacks = {}; + context = {}; + initializationState = ZE_RESULT_ERROR_UNINITIALIZED; +} + bool MetricsLibrary::load() { // Load library. handle = NEO::OsLibrary::load(getFilename()); @@ -320,15 +348,38 @@ ConfigurationHandle_1_0 MetricsLibrary::addConfiguration(zet_metric_group_handle // Cache configuration if valid. if (configuration.IsValid()) { libraryHandle = configuration; - configurations[handle] = libraryHandle; + cacheConfiguration(handle, libraryHandle); } DEBUG_BREAK_IF(!libraryHandle.IsValid()); return libraryHandle; } +void MetricsLibrary::deleteAllConfigurations() { + + if (api.ConfigurationDelete) { + for (auto &configuration : configurations) { + if (configuration.second.IsValid()) { + api.ConfigurationDelete(configuration.second); + } + } + } + + configurations.clear(); +} + ze_result_t metricQueryPoolCreate(zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup, const zet_metric_query_pool_desc_t *pDesc, zet_metric_query_pool_handle_t *phMetricQueryPool) { + + auto device = Device::fromHandle(hDevice); + auto &metricContext = device->getMetricContext(); + + // Metric query cannot be used with tracer simultaneously + // (due to oa buffer usage constraints). + if (metricContext.getMetricTracer() != nullptr) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + // Create metric query pool *phMetricQueryPool = MetricQueryPool::create(hDevice, hMetricGroup, *pDesc); diff --git a/level_zero/tools/source/metrics/metric_query_imp.h b/level_zero/tools/source/metrics/metric_query_imp.h index d98362f687..dad708f3f6 100644 --- a/level_zero/tools/source/metrics/metric_query_imp.h +++ b/level_zero/tools/source/metrics/metric_query_imp.h @@ -48,6 +48,7 @@ struct MetricsLibrary { // Metric query. bool createMetricQuery(const uint32_t slotsCount, QueryHandle_1_0 &query, NEO::GraphicsAllocation *&pAllocation); + uint32_t getMetricQueryCount(); bool getMetricQueryReport(QueryHandle_1_0 &query, const size_t rawDataSize, uint8_t *pData); virtual bool getMetricQueryReportSize(size_t &rawDataSize); bool destroyMetricQuery(QueryHandle_1_0 &query); @@ -60,9 +61,12 @@ struct MetricsLibrary { ConfigurationHandle_1_0 getConfiguration(const zet_metric_group_handle_t metricGroup); bool activateConfiguration(const ConfigurationHandle_1_0 configurationHandle); bool deactivateConfiguration(const ConfigurationHandle_1_0 configurationHandle); + void cacheConfiguration(zet_metric_group_handle_t metricGroup, ConfigurationHandle_1_0 configurationHandle); + void deleteAllConfigurations(); protected: void initialize(); + void release(); bool createContext(); virtual bool getContextData(Device &device, ContextCreateData_1_0 &contextData); @@ -77,6 +81,7 @@ struct MetricsLibrary { NEO::OsLibrary *handle = nullptr; MetricContext &metricContext; ze_result_t initializationState = ZE_RESULT_ERROR_UNINITIALIZED; + std::mutex mutex; // Metrics library types. Interface_1_0 api = {}; @@ -84,8 +89,8 @@ struct MetricsLibrary { ContextHandle_1_0 context = {}; ContextCreateFunction_1_0 contextCreateFunction = nullptr; ContextDeleteFunction_1_0 contextDeleteFunction = nullptr; - // MetricGroup configurations std::map configurations; + std::vector queries; }; struct MetricQueryImp : MetricQuery { diff --git a/level_zero/tools/source/metrics/metric_tracer_imp.cpp b/level_zero/tools/source/metrics/metric_tracer_imp.cpp index aba39d21e4..08b9048c15 100644 --- a/level_zero/tools/source/metrics/metric_tracer_imp.cpp +++ b/level_zero/tools/source/metrics/metric_tracer_imp.cpp @@ -10,6 +10,7 @@ #include "shared/source/helpers/debug_helpers.h" #include "level_zero/core/source/device/device.h" +#include "level_zero/tools/source/metrics/metric_query_imp.h" namespace L0 { @@ -137,25 +138,34 @@ uint32_t MetricTracerImp::getRequiredBufferSize(const uint32_t maxReportCount) c : maxReportCount * rawReportSize; } -MetricTracer *MetricTracer::open(zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup, - zet_metric_tracer_desc_t &desc, ze_event_handle_t hNotificationEvent) { +ze_result_t MetricTracer::open(zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup, + zet_metric_tracer_desc_t &desc, ze_event_handle_t hNotificationEvent, + zet_metric_tracer_handle_t *phMetricTracer) { auto pDevice = Device::fromHandle(hDevice); auto &metricContext = pDevice->getMetricContext(); + *phMetricTracer = nullptr; + // Check whether metric tracer is already open. if (metricContext.getMetricTracer() != nullptr) { - return nullptr; + return ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE; + } + + // Metric tracer cannot be used with query simultaneously + // (oa buffer cannot be shared). + if (metricContext.getMetricsLibrary().getMetricQueryCount() > 0) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; } // Check metric group sampling type. auto metricGroupProperties = MetricGroup::getProperties(hMetricGroup); if (metricGroupProperties.samplingType != ZET_METRIC_GROUP_SAMPLING_TYPE_TIME_BASED) { - return nullptr; + return ZE_RESULT_ERROR_INVALID_ARGUMENT; } // Check whether metric group is activated. if (!metricContext.isMetricGroupActivated(hMetricGroup)) { - return nullptr; + return ZE_RESULT_NOT_READY; } auto pMetricTracer = new MetricTracerImp(); @@ -169,9 +179,11 @@ MetricTracer *MetricTracer::open(zet_device_handle_t hDevice, zet_metric_group_h } else { delete pMetricTracer; pMetricTracer = nullptr; + return ZE_RESULT_ERROR_UNKNOWN; } - return pMetricTracer; + *phMetricTracer = pMetricTracer->toHandle(); + return ZE_RESULT_SUCCESS; } } // namespace L0 diff --git a/level_zero/tools/source/metrics/windows/os_metric_query_imp_windows.cpp b/level_zero/tools/source/metrics/windows/os_metric_query_imp_windows.cpp index 2aaa23ad64..4c9eaabc2c 100644 --- a/level_zero/tools/source/metrics/windows/os_metric_query_imp_windows.cpp +++ b/level_zero/tools/source/metrics/windows/os_metric_query_imp_windows.cpp @@ -64,4 +64,7 @@ bool MetricsLibrary::deactivateConfiguration(const ConfigurationHandle_1_0 confi return result; } +void MetricsLibrary::cacheConfiguration(zet_metric_group_handle_t metricGroup, ConfigurationHandle_1_0 configurationHandle) { + configurations[metricGroup] = configurationHandle; +} } // namespace L0