2020-03-06 18:09:57 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2019-2020 Intel Corporation
|
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
#include "level_zero/tools/source/metrics/metric_streamer_imp.h"
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
#include "shared/source/helpers/debug_helpers.h"
|
|
|
|
|
2020-03-19 13:21:57 +08:00
|
|
|
#include "level_zero/core/source/device/device.h"
|
2020-05-08 15:33:58 +08:00
|
|
|
#include "level_zero/tools/source/metrics/metric_query_imp.h"
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
namespace L0 {
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
ze_result_t MetricStreamerImp::readData(uint32_t maxReportCount, size_t *pRawDataSize,
|
|
|
|
uint8_t *pRawData) {
|
2020-03-17 21:15:35 +08:00
|
|
|
DEBUG_BREAK_IF(rawReportSize == 0);
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
auto metricGroup = MetricGroup::fromHandle(hMetricGroup);
|
|
|
|
|
|
|
|
// Return required size if requested.
|
|
|
|
if (*pRawDataSize == 0) {
|
|
|
|
*pRawDataSize = getRequiredBufferSize(maxReportCount);
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// User is expected to allocate space.
|
|
|
|
if (pRawData == nullptr) {
|
|
|
|
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the number of reports that fit into the buffer.
|
|
|
|
uint32_t reportCount = static_cast<uint32_t>(*pRawDataSize / rawReportSize);
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
// Read streamer data.
|
2020-03-06 18:09:57 +08:00
|
|
|
const ze_result_t result = metricGroup->readIoStream(reportCount, *pRawData);
|
|
|
|
if (result == ZE_RESULT_SUCCESS) {
|
|
|
|
*pRawDataSize = reportCount * rawReportSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
ze_result_t MetricStreamerImp::close() {
|
2020-03-06 18:09:57 +08:00
|
|
|
const auto result = stopMeasurements();
|
|
|
|
if (result == ZE_RESULT_SUCCESS) {
|
|
|
|
|
|
|
|
auto device = Device::fromHandle(hDevice);
|
2020-05-13 21:13:31 +08:00
|
|
|
auto &metricContext = device->getMetricContext();
|
|
|
|
auto &metricsLibrary = metricContext.getMetricsLibrary();
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
// Clear metric streamer reference in context.
|
|
|
|
// Another metric streamer instance or query can be used.
|
|
|
|
metricContext.setMetricStreamer(nullptr);
|
2020-05-13 21:13:31 +08:00
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
// Close metrics library (if was used to generate streamer's marker gpu commands).
|
2020-05-13 21:13:31 +08:00
|
|
|
// It will allow metric query to use Linux Tbs stream exclusively
|
|
|
|
// (to activate metric sets and to read context switch reports).
|
|
|
|
metricsLibrary.release();
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
// Release notification event.
|
|
|
|
if (pNotificationEvent != nullptr) {
|
2020-07-09 20:21:33 +08:00
|
|
|
pNotificationEvent->metricStreamer = nullptr;
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
// Delete metric streamer.
|
2020-03-06 18:09:57 +08:00
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
ze_result_t MetricStreamerImp::initialize(ze_device_handle_t hDevice,
|
|
|
|
zet_metric_group_handle_t hMetricGroup) {
|
2020-03-06 18:09:57 +08:00
|
|
|
this->hDevice = hDevice;
|
|
|
|
this->hMetricGroup = hMetricGroup;
|
|
|
|
|
|
|
|
auto metricGroup = MetricGroup::fromHandle(this->hMetricGroup);
|
|
|
|
rawReportSize = metricGroup->getRawReportSize();
|
|
|
|
|
|
|
|
return ZE_RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
ze_result_t MetricStreamerImp::startMeasurements(uint32_t ¬ifyEveryNReports,
|
|
|
|
uint32_t &samplingPeriodNs,
|
|
|
|
ze_event_handle_t hNotificationEvent) {
|
2020-03-06 18:09:57 +08:00
|
|
|
auto metricGroup = MetricGroup::fromHandle(hMetricGroup);
|
|
|
|
uint32_t requestedOaBufferSize = getOaBufferSize(notifyEveryNReports);
|
|
|
|
|
|
|
|
const ze_result_t result = metricGroup->openIoStream(samplingPeriodNs, requestedOaBufferSize);
|
|
|
|
|
|
|
|
// Return oa buffer size and notification event aligned to gpu capabilities.
|
|
|
|
if (result == ZE_RESULT_SUCCESS) {
|
|
|
|
oaBufferSize = requestedOaBufferSize;
|
|
|
|
notifyEveryNReports = getNotifyEveryNReports(requestedOaBufferSize);
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
// Associate notification event with metric streamer.
|
2020-03-06 18:09:57 +08:00
|
|
|
pNotificationEvent = Event::fromHandle(hNotificationEvent);
|
|
|
|
if (pNotificationEvent != nullptr) {
|
2020-07-09 20:21:33 +08:00
|
|
|
pNotificationEvent->metricStreamer = this;
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
ze_result_t MetricStreamerImp::stopMeasurements() {
|
2020-03-06 18:09:57 +08:00
|
|
|
auto metricGroup = MetricGroup::fromHandle(hMetricGroup);
|
|
|
|
|
|
|
|
const ze_result_t result = metricGroup->closeIoStream();
|
|
|
|
if (result == ZE_RESULT_SUCCESS) {
|
|
|
|
oaBufferSize = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
uint32_t MetricStreamerImp::getOaBufferSize(const uint32_t notifyEveryNReports) const {
|
2020-03-06 18:09:57 +08:00
|
|
|
// Notification is on half full buffer, hence multiplication by 2.
|
|
|
|
return notifyEveryNReports * rawReportSize * 2;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
uint32_t MetricStreamerImp::getNotifyEveryNReports(const uint32_t oaBufferSize) const {
|
2020-03-06 18:09:57 +08:00
|
|
|
// Notification is on half full buffer, hence division by 2.
|
|
|
|
return rawReportSize
|
|
|
|
? oaBufferSize / (rawReportSize * 2)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
Event::State MetricStreamerImp::getNotificationState() {
|
2020-03-06 18:09:57 +08:00
|
|
|
|
|
|
|
auto metricGroup = MetricGroup::fromHandle(hMetricGroup);
|
|
|
|
bool reportsReady = metricGroup->waitForReports(0) == ZE_RESULT_SUCCESS;
|
|
|
|
|
|
|
|
return reportsReady
|
|
|
|
? Event::State::STATE_SIGNALED
|
|
|
|
: Event::State::STATE_INITIAL;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
uint32_t MetricStreamerImp::getRequiredBufferSize(const uint32_t maxReportCount) const {
|
2020-03-17 21:15:35 +08:00
|
|
|
DEBUG_BREAK_IF(rawReportSize == 0);
|
2020-03-06 18:09:57 +08:00
|
|
|
uint32_t maxOaBufferReportCount = oaBufferSize / rawReportSize;
|
|
|
|
|
|
|
|
// Trim to OA buffer size if needed.
|
|
|
|
return maxReportCount > maxOaBufferReportCount ? oaBufferSize
|
|
|
|
: maxReportCount * rawReportSize;
|
|
|
|
}
|
|
|
|
|
2020-07-29 17:45:54 +08:00
|
|
|
ze_result_t MetricStreamer::open(zet_context_handle_t hContext, zet_device_handle_t hDevice, zet_metric_group_handle_t hMetricGroup,
|
2020-07-09 20:21:33 +08:00
|
|
|
zet_metric_streamer_desc_t &desc, ze_event_handle_t hNotificationEvent,
|
|
|
|
zet_metric_streamer_handle_t *phMetricStreamer) {
|
2020-03-06 18:09:57 +08:00
|
|
|
auto pDevice = Device::fromHandle(hDevice);
|
|
|
|
auto &metricContext = pDevice->getMetricContext();
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
*phMetricStreamer = nullptr;
|
2020-05-08 15:33:58 +08:00
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
// Check whether metric streamer is already open.
|
|
|
|
if (metricContext.getMetricStreamer() != nullptr) {
|
2020-05-08 15:33:58 +08:00
|
|
|
return ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE;
|
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
// metric streamer cannot be used with query simultaneously
|
2020-05-08 15:33:58 +08:00
|
|
|
// (oa buffer cannot be shared).
|
|
|
|
if (metricContext.getMetricsLibrary().getMetricQueryCount() > 0) {
|
|
|
|
return ZE_RESULT_ERROR_NOT_AVAILABLE;
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check metric group sampling type.
|
|
|
|
auto metricGroupProperties = MetricGroup::getProperties(hMetricGroup);
|
2020-07-31 19:23:37 +08:00
|
|
|
if (metricGroupProperties.samplingType != ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_TIME_BASED) {
|
2020-05-08 15:33:58 +08:00
|
|
|
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether metric group is activated.
|
|
|
|
if (!metricContext.isMetricGroupActivated(hMetricGroup)) {
|
2020-05-08 15:33:58 +08:00
|
|
|
return ZE_RESULT_NOT_READY;
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
auto pMetricStreamer = new MetricStreamerImp();
|
|
|
|
UNRECOVERABLE_IF(pMetricStreamer == nullptr);
|
|
|
|
pMetricStreamer->initialize(hDevice, hMetricGroup);
|
2020-03-06 18:09:57 +08:00
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
const ze_result_t result = pMetricStreamer->startMeasurements(
|
2020-03-06 18:09:57 +08:00
|
|
|
desc.notifyEveryNReports, desc.samplingPeriod, hNotificationEvent);
|
|
|
|
if (result == ZE_RESULT_SUCCESS) {
|
2020-07-09 20:21:33 +08:00
|
|
|
metricContext.setMetricStreamer(pMetricStreamer);
|
2020-03-06 18:09:57 +08:00
|
|
|
} else {
|
2020-07-09 20:21:33 +08:00
|
|
|
delete pMetricStreamer;
|
|
|
|
pMetricStreamer = nullptr;
|
2020-05-08 15:33:58 +08:00
|
|
|
return ZE_RESULT_ERROR_UNKNOWN;
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
2020-07-09 20:21:33 +08:00
|
|
|
*phMetricStreamer = pMetricStreamer->toHandle();
|
2020-05-08 15:33:58 +08:00
|
|
|
return ZE_RESULT_SUCCESS;
|
2020-03-06 18:09:57 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace L0
|