400 lines
14 KiB
C++
400 lines
14 KiB
C++
/*
|
|
* Copyright (C) 2019-2021 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
|
|
#include "level_zero/tools/source/metrics/metric.h"
|
|
|
|
#include "shared/source/os_interface/os_library.h"
|
|
|
|
#include "level_zero/core/source/device/device.h"
|
|
#include "level_zero/core/source/driver/driver.h"
|
|
#include "level_zero/core/source/driver/driver_handle_imp.h"
|
|
#include "level_zero/source/inc/ze_intel_gpu.h"
|
|
#include "level_zero/tools/source/metrics/metric_enumeration_imp.h"
|
|
#include "level_zero/tools/source/metrics/metric_query_imp.h"
|
|
|
|
#include <map>
|
|
#include <utility>
|
|
|
|
namespace L0 {
|
|
|
|
struct MetricGroupDomains {
|
|
|
|
public:
|
|
MetricGroupDomains(MetricContext &metricContext);
|
|
ze_result_t activateDeferred(const uint32_t count, zet_metric_group_handle_t *phMetricGroups);
|
|
ze_result_t activate();
|
|
ze_result_t deactivate();
|
|
bool isActivated(const zet_metric_group_handle_t hMetricGroup);
|
|
|
|
protected:
|
|
bool activateMetricGroupDeferred(const zet_metric_group_handle_t hMetricGroup);
|
|
bool activateEventMetricGroup(const zet_metric_group_handle_t hMetricGroup);
|
|
|
|
protected:
|
|
MetricsLibrary &metricsLibrary;
|
|
|
|
// Map holds activated domains and associated metric groups.
|
|
// Content: <domain number, pair<metric group, is activated on gpu flag>
|
|
std::map<uint32_t, std::pair<zet_metric_group_handle_t, bool>> domains;
|
|
};
|
|
|
|
struct MetricContextImp : public MetricContext {
|
|
public:
|
|
MetricContextImp(Device &device);
|
|
~MetricContextImp() override;
|
|
|
|
bool loadDependencies() override;
|
|
bool isInitialized() override;
|
|
void setInitializationState(const ze_result_t state) override;
|
|
Device &getDevice() override;
|
|
MetricsLibrary &getMetricsLibrary() override;
|
|
MetricEnumeration &getMetricEnumeration() override;
|
|
MetricStreamer *getMetricStreamer() override;
|
|
void setMetricStreamer(MetricStreamer *pMetricStreamer) override;
|
|
void setMetricsLibrary(MetricsLibrary &metricsLibrary) override;
|
|
void setMetricEnumeration(MetricEnumeration &metricEnumeration) override;
|
|
|
|
ze_result_t activateMetricGroups() override;
|
|
ze_result_t activateMetricGroupsDeferred(const uint32_t count,
|
|
zet_metric_group_handle_t *phMetricGroups) override;
|
|
bool isMetricGroupActivated(const zet_metric_group_handle_t hMetricGroup) override;
|
|
|
|
void setUseCompute(const bool useCompute) override;
|
|
bool isComputeUsed() override;
|
|
uint32_t getSubDeviceIndex() override;
|
|
void setSubDeviceIndex(const uint32_t index) override;
|
|
|
|
protected:
|
|
ze_result_t initializationState = ZE_RESULT_ERROR_UNINITIALIZED;
|
|
struct Device &device;
|
|
std::unique_ptr<MetricEnumeration> metricEnumeration = nullptr;
|
|
std::unique_ptr<MetricsLibrary> metricsLibrary = nullptr;
|
|
MetricGroupDomains metricGroupDomains;
|
|
MetricStreamer *pMetricStreamer = nullptr;
|
|
uint32_t subDeviceIndex = 0;
|
|
bool useCompute = false;
|
|
};
|
|
|
|
MetricContextImp::MetricContextImp(Device &deviceInput)
|
|
: device(deviceInput),
|
|
metricEnumeration(std::unique_ptr<MetricEnumeration>(new (std::nothrow) MetricEnumeration(*this))),
|
|
metricsLibrary(std::unique_ptr<MetricsLibrary>(new (std::nothrow) MetricsLibrary(*this))),
|
|
metricGroupDomains(*this) {
|
|
|
|
auto deviceNeo = deviceInput.getNEODevice();
|
|
bool isSubDevice = deviceNeo->getParentDevice() != nullptr;
|
|
|
|
subDeviceIndex = isSubDevice
|
|
? static_cast<NEO::SubDevice *>(deviceNeo)->getSubDeviceIndex()
|
|
: 0;
|
|
}
|
|
|
|
MetricContextImp::~MetricContextImp() {
|
|
metricsLibrary.reset();
|
|
metricEnumeration.reset();
|
|
}
|
|
|
|
bool MetricContextImp::loadDependencies() {
|
|
bool result = true;
|
|
if (metricEnumeration->loadMetricsDiscovery() != ZE_RESULT_SUCCESS) {
|
|
result = false;
|
|
DEBUG_BREAK_IF(!result);
|
|
}
|
|
if (result && !metricsLibrary->load()) {
|
|
result = false;
|
|
DEBUG_BREAK_IF(!result);
|
|
}
|
|
|
|
// Set metric context initialization state.
|
|
setInitializationState(result
|
|
? ZE_RESULT_SUCCESS
|
|
: ZE_RESULT_ERROR_UNKNOWN);
|
|
|
|
return result;
|
|
}
|
|
|
|
bool MetricContextImp::isInitialized() {
|
|
return initializationState == ZE_RESULT_SUCCESS;
|
|
}
|
|
|
|
void MetricContextImp::setInitializationState(const ze_result_t state) {
|
|
initializationState = state;
|
|
}
|
|
|
|
Device &MetricContextImp::getDevice() { return device; }
|
|
|
|
MetricsLibrary &MetricContextImp::getMetricsLibrary() { return *metricsLibrary; }
|
|
|
|
MetricEnumeration &MetricContextImp::getMetricEnumeration() { return *metricEnumeration; }
|
|
|
|
MetricStreamer *MetricContextImp::getMetricStreamer() { return pMetricStreamer; }
|
|
|
|
void MetricContextImp::setMetricStreamer(MetricStreamer *pMetricStreamer) {
|
|
this->pMetricStreamer = pMetricStreamer;
|
|
}
|
|
|
|
void MetricContextImp::setMetricsLibrary(MetricsLibrary &metricsLibrary) {
|
|
this->metricsLibrary.release();
|
|
this->metricsLibrary.reset(&metricsLibrary);
|
|
}
|
|
|
|
void MetricContextImp::setMetricEnumeration(MetricEnumeration &metricEnumeration) {
|
|
this->metricEnumeration.release();
|
|
this->metricEnumeration.reset(&metricEnumeration);
|
|
}
|
|
|
|
void MetricContextImp::setUseCompute(const bool useCompute) {
|
|
this->useCompute = useCompute;
|
|
}
|
|
|
|
bool MetricContextImp::isComputeUsed() {
|
|
return useCompute;
|
|
}
|
|
|
|
uint32_t MetricContextImp::getSubDeviceIndex() {
|
|
return subDeviceIndex;
|
|
}
|
|
|
|
void MetricContextImp::setSubDeviceIndex(const uint32_t index) {
|
|
subDeviceIndex = index;
|
|
}
|
|
|
|
ze_result_t
|
|
MetricContextImp::activateMetricGroupsDeferred(const uint32_t count,
|
|
zet_metric_group_handle_t *phMetricGroups) {
|
|
|
|
// Activation: postpone until zetMetricStreamerOpen or zeCommandQueueExecuteCommandLists
|
|
// Deactivation: execute immediately.
|
|
return phMetricGroups ? metricGroupDomains.activateDeferred(count, phMetricGroups)
|
|
: metricGroupDomains.deactivate();
|
|
}
|
|
|
|
bool MetricContextImp::isMetricGroupActivated(const zet_metric_group_handle_t hMetricGroup) {
|
|
return metricGroupDomains.isActivated(hMetricGroup);
|
|
}
|
|
|
|
ze_result_t MetricContextImp::activateMetricGroups() { return metricGroupDomains.activate(); }
|
|
|
|
ze_result_t MetricContext::enableMetricApi() {
|
|
|
|
if (!isMetricApiAvailable()) {
|
|
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
|
|
}
|
|
|
|
bool failed = false;
|
|
|
|
uint32_t rootDeviceCount = 0;
|
|
uint32_t subDeviceCount = 0;
|
|
|
|
auto driverHandle = L0::DriverHandle::fromHandle(GlobalDriverHandle);
|
|
auto rootDevices = std::vector<ze_device_handle_t>();
|
|
auto subDevices = std::vector<ze_device_handle_t>();
|
|
|
|
// Obtain root devices.
|
|
driverHandle->getDevice(&rootDeviceCount, nullptr);
|
|
rootDevices.resize(rootDeviceCount);
|
|
driverHandle->getDevice(&rootDeviceCount, rootDevices.data());
|
|
|
|
for (auto rootDeviceHandle : rootDevices) {
|
|
|
|
// Initialize root device.
|
|
auto rootDevice = L0::Device::fromHandle(rootDeviceHandle);
|
|
failed |= !rootDevice->getMetricContext().loadDependencies();
|
|
|
|
// Sub devices count.
|
|
subDeviceCount = 0;
|
|
rootDevice->getSubDevices(&subDeviceCount, nullptr);
|
|
|
|
// Sub device instances.
|
|
subDevices.clear();
|
|
subDevices.resize(subDeviceCount);
|
|
rootDevice->getSubDevices(&subDeviceCount, subDevices.data());
|
|
|
|
// Initialize sub devices.
|
|
for (uint32_t i = 0; i < subDevices.size(); ++i) {
|
|
|
|
auto subDevice = L0::Device::fromHandle(subDevices[i]);
|
|
failed |= !subDevice->getMetricContext().loadDependencies();
|
|
}
|
|
}
|
|
|
|
return failed
|
|
? ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE
|
|
: ZE_RESULT_SUCCESS;
|
|
}
|
|
|
|
std::unique_ptr<MetricContext> MetricContext::create(Device &device) {
|
|
auto metricContextImp = new (std::nothrow) MetricContextImp(device);
|
|
std::unique_ptr<MetricContext> metricContext{metricContextImp};
|
|
return metricContext;
|
|
}
|
|
|
|
bool MetricContext::isMetricApiAvailable() {
|
|
|
|
std::unique_ptr<NEO::OsLibrary> library = nullptr;
|
|
|
|
// Check Metrics Discovery availability.
|
|
library.reset(NEO::OsLibrary::load(MetricEnumeration::getMetricsDiscoveryFilename()));
|
|
if (library == nullptr) {
|
|
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Unable to find metrics discovery %s\n", MetricEnumeration::getMetricsDiscoveryFilename());
|
|
return false;
|
|
}
|
|
|
|
// Check Metrics Library availability.
|
|
library.reset(NEO::OsLibrary::load(MetricsLibrary::getFilename()));
|
|
if (library == nullptr) {
|
|
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Unable to find metrics library %s\n", MetricsLibrary::getFilename());
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
MetricGroupDomains::MetricGroupDomains(MetricContext &metricContext)
|
|
: metricsLibrary(metricContext.getMetricsLibrary()) {}
|
|
|
|
ze_result_t MetricGroupDomains::activateDeferred(const uint32_t count,
|
|
zet_metric_group_handle_t *phMetricGroups) {
|
|
// For each metric group:
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
DEBUG_BREAK_IF(!phMetricGroups[i]);
|
|
|
|
// Try to associate it with a domain (oa, ...).
|
|
if (!activateMetricGroupDeferred(phMetricGroups[i])) {
|
|
return ZE_RESULT_ERROR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
}
|
|
|
|
bool MetricGroupDomains::activateMetricGroupDeferred(const zet_metric_group_handle_t hMetricGroup) {
|
|
|
|
const auto properites = MetricGroup::getProperties(hMetricGroup);
|
|
const auto domain = properites.domain;
|
|
|
|
const bool isDomainFree = domains[domain].first == nullptr;
|
|
const bool isSameGroup = domains[domain].first == hMetricGroup;
|
|
|
|
// The same metric group has been already associated.
|
|
if (isSameGroup) {
|
|
return true;
|
|
}
|
|
|
|
// Domain has been already associated with a different metric group.
|
|
if (!isDomainFree) {
|
|
return false;
|
|
}
|
|
|
|
// Associate metric group with domain and mark it as not active.
|
|
// Activation will be performed during zeCommandQueueExecuteCommandLists (query)
|
|
// or zetMetricStreamerOpen (time based sampling).
|
|
domains[domain].first = hMetricGroup;
|
|
domains[domain].second = false;
|
|
|
|
return true;
|
|
}
|
|
|
|
ze_result_t MetricGroupDomains::activate() {
|
|
|
|
// For each domain.
|
|
for (auto &domain : domains) {
|
|
|
|
auto hMetricGroup = domain.second.first;
|
|
bool &metricGroupActive = domain.second.second;
|
|
bool metricGroupEventBased =
|
|
hMetricGroup && MetricGroup::getProperties(hMetricGroup).samplingType ==
|
|
ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_EVENT_BASED;
|
|
|
|
// Activate only event based metric groups.
|
|
// Time based metric group will be activated during zetMetricStreamerOpen.
|
|
if (metricGroupEventBased && !metricGroupActive) {
|
|
|
|
metricGroupActive = activateEventMetricGroup(hMetricGroup);
|
|
|
|
if (metricGroupActive == false) {
|
|
DEBUG_BREAK_IF(true);
|
|
return ZE_RESULT_ERROR_UNKNOWN;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
}
|
|
|
|
bool MetricGroupDomains::activateEventMetricGroup(const zet_metric_group_handle_t hMetricGroup) {
|
|
// Obtain metric group configuration handle from metrics library.
|
|
auto hConfiguration = metricsLibrary.getConfiguration(hMetricGroup);
|
|
|
|
// Validate metrics library handle.
|
|
if (!hConfiguration.IsValid()) {
|
|
DEBUG_BREAK_IF(true);
|
|
return false;
|
|
}
|
|
|
|
// Write metric group configuration to gpu.
|
|
const bool result = metricsLibrary.activateConfiguration(hConfiguration);
|
|
|
|
DEBUG_BREAK_IF(!result);
|
|
return result;
|
|
}
|
|
|
|
ze_result_t MetricGroupDomains::deactivate() {
|
|
// Deactivate metric group for each domain.
|
|
for (auto &domain : domains) {
|
|
|
|
auto hMetricGroup = domain.second.first;
|
|
auto metricGroup = MetricGroup::fromHandle(hMetricGroup);
|
|
bool metricGroupActivated = domain.second.second;
|
|
auto metricGroupEventBased = (metricGroup != nullptr)
|
|
? MetricGroup::getProperties(hMetricGroup).samplingType == ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_EVENT_BASED
|
|
: false;
|
|
auto hConfigurationEmpty = ConfigurationHandle_1_0{};
|
|
auto hConfiguration = metricGroupEventBased
|
|
? metricsLibrary.getConfiguration(hMetricGroup)
|
|
: hConfigurationEmpty;
|
|
|
|
// Deactivate metric group configuration using metrics library.
|
|
if (hConfiguration.IsValid() && metricGroupActivated) {
|
|
metricsLibrary.deactivateConfiguration(hConfiguration);
|
|
}
|
|
|
|
// Mark domain as free.
|
|
domain.second = {};
|
|
}
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
}
|
|
|
|
bool MetricGroupDomains::isActivated(const zet_metric_group_handle_t hMetricGroup) {
|
|
auto metricGroupProperties = MetricGroup::getProperties(hMetricGroup);
|
|
|
|
// 1. Check whether domain is activated.
|
|
const auto domain = domains.find(metricGroupProperties.domain);
|
|
if (domain == domains.end()) {
|
|
return false;
|
|
}
|
|
|
|
// 2. Check whether the specific MetricGroup is activated.
|
|
return domain->second.first == hMetricGroup;
|
|
}
|
|
|
|
ze_result_t metricGroupGet(zet_device_handle_t hDevice, uint32_t *pCount, zet_metric_group_handle_t *phMetricGroups) {
|
|
auto device = Device::fromHandle(hDevice);
|
|
return device->getMetricContext().getMetricEnumeration().metricGroupGet(*pCount,
|
|
phMetricGroups);
|
|
}
|
|
|
|
ze_result_t metricStreamerOpen(zet_context_handle_t hContext, zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup,
|
|
zet_metric_streamer_desc_t *pDesc, ze_event_handle_t hNotificationEvent,
|
|
zet_metric_streamer_handle_t *phMetricStreamer) {
|
|
|
|
return MetricStreamer::open(hContext, hDevice, hMetricGroup, *pDesc, hNotificationEvent, phMetricStreamer);
|
|
}
|
|
|
|
} // namespace L0
|