compute-runtime/level_zero/tools/source/metrics/metric_enumeration_imp.cpp

797 lines
30 KiB
C++

/*
* Copyright (C) 2020-2021 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/tools/source/metrics/metric_enumeration_imp.h"
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/helpers/string.h"
#include "shared/source/os_interface/os_library.h"
#include "level_zero/core/source/device/device_imp.h"
#include <algorithm>
namespace L0 {
const char *MetricEnumeration::oaConcurrentGroupName = "OA";
MetricEnumeration::MetricEnumeration(MetricContext &metricContextInput)
: metricContext(metricContextInput) {}
MetricEnumeration::~MetricEnumeration() {
cleanupMetricsDiscovery();
initializationState = ZE_RESULT_ERROR_UNINITIALIZED;
}
ze_result_t MetricEnumeration::metricGroupGet(uint32_t &count,
zet_metric_group_handle_t *phMetricGroups) {
ze_result_t result = initialize();
if (result != ZE_RESULT_SUCCESS) {
return result;
}
if (count == 0) {
count = static_cast<uint32_t>(metricGroups.size());
return ZE_RESULT_SUCCESS;
} else if (count > metricGroups.size()) {
count = static_cast<uint32_t>(metricGroups.size());
}
for (uint32_t i = 0; i < count; i++) {
phMetricGroups[i] = metricGroups[i]->toHandle();
}
return ZE_RESULT_SUCCESS;
}
MetricGroup *MetricEnumeration::getMetricGroupByIndex(const uint32_t index) {
return metricGroups[index];
}
uint32_t MetricEnumeration::getMetricGroupCount() {
return static_cast<uint32_t>(metricGroups.size());
}
bool MetricEnumeration::isInitialized() {
if (initializationState == ZE_RESULT_ERROR_UNINITIALIZED) {
initialize();
}
return initializationState == ZE_RESULT_SUCCESS;
}
ze_result_t MetricEnumeration::initialize() {
if (initializationState == ZE_RESULT_ERROR_UNINITIALIZED) {
if (!this->metricContext.getMetricCollectionEnabled()) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "%s",
"metrics collection is disabled on the root device\n");
initializationState = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
} else if (hMetricsDiscovery &&
openMetricsDiscovery() == ZE_RESULT_SUCCESS &&
cacheMetricInformation() == ZE_RESULT_SUCCESS) {
initializationState = ZE_RESULT_SUCCESS;
} else {
initializationState = ZE_RESULT_ERROR_UNKNOWN;
cleanupMetricsDiscovery();
}
}
return initializationState;
}
ze_result_t MetricEnumeration::loadMetricsDiscovery() {
// Load library.
hMetricsDiscovery.reset(NEO::OsLibrary::load(getMetricsDiscoveryFilename()));
// Load exported functions.
if (hMetricsDiscovery) {
openAdapterGroup = reinterpret_cast<MetricsDiscovery::OpenAdapterGroup_fn>(
hMetricsDiscovery->getProcAddress("OpenAdapterGroup"));
}
if (openAdapterGroup == nullptr) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "cannot load %s exported functions\n", MetricEnumeration::getMetricsDiscoveryFilename());
cleanupMetricsDiscovery();
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
// Return success if exported functions have been loaded.
return ZE_RESULT_SUCCESS;
}
ze_result_t MetricEnumeration::openMetricsDiscovery() {
UNRECOVERABLE_IF(openAdapterGroup == nullptr);
const uint32_t subDeviceIndex = metricContext.getSubDeviceIndex();
// Clean up members.
pAdapterGroup = nullptr;
pAdapter = nullptr;
pMetricsDevice = nullptr;
// Open adapter group.
openAdapterGroup(&pAdapterGroup);
if (pAdapterGroup == nullptr) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "unable to open metrics adapter groups %s\n", " ");
cleanupMetricsDiscovery();
return ZE_RESULT_ERROR_UNKNOWN;
}
// Obtain metrics adapter that matches adapter used by l0.
pAdapter = getMetricsAdapter();
if (pAdapter == nullptr) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "unable to open metrics adapter %s\n", " ");
cleanupMetricsDiscovery();
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
auto &device = metricContext.getDevice();
if (device.isMultiDeviceCapable()) {
// Open metrics device for each sub device.
const auto &deviceImp = *static_cast<DeviceImp *>(&device);
for (size_t i = 0; i < deviceImp.subDevices.size(); i++) {
auto &metricsDevice = deviceImp.subDevices[i]->getMetricContext().getMetricEnumeration().pMetricsDevice;
pAdapter->OpenMetricsSubDevice(static_cast<uint32_t>(i), &metricsDevice);
if (metricsDevice == nullptr) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "unable to open metrics device %u\n", i);
cleanupMetricsDiscovery();
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
}
} else {
if (subDeviceIndex == 0) {
// Open metrics device for root device or sub device with index 0.
pAdapter->OpenMetricsDevice(&pMetricsDevice);
} else {
// Open metrics device for a given sub device index.
pAdapter->OpenMetricsSubDevice(subDeviceIndex, &pMetricsDevice);
}
if (pMetricsDevice == nullptr) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "unable to open metrics device %u\n", subDeviceIndex);
cleanupMetricsDiscovery();
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
}
return ZE_RESULT_SUCCESS;
}
ze_result_t MetricEnumeration::cleanupMetricsDiscovery() {
if (pAdapter) {
auto &device = metricContext.getDevice();
if (device.isMultiDeviceCapable()) {
// Close metrics device for each sub device.
const auto &deviceImp = *static_cast<DeviceImp *>(&device);
for (size_t i = 0; i < deviceImp.subDevices.size(); i++) {
auto &metricsDevice = deviceImp.subDevices[i]->getMetricContext().getMetricEnumeration().pMetricsDevice;
if (metricsDevice) {
pAdapter->CloseMetricsDevice(metricsDevice);
metricsDevice = nullptr;
}
auto &metricGroupsSubDevice = deviceImp.subDevices[i]->getMetricContext().getMetricEnumeration().metricGroups;
for (size_t j = 0; j < metricGroupsSubDevice.size(); ++j) {
auto metricGroupSubDevice = MetricGroup::fromHandle(metricGroupsSubDevice[j]);
delete metricGroupSubDevice;
}
metricGroupsSubDevice.clear();
}
} else if (pMetricsDevice) {
// Close metrics device for one sub device or root device.
pAdapter->CloseMetricsDevice(pMetricsDevice);
pMetricsDevice = nullptr;
}
}
for (size_t i = 0; i < metricGroups.size(); ++i) {
delete metricGroups[i];
}
metricGroups.clear();
if (hMetricsDiscovery != nullptr) {
openAdapterGroup = nullptr;
hMetricsDiscovery.reset();
}
return ZE_RESULT_SUCCESS;
}
ze_result_t MetricEnumeration::cacheMetricInformation() {
auto &device = metricContext.getDevice();
if (device.isMultiDeviceCapable()) {
ze_result_t result = ZE_RESULT_SUCCESS;
// Get metric information from all sub devices.
const auto &deviceImp = *static_cast<DeviceImp *>(&device);
for (auto subDevice : deviceImp.subDevices) {
result = subDevice->getMetricContext().getMetricEnumeration().cacheMetricInformation();
if (ZE_RESULT_SUCCESS != result) {
return result;
}
}
// Get metric groups count for one sub device.
const uint32_t metricGroupCount = deviceImp.subDevices[0]->getMetricContext().getMetricEnumeration().getMetricGroupCount();
// Cache and aggregate all metric groups from all sub devices.
for (uint32_t i = 0; i < metricGroupCount; i++) {
auto metricGroupRootDevice = new MetricGroupImp();
for (auto subDevice : deviceImp.subDevices) {
MetricGroup *metricGroupSubDevice = subDevice->getMetricContext().getMetricEnumeration().getMetricGroupByIndex(i);
metricGroupRootDevice->getMetricGroups().push_back(metricGroupSubDevice);
}
metricGroups.push_back(metricGroupRootDevice);
}
return result;
}
DEBUG_BREAK_IF(pMetricsDevice == nullptr);
MetricsDiscovery::TMetricsDeviceParams_1_2 *pMetricsDeviceParams = pMetricsDevice->GetParams();
DEBUG_BREAK_IF(pMetricsDeviceParams == nullptr);
// Check required Metrics Discovery API version - should be at least 1.5.
const bool unsupportedMajorVersion =
pMetricsDeviceParams->Version.MajorNumber < requiredMetricsDiscoveryMajorVersion;
const bool unsupportedMinorVersion =
(pMetricsDeviceParams->Version.MajorNumber == requiredMetricsDiscoveryMajorVersion) &&
(pMetricsDeviceParams->Version.MinorNumber < requiredMetricsDiscoveryMinorVersion);
if (unsupportedMajorVersion || unsupportedMinorVersion) {
// Metrics Discovery API version too low
return ZE_RESULT_ERROR_UNKNOWN;
}
// 1. Iterate over concurrent groups.
MetricsDiscovery::IConcurrentGroup_1_5 *pConcurrentGroup = nullptr;
for (uint32_t i = 0; i < pMetricsDeviceParams->ConcurrentGroupsCount; ++i) {
pConcurrentGroup = pMetricsDevice->GetConcurrentGroup(i);
DEBUG_BREAK_IF(pConcurrentGroup == nullptr);
MetricsDiscovery::TConcurrentGroupParams_1_0 *pConcurrentGroupParams =
pConcurrentGroup->GetParams();
DEBUG_BREAK_IF(pConcurrentGroupParams == nullptr);
// 2. Find "OA" concurrent group.
if (strcmp(pConcurrentGroupParams->SymbolName, oaConcurrentGroupName) == 0) {
// Reserve memory for metric groups
metricGroups.reserve(pConcurrentGroupParams->MetricSetsCount);
// 3. Iterate over metric sets.
for (uint32_t j = 0; j < pConcurrentGroupParams->MetricSetsCount; ++j) {
MetricsDiscovery::IMetricSet_1_5 *pMetricSet = pConcurrentGroup->GetMetricSet(j);
DEBUG_BREAK_IF(pMetricSet == nullptr);
cacheMetricGroup(*pMetricSet, *pConcurrentGroup, i,
ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_TIME_BASED);
cacheMetricGroup(*pMetricSet, *pConcurrentGroup, i,
ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_EVENT_BASED);
}
}
}
return ZE_RESULT_SUCCESS;
}
ze_result_t
MetricEnumeration::cacheMetricGroup(MetricsDiscovery::IMetricSet_1_5 &metricSet,
MetricsDiscovery::IConcurrentGroup_1_5 &concurrentGroup,
const uint32_t domain,
const zet_metric_group_sampling_type_flag_t samplingType) {
MetricsDiscovery::TMetricSetParams_1_4 *pMetricSetParams = metricSet.GetParams();
DEBUG_BREAK_IF(pMetricSetParams == nullptr);
const uint32_t sourceApiMask = MetricGroupImp::getApiMask(samplingType);
// Map metric groups to level zero format and cache them.
if (pMetricSetParams->ApiMask & sourceApiMask) {
metricSet.SetApiFiltering(sourceApiMask);
// Obtain params once again - updated after SetApiFiltering
pMetricSetParams = metricSet.GetParams();
zet_metric_group_properties_t properties = {};
properties.stype = ZET_STRUCTURE_TYPE_METRIC_GROUP_PROPERTIES;
snprintf(properties.name, sizeof(properties.name), "%s",
pMetricSetParams->SymbolName); // To always have null-terminated string
snprintf(properties.description, sizeof(properties.description), "%s",
pMetricSetParams->ShortName);
properties.samplingType = samplingType;
properties.domain = domain; // Concurrent group number
properties.metricCount =
pMetricSetParams->MetricsCount + pMetricSetParams->InformationCount;
std::vector<Metric *> metrics;
createMetrics(metricSet, metrics);
auto pMetricGroup = MetricGroup::create(properties, metricSet, concurrentGroup, metrics);
DEBUG_BREAK_IF(pMetricGroup == nullptr);
metricGroups.push_back(pMetricGroup);
// Disable api filtering
metricSet.SetApiFiltering(MetricsDiscovery::API_TYPE_ALL);
}
return ZE_RESULT_SUCCESS;
}
ze_result_t MetricEnumeration::createMetrics(MetricsDiscovery::IMetricSet_1_5 &metricSet,
std::vector<Metric *> &metrics) {
MetricsDiscovery::TMetricSetParams_1_4 *pMetricSetParams = metricSet.GetParams();
DEBUG_BREAK_IF(pMetricSetParams == nullptr);
metrics.reserve(pMetricSetParams->MetricsCount + pMetricSetParams->InformationCount);
// Map metrics to level zero format and add them to 'metrics' vector.
for (uint32_t i = 0; i < pMetricSetParams->MetricsCount; ++i) {
MetricsDiscovery::IMetric_1_0 *pSourceMetric = metricSet.GetMetric(i);
DEBUG_BREAK_IF(pSourceMetric == nullptr);
MetricsDiscovery::TMetricParams_1_0 *pSourceMetricParams = pSourceMetric->GetParams();
DEBUG_BREAK_IF(pSourceMetricParams == nullptr);
zet_metric_properties_t properties = {};
properties.stype = ZET_STRUCTURE_TYPE_METRIC_PROPERTIES;
snprintf(properties.name, sizeof(properties.name), "%s",
pSourceMetricParams->SymbolName); // To always have a null-terminated string
snprintf(properties.description, sizeof(properties.description), "%s",
pSourceMetricParams->LongName);
snprintf(properties.component, sizeof(properties.component), "%s",
pSourceMetricParams->GroupName);
snprintf(properties.resultUnits, sizeof(properties.resultUnits), "%s",
pSourceMetricParams->MetricResultUnits);
properties.tierNumber = getMetricTierNumber(pSourceMetricParams->UsageFlagsMask);
properties.metricType = getMetricType(pSourceMetricParams->MetricType);
properties.resultType = getMetricResultType(pSourceMetricParams->ResultType);
auto pMetric = Metric::create(properties);
UNRECOVERABLE_IF(pMetric == nullptr);
metrics.push_back(pMetric);
}
// Map information to level zero format and add them to 'metrics' vector (as metrics).
for (uint32_t i = 0; i < pMetricSetParams->InformationCount; ++i) {
MetricsDiscovery::IInformation_1_0 *pSourceInformation = metricSet.GetInformation(i);
DEBUG_BREAK_IF(pSourceInformation == nullptr);
MetricsDiscovery::TInformationParams_1_0 *pSourceInformationParams =
pSourceInformation->GetParams();
DEBUG_BREAK_IF(pSourceInformationParams == nullptr);
zet_metric_properties_t properties = {};
properties.stype = ZET_STRUCTURE_TYPE_METRIC_PROPERTIES;
snprintf(properties.name, sizeof(properties.name), "%s",
pSourceInformationParams->SymbolName); // To always have a null-terminated string
snprintf(properties.description, sizeof(properties.description), "%s",
pSourceInformationParams->LongName);
snprintf(properties.component, sizeof(properties.component), "%s",
pSourceInformationParams->GroupName);
snprintf(properties.resultUnits, sizeof(properties.resultUnits), "%s",
pSourceInformationParams->InfoUnits);
properties.tierNumber = 1;
properties.metricType = getMetricType(pSourceInformationParams->InfoType);
// MetricsDiscovery information are always UINT64
properties.resultType = ZET_VALUE_TYPE_UINT64;
auto pMetric = Metric::create(properties);
UNRECOVERABLE_IF(pMetric == nullptr);
metrics.push_back(pMetric);
}
return ZE_RESULT_SUCCESS;
}
uint32_t MetricEnumeration::getMetricTierNumber(const uint32_t sourceUsageFlagsMask) const {
uint32_t tierNumber = 0;
if (sourceUsageFlagsMask & MetricsDiscovery::USAGE_FLAG_TIER_1) {
tierNumber = 1;
} else if (sourceUsageFlagsMask & MetricsDiscovery::USAGE_FLAG_TIER_2) {
tierNumber = 2;
} else if (sourceUsageFlagsMask & MetricsDiscovery::USAGE_FLAG_TIER_3) {
tierNumber = 3;
} else if (sourceUsageFlagsMask & MetricsDiscovery::USAGE_FLAG_TIER_4) {
tierNumber = 4;
} else {
// No tier - some metrics may have this undefined
tierNumber = 0;
}
return tierNumber;
}
zet_metric_type_t
MetricEnumeration::getMetricType(const MetricsDiscovery::TMetricType sourceMetricType) const {
switch (sourceMetricType) {
case MetricsDiscovery::METRIC_TYPE_DURATION:
return ZET_METRIC_TYPE_DURATION;
case MetricsDiscovery::METRIC_TYPE_EVENT:
return ZET_METRIC_TYPE_EVENT;
case MetricsDiscovery::METRIC_TYPE_EVENT_WITH_RANGE:
return ZET_METRIC_TYPE_EVENT_WITH_RANGE;
case MetricsDiscovery::METRIC_TYPE_THROUGHPUT:
return ZET_METRIC_TYPE_THROUGHPUT;
case MetricsDiscovery::METRIC_TYPE_TIMESTAMP:
return ZET_METRIC_TYPE_TIMESTAMP;
case MetricsDiscovery::METRIC_TYPE_FLAG:
return ZET_METRIC_TYPE_FLAG;
case MetricsDiscovery::METRIC_TYPE_RATIO:
return ZET_METRIC_TYPE_RATIO;
case MetricsDiscovery::METRIC_TYPE_RAW:
return ZET_METRIC_TYPE_RAW;
default:
DEBUG_BREAK_IF(!false);
return ZET_METRIC_TYPE_RAW;
}
}
zet_metric_type_t MetricEnumeration::getMetricType(
const MetricsDiscovery::TInformationType sourceInformationType) const {
switch (sourceInformationType) {
case MetricsDiscovery::INFORMATION_TYPE_REPORT_REASON:
return ZET_METRIC_TYPE_EVENT;
case MetricsDiscovery::INFORMATION_TYPE_VALUE:
case MetricsDiscovery::INFORMATION_TYPE_CONTEXT_ID_TAG:
case MetricsDiscovery::INFORMATION_TYPE_SAMPLE_PHASE:
case MetricsDiscovery::INFORMATION_TYPE_GPU_NODE:
return ZET_METRIC_TYPE_RAW;
case MetricsDiscovery::INFORMATION_TYPE_FLAG:
return ZET_METRIC_TYPE_FLAG;
case MetricsDiscovery::INFORMATION_TYPE_TIMESTAMP:
return ZET_METRIC_TYPE_TIMESTAMP;
default:
DEBUG_BREAK_IF(!false);
return ZET_METRIC_TYPE_RAW;
}
}
zet_value_type_t MetricEnumeration::getMetricResultType(
const MetricsDiscovery::TMetricResultType sourceMetricResultType) const {
switch (sourceMetricResultType) {
case MetricsDiscovery::RESULT_UINT32:
return ZET_VALUE_TYPE_UINT32;
case MetricsDiscovery::RESULT_UINT64:
return ZET_VALUE_TYPE_UINT64;
case MetricsDiscovery::RESULT_BOOL:
return ZET_VALUE_TYPE_BOOL8;
case MetricsDiscovery::RESULT_FLOAT:
return ZET_VALUE_TYPE_FLOAT32;
default:
DEBUG_BREAK_IF(!false);
return ZET_VALUE_TYPE_UINT64;
}
}
MetricGroupImp ::~MetricGroupImp() {
for (size_t i = 0; i < metrics.size(); ++i) {
delete metrics[i];
}
metrics.clear();
};
ze_result_t MetricGroupImp::getProperties(zet_metric_group_properties_t *pProperties) {
if (metricGroups.size() > 0) {
*pProperties = MetricGroup::getProperties(metricGroups[0]);
} else {
copyProperties(properties, *pProperties);
}
return ZE_RESULT_SUCCESS;
}
zet_metric_group_properties_t MetricGroup::getProperties(const zet_metric_group_handle_t handle) {
auto metricGroup = MetricGroup::fromHandle(handle);
UNRECOVERABLE_IF(!metricGroup);
zet_metric_group_properties_t properties = {ZET_STRUCTURE_TYPE_METRIC_GROUP_PROPERTIES};
metricGroup->getProperties(&properties);
return properties;
}
ze_result_t MetricGroupImp::getMetric(uint32_t *pCount, zet_metric_handle_t *phMetrics) {
if (metricGroups.size() > 0) {
auto metricGroupSubDevice = MetricGroup::fromHandle(metricGroups[0]);
return metricGroupSubDevice->getMetric(pCount, phMetrics);
}
if (*pCount == 0) {
*pCount = static_cast<uint32_t>(metrics.size());
return ZE_RESULT_SUCCESS;
}
// User is expected to allocate space.
DEBUG_BREAK_IF(phMetrics == nullptr);
if (*pCount > metrics.size()) {
*pCount = static_cast<uint32_t>(metrics.size());
}
for (uint32_t i = 0; i < *pCount; i++) {
phMetrics[i] = metrics[i]->toHandle();
}
return ZE_RESULT_SUCCESS;
}
bool MetricGroupImp::activate() {
DEBUG_BREAK_IF(pReferenceMetricSet == nullptr);
const bool result = pReferenceMetricSet->Activate() == MetricsDiscovery::CC_OK;
DEBUG_BREAK_IF(!result);
return result;
}
bool MetricGroupImp::deactivate() {
DEBUG_BREAK_IF(pReferenceMetricSet == nullptr);
const bool result = pReferenceMetricSet->Deactivate() == MetricsDiscovery::CC_OK;
return result;
}
uint32_t MetricGroupImp::getApiMask(const zet_metric_group_sampling_type_flags_t samplingType) {
switch (samplingType) {
case ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_TIME_BASED:
return MetricsDiscovery::API_TYPE_IOSTREAM;
case ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_EVENT_BASED:
return MetricsDiscovery::API_TYPE_OCL | MetricsDiscovery::API_TYPE_OGL4_X;
default:
DEBUG_BREAK_IF(true);
return 0;
}
}
ze_result_t MetricGroupImp::openIoStream(uint32_t &timerPeriodNs, uint32_t &oaBufferSize) {
const auto openResult = pReferenceConcurrentGroup->OpenIoStream(pReferenceMetricSet, 0,
&timerPeriodNs, &oaBufferSize);
return (openResult == MetricsDiscovery::CC_OK) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t MetricGroupImp::waitForReports(const uint32_t timeoutMs) {
return (pReferenceConcurrentGroup->WaitForReports(timeoutMs) == MetricsDiscovery::TCompletionCode::CC_OK)
? ZE_RESULT_SUCCESS
: ZE_RESULT_NOT_READY;
}
ze_result_t MetricGroupImp::readIoStream(uint32_t &reportCount, uint8_t &reportData) {
char *castedReportData = reinterpret_cast<char *>(&reportData);
const auto readResult =
pReferenceConcurrentGroup->ReadIoStream(&reportCount, castedReportData, 0);
switch (readResult) {
case MetricsDiscovery::CC_OK:
case MetricsDiscovery::CC_READ_PENDING:
return ZE_RESULT_SUCCESS;
default:
return ZE_RESULT_ERROR_UNKNOWN;
}
}
ze_result_t MetricGroupImp::closeIoStream() {
const auto closeResult = pReferenceConcurrentGroup->CloseIoStream();
return (closeResult == MetricsDiscovery::CC_OK) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t MetricGroupImp::calculateMetricValues(const zet_metric_group_calculation_type_t type, size_t rawDataSize,
const uint8_t *pRawData, uint32_t *pMetricValueCount,
zet_typed_value_t *pMetricValues) {
const bool calculateCountOnly = *pMetricValueCount == 0;
const bool result = calculateCountOnly
? getCalculatedMetricCount(rawDataSize, *pMetricValueCount)
: getCalculatedMetricValues(type, rawDataSize, pRawData, *pMetricValueCount, pMetricValues);
return result ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN;
}
bool MetricGroupImp::getCalculatedMetricCount(const size_t rawDataSize,
uint32_t &metricValueCount) {
uint32_t rawReportSize = getRawReportSize();
if (rawReportSize == 0) {
return false;
}
if ((rawDataSize % rawReportSize) != 0) {
return false;
}
const uint32_t rawReportCount = static_cast<uint32_t>(rawDataSize) / rawReportSize;
metricValueCount = rawReportCount * properties.metricCount;
return true;
}
bool MetricGroupImp::getCalculatedMetricValues(const zet_metric_group_calculation_type_t type, const size_t rawDataSize, const uint8_t *pRawData,
uint32_t &metricValueCount,
zet_typed_value_t *pCalculatedData) {
uint32_t calculatedReportCount = 0;
uint32_t expectedMetricValueCount = 0;
if (pCalculatedData == nullptr) {
return false;
}
if (getCalculatedMetricCount(rawDataSize, expectedMetricValueCount) == false) {
return false;
}
// Calculated metrics / maximum values container.
std::vector<MetricsDiscovery::TTypedValue_1_0> calculatedMetrics(expectedMetricValueCount);
std::vector<MetricsDiscovery::TTypedValue_1_0> maximumValues(expectedMetricValueCount);
// Set filtering type.
pReferenceMetricSet->SetApiFiltering(MetricGroupImp::getApiMask(properties.samplingType));
// Calculate metrics.
const uint32_t outMetricsSize = static_cast<uint32_t>(calculatedMetrics.size()) * sizeof(MetricsDiscovery::TTypedValue_1_0);
bool result = pReferenceMetricSet->CalculateMetrics(
reinterpret_cast<unsigned char *>(const_cast<uint8_t *>(pRawData)), static_cast<uint32_t>(rawDataSize),
calculatedMetrics.data(),
outMetricsSize,
&calculatedReportCount, maximumValues.data(), outMetricsSize) == MetricsDiscovery::CC_OK;
if (result) {
// Adjust copied reports to buffer provided by the user.
metricValueCount = std::min<uint32_t>(metricValueCount, calculatedReportCount * properties.metricCount);
// Translate metrics from metrics discovery to oneAPI format.
switch (type) {
case ZET_METRIC_GROUP_CALCULATION_TYPE_METRIC_VALUES:
for (size_t i = 0; i < metricValueCount; ++i) {
copyValue(calculatedMetrics[i], pCalculatedData[i]);
}
break;
case ZET_METRIC_GROUP_CALCULATION_TYPE_MAX_METRIC_VALUES:
for (size_t i = 0; i < metricValueCount; ++i) {
copyValue(maximumValues[i], pCalculatedData[i]);
}
break;
default:
result = false;
break;
}
}
return result;
}
ze_result_t MetricGroupImp::initialize(const zet_metric_group_properties_t &sourceProperties,
MetricsDiscovery::IMetricSet_1_5 &metricSet,
MetricsDiscovery::IConcurrentGroup_1_5 &concurrentGroup,
const std::vector<Metric *> &groupMetrics) {
copyProperties(sourceProperties, properties);
pReferenceMetricSet = &metricSet;
pReferenceConcurrentGroup = &concurrentGroup;
metrics = groupMetrics;
return ZE_RESULT_SUCCESS;
}
uint32_t MetricGroupImp::getRawReportSize() {
auto pMetricSetParams = pReferenceMetricSet->GetParams();
return (properties.samplingType == ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_TIME_BASED)
? pMetricSetParams->RawReportSize
: pMetricSetParams->QueryReportSize;
}
std::vector<zet_metric_group_handle_t> &MetricGroupImp::getMetricGroups() {
return metricGroups;
}
void MetricGroupImp::copyProperties(const zet_metric_group_properties_t &source,
zet_metric_group_properties_t &destination) {
destination = source;
memcpy_s(destination.name, sizeof(destination.name),
source.name, sizeof(destination.name));
memcpy_s(destination.description, sizeof(destination.description),
source.description, sizeof(destination.description));
}
void MetricGroupImp::copyValue(const MetricsDiscovery::TTypedValue_1_0 &source,
zet_typed_value_t &destination) const {
destination = {};
switch (source.ValueType) {
case MetricsDiscovery::VALUE_TYPE_UINT32:
destination.type = ZET_VALUE_TYPE_UINT32;
destination.value.ui32 = source.ValueUInt32;
break;
case MetricsDiscovery::VALUE_TYPE_UINT64:
destination.type = ZET_VALUE_TYPE_UINT64;
destination.value.ui64 = source.ValueUInt64;
break;
case MetricsDiscovery::VALUE_TYPE_FLOAT:
destination.type = ZET_VALUE_TYPE_FLOAT32;
destination.value.fp32 = source.ValueFloat;
break;
case MetricsDiscovery::VALUE_TYPE_BOOL:
destination.type = ZET_VALUE_TYPE_BOOL8;
destination.value.b8 = source.ValueBool;
break;
default:
destination.type = ZET_VALUE_TYPE_UINT64;
destination.value.ui64 = 0;
DEBUG_BREAK_IF(true);
break;
}
}
ze_result_t MetricImp::getProperties(zet_metric_properties_t *pProperties) {
copyProperties(properties, *pProperties);
return ZE_RESULT_SUCCESS;
}
ze_result_t MetricImp::initialize(const zet_metric_properties_t &sourceProperties) {
copyProperties(sourceProperties, properties);
return ZE_RESULT_SUCCESS;
}
void MetricImp::copyProperties(const zet_metric_properties_t &source,
zet_metric_properties_t &destination) {
destination = source;
memcpy_s(destination.name, sizeof(destination.name),
source.name, sizeof(destination.name));
memcpy_s(destination.description, sizeof(destination.description),
source.description, sizeof(destination.description));
memcpy_s(destination.component, sizeof(destination.component),
source.component, sizeof(destination.component));
memcpy_s(destination.resultUnits, sizeof(destination.resultUnits),
source.resultUnits, sizeof(destination.resultUnits));
}
MetricGroup *MetricGroup::create(zet_metric_group_properties_t &properties,
MetricsDiscovery::IMetricSet_1_5 &metricSet,
MetricsDiscovery::IConcurrentGroup_1_5 &concurrentGroup,
const std::vector<Metric *> &metrics) {
auto pMetricGroup = new MetricGroupImp();
UNRECOVERABLE_IF(pMetricGroup == nullptr);
pMetricGroup->initialize(properties, metricSet, concurrentGroup, metrics);
return pMetricGroup;
}
Metric *Metric::create(zet_metric_properties_t &properties) {
auto pMetric = new MetricImp();
UNRECOVERABLE_IF(pMetric == nullptr);
pMetric->initialize(properties);
return pMetric;
}
} // namespace L0