Metric Tracer Experimental Extension

API

Metric Tracer

Metrics collection model that allows retrieving metrics from events generated in asynchronous fashion. A Metrics Tracer is a software interface that allows configuration for collection of such metrics. Collected raw data can be converted into parsable data with the use of a decoder object.

Enumeration

Application can use zetMetricGroupGet to enumerate the list of metric groups and zetMetricGroupGetProperties to get metric group sampling type and search for ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_EXP_TRACER_BASED.

Configuration

Use the zetContextActivateMetricGroups API call to configure the device for data collection.

Collection

Metric Tracer based collection mode allows the creation of a tracer object for multiple metric groups than can be collected concurrently. Once metric groups are activated the tracer can be created using zetMetricTracerCreateExp. Tracers are created in disabled state, applications have the flexibility to to enable (zetMetricTracerEnableExp) and disable (zetMetricTracerDisableExp) during workload execution to selectively decide sections on which to collect metrics. ata can be retrieved from the tracer with zetMetricTracerReadDataExp.

Decoding

Metric Tracer collects the data in device specific, raw form that is not suitable for application processing. To convert data into a format that allows application parsing a decoder object can be used. The decoder object is created with zetMetricDecoderCreateExp and data can be converted using zetMetricTracerDecodeExp. Each event in the data is associated with a decodable metric, which can be retrieved with zetMetricDecoderGetDecodableMetricsExp.

Sample Code

The following pseudo-code demonstrates how to enumerate Tracer based metric groups and collect data.

  zet_metric_group_handle_t     hMetricGroup           = nullptr;
  ze_event_handle_t            hNotificationEvent     = nullptr;
  ze_event_pool_handle_t       hEventPool             = nullptr;
  ze_event_pool_desc_t         eventPoolDesc          = {ZE_STRUCTURE_TYPE_EVENT_POOL_DESC, nullptr, 0, 1};
  ze_event_desc_t              eventDesc              = {ZE_STRUCTURE_TYPE_EVENT_DESC};
  zet_metric_tracer_exp_handle_t hMetricTracer         = nullptr;
  zet_metric_tracer_exp_desc_t tracerDescriptor = { ZET_STRUCTURE_TYPE_METRIC_TRACER_EXP_DESC, nullptr, 1024};
  zet_metric_decoder_exp_handle_t hMetricDecoder       = nullptr;

  // Find the first metric group suitable for Tracer Based collection
  FindMetricGroup(hDevice,  ZET_METRIC_GROUP_SAMPLING_TYPE_FLAG_EXP_TRACER_BASED, &hMetricGroup );

  // Configure the HW
  zetContextActivateMetricGroups( hContext, hDevice, /* count= */ 1, &hMetricGroup );

  // Create notification event
  zeEventPoolCreate( hContext, &eventPoolDesc, 1, &hDevice, &hEventPool );
  eventDesc.index  = 0;
  eventDesc.signal = ZE_EVENT_SCOPE_FLAG_HOST;
  eventDesc.wait   = ZE_EVENT_SCOPE_FLAG_HOST;
  zeEventCreate( hEventPool, &eventDesc, &hNotificationEvent );

  // Create tracer
  zetMetricTracerCreateExp(hContext, hDevice, 1, &hMetricGroup , &tracerDescriptor, hNotificationEvent, &hMetricTracer);

  // create decoder
  zetMetricDecoderCreateExp( hMetricTracer,  &hMetricDecoder);

  // Get decodable metrics
  uint32_t numDecodableMetrics = 0;
  zetMetricDecoderGetDecodableMetricsExp(hMetricDecoder, &numDecodableMetrics, nullptr);
  std::vector<zet_metric_handle_t>decodableMetrics(numDecodableMetrics);
  zetMetricDecoderGetDecodableMetricsExp(hMetricDecoder, &numDecodableMetrics, decodableMetrics.data());

  // Enable the tracer
  zetMetricTracerEnableExp(hMetricTracer, true);

  // Run your workload
  Workload(hDevice);

  // Wait for data, optional in this example
  zeEventHostSynchronize( hNotificationEvent, 1000 /*timeout*/ );
  // reset the event if it fired

  // Read raw data
  size_t rawDataSize = 0;
  zetMetricTracerReadDataExp(hMetricTracer, &rawDataSize, nullptr);
  std::vector<uint8_t>rawData(rawDataSize);
  zetMetricTracerReadDataExp(hMetricTracer, &rawDataSize, rawData.data());

  // decode
  uint32_t totalNumEntries = 0;
  uint32_t setCount = 0;
  zetMetricTracerDecodeExp(hMetricDecoder,  &rawDataSize, rawData.data(), numDecodableMetrics, decodableMetrics.data(), &setCount, nullptr, &totalNumEntries, nullptr);
  std::vector<ze_metric_entry_exp_t> decodedEntries(totalNumEntries)
  std::vector<uint32_t> metricEntriesCountPerSet(setCount);
  zetMetricTracerDecodeExp(hMetricDecoder,  &rawDataSize, rawData.data(), numDecodableMetrics, decodableMetrics.data(), &setCount, metricEntriesCountPerSet.data(), &totalNumEntries, decodedEntries.data());

uint32_t setEntryStart = 0;
  for (uint8_t setIndex = 0; setIndex < setCount; setIndex++) {
      for (uint32_t index = setEntryStart;  index < metricEntriesCountPerSet[setIndex]; index++) {
          zet_metric_entry_exp_t metricEntry = decodedEntries[index];
          zet_metric_properties_t metricProperties = {};
          zetMetricGetProperties(decodableMetrics[metricEntry.metricIndex], &metricProperties);
          std::cout << "Component: " << metricProperties.component ". Decodable metric name: " << metricProperties.name;
          switch (metricProperties.resultType) {
          case ZET_VALUE_TYPE_UINT8:
          case ZET_VALUE_TYPE_UINT16:
          case ZET_VALUE_TYPE_UINT32:
              std::cout << ".t value: " << metricEntry.value.ui32 << std::endl;
          break;
          case ZET_VALUE_TYPE_UINT64:
              std::cout << ".t value: " << metricEntry.value.ui64 << std::endl;
          break;
          case ZET_VALUE_TYPE_FLOAT32:
              std::cout << ".t value: " << metricEntry.value.fp32 << std::endl;
          break;
          case ZET_VALUE_TYPE_FLOAT64:
              std::cout << ".t value: " << metricEntry.value.fp64 << std::endl;
          break;
          case ZET_VALUE_TYPE_BOOL8:
              if( metricEntry.value.b8 ){
                  std::cout << ".t value: true" << std::endl;
              else
                  std::cout << ".t value: false" << std::endl;
              }
          break;
          default:
          break;
          }

          setEntryStart = metricEntriesCountPerSet[setIndex];
      }
  }

  // Close metric tracer
  zetMetricTracerDisableExp(hMetricTracer, true);
  zetMetricDecoderDestroyExp(hMetricDecoder);
  zetMetricTracerDestroyExp(hMetricTracer);
  zeEventDestroy( hNotificationEvent );
  zeEventPoolDestroy( hEventPool );

  // Clean device configuration and free memory
  zetContextActivateMetricGroups( hContext, hDevice, 0, nullptr );