blob: 1ed683c29e16b1407afc78caa97556c2daa0aab8 [file]
// Copyright 2026 The IREE Authors
//
// Licensed under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "iree/tooling/profile/model.h"
#include <string.h>
#include "iree/tooling/profile/reader.h"
void iree_profile_model_initialize(iree_allocator_t host_allocator,
iree_profile_model_t* out_model) {
memset(out_model, 0, sizeof(*out_model));
out_model->host_allocator = host_allocator;
}
void iree_profile_model_deinitialize(iree_profile_model_t* model) {
iree_profile_index_deinitialize(&model->device_index, model->host_allocator);
iree_profile_index_deinitialize(&model->metric_descriptor_index,
model->host_allocator);
iree_profile_index_deinitialize(&model->metric_source_index,
model->host_allocator);
iree_profile_index_deinitialize(&model->queue_index, model->host_allocator);
iree_profile_index_deinitialize(&model->command_buffer_index,
model->host_allocator);
iree_profile_index_deinitialize(&model->function_index,
model->host_allocator);
iree_profile_index_deinitialize(&model->executable_index,
model->host_allocator);
iree_allocator_free(model->host_allocator, model->devices);
iree_allocator_free(model->host_allocator, model->metric_descriptors);
iree_allocator_free(model->host_allocator, model->metric_sources);
iree_allocator_free(model->host_allocator, model->queues);
iree_allocator_free(model->host_allocator, model->command_operations);
iree_allocator_free(model->host_allocator, model->command_buffers);
iree_allocator_free(model->host_allocator, model->functions);
iree_allocator_free(model->host_allocator, model->executables);
memset(model, 0, sizeof(*model));
}
typedef struct iree_profile_model_device_lookup_t {
// Model owning the candidate rows.
const iree_profile_model_t* model;
// Session-local physical device ordinal.
uint32_t physical_device_ordinal;
} iree_profile_model_device_lookup_t;
typedef struct iree_profile_model_queue_lookup_t {
// Model owning the candidate rows.
const iree_profile_model_t* model;
// Session-local physical device ordinal.
uint32_t physical_device_ordinal;
// Session-local queue ordinal.
uint32_t queue_ordinal;
// Producer-defined queue stream identifier.
uint64_t stream_id;
} iree_profile_model_queue_lookup_t;
typedef struct iree_profile_model_executable_lookup_t {
// Model owning the candidate rows.
const iree_profile_model_t* model;
// Producer-local executable identifier.
uint64_t executable_id;
} iree_profile_model_executable_lookup_t;
typedef struct iree_profile_model_function_lookup_t {
// Model owning the candidate rows.
const iree_profile_model_t* model;
// Producer-local executable identifier.
uint64_t executable_id;
// Function ordinal within |executable_id|.
uint32_t function_ordinal;
} iree_profile_model_function_lookup_t;
typedef struct iree_profile_model_command_buffer_lookup_t {
// Model owning the candidate rows.
const iree_profile_model_t* model;
// Producer-local command-buffer identifier.
uint64_t command_buffer_id;
} iree_profile_model_command_buffer_lookup_t;
typedef struct iree_profile_model_metric_source_lookup_t {
// Model owning the candidate rows.
const iree_profile_model_t* model;
// Producer-defined metric source identifier.
uint64_t source_id;
} iree_profile_model_metric_source_lookup_t;
typedef struct iree_profile_model_metric_descriptor_lookup_t {
// Model owning the candidate rows.
const iree_profile_model_t* model;
// Producer-defined metric source identifier.
uint64_t source_id;
// Source-scoped metric identifier.
uint64_t metric_id;
} iree_profile_model_metric_descriptor_lookup_t;
static uint64_t iree_profile_model_device_hash(
uint32_t physical_device_ordinal) {
return iree_profile_index_mix_u64(physical_device_ordinal);
}
static uint64_t iree_profile_model_queue_hash(uint32_t physical_device_ordinal,
uint32_t queue_ordinal,
uint64_t stream_id) {
uint64_t hash = iree_profile_model_device_hash(physical_device_ordinal);
hash = iree_profile_index_combine_u64(hash, queue_ordinal);
return iree_profile_index_combine_u64(hash, stream_id);
}
static uint64_t iree_profile_model_executable_hash(uint64_t executable_id) {
return iree_profile_index_mix_u64(executable_id);
}
static uint64_t iree_profile_model_function_hash(uint64_t executable_id,
uint32_t function_ordinal) {
uint64_t hash = iree_profile_model_executable_hash(executable_id);
return iree_profile_index_combine_u64(hash, function_ordinal);
}
static uint64_t iree_profile_model_command_buffer_hash(
uint64_t command_buffer_id) {
return iree_profile_index_mix_u64(command_buffer_id);
}
static uint64_t iree_profile_model_metric_source_hash(uint64_t source_id) {
return iree_profile_index_mix_u64(source_id);
}
static uint64_t iree_profile_model_metric_descriptor_hash(uint64_t source_id,
uint64_t metric_id) {
uint64_t hash = iree_profile_model_metric_source_hash(source_id);
return iree_profile_index_combine_u64(hash, metric_id);
}
static bool iree_profile_model_device_matches(const void* user_data,
iree_host_size_t value) {
const iree_profile_model_device_lookup_t* lookup =
(const iree_profile_model_device_lookup_t*)user_data;
return lookup->model->devices[value].physical_device_ordinal ==
lookup->physical_device_ordinal;
}
static bool iree_profile_model_queue_matches(const void* user_data,
iree_host_size_t value) {
const iree_profile_model_queue_lookup_t* lookup =
(const iree_profile_model_queue_lookup_t*)user_data;
const iree_hal_profile_queue_record_t* record =
&lookup->model->queues[value].record;
return record->physical_device_ordinal == lookup->physical_device_ordinal &&
record->queue_ordinal == lookup->queue_ordinal &&
record->stream_id == lookup->stream_id;
}
static bool iree_profile_model_executable_matches(const void* user_data,
iree_host_size_t value) {
const iree_profile_model_executable_lookup_t* lookup =
(const iree_profile_model_executable_lookup_t*)user_data;
return lookup->model->executables[value].record.executable_id ==
lookup->executable_id;
}
static bool iree_profile_model_function_matches(const void* user_data,
iree_host_size_t value) {
const iree_profile_model_function_lookup_t* lookup =
(const iree_profile_model_function_lookup_t*)user_data;
const iree_profile_model_function_t* function_info =
&lookup->model->functions[value];
return function_info->executable_id == lookup->executable_id &&
function_info->function_ordinal == lookup->function_ordinal;
}
static bool iree_profile_model_command_buffer_matches(const void* user_data,
iree_host_size_t value) {
const iree_profile_model_command_buffer_lookup_t* lookup =
(const iree_profile_model_command_buffer_lookup_t*)user_data;
return lookup->model->command_buffers[value].record.command_buffer_id ==
lookup->command_buffer_id;
}
static bool iree_profile_model_metric_source_matches(const void* user_data,
iree_host_size_t value) {
const iree_profile_model_metric_source_lookup_t* lookup =
(const iree_profile_model_metric_source_lookup_t*)user_data;
return lookup->model->metric_sources[value].record.source_id ==
lookup->source_id;
}
static bool iree_profile_model_metric_descriptor_matches(
const void* user_data, iree_host_size_t value) {
const iree_profile_model_metric_descriptor_lookup_t* lookup =
(const iree_profile_model_metric_descriptor_lookup_t*)user_data;
const iree_hal_profile_device_metric_descriptor_record_t* record =
&lookup->model->metric_descriptors[value].record;
return record->source_id == lookup->source_id &&
record->metric_id == lookup->metric_id;
}
iree_status_t iree_profile_model_ensure_device(
iree_profile_model_t* model, uint32_t physical_device_ordinal,
iree_profile_model_device_t** out_device) {
*out_device = NULL;
const iree_profile_model_device_lookup_t lookup = {
.model = model,
.physical_device_ordinal = physical_device_ordinal,
};
const uint64_t hash = iree_profile_model_device_hash(physical_device_ordinal);
iree_host_size_t existing_index = 0;
if (iree_profile_index_find(&model->device_index, hash,
iree_profile_model_device_matches, &lookup,
&existing_index)) {
*out_device = &model->devices[existing_index];
return iree_ok_status();
}
if (model->device_count + 1 > model->device_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)4, model->device_count + 1),
sizeof(model->devices[0]), &model->device_capacity,
(void**)&model->devices));
}
const iree_host_size_t device_index = model->device_count;
IREE_RETURN_IF_ERROR(iree_profile_index_insert(
&model->device_index, model->host_allocator, hash, device_index));
++model->device_count;
iree_profile_model_device_t* device = &model->devices[device_index];
memset(device, 0, sizeof(*device));
device->physical_device_ordinal = physical_device_ordinal;
*out_device = device;
return iree_ok_status();
}
static void iree_profile_model_record_clock_sample(
iree_profile_model_device_t* device,
const iree_hal_profile_clock_correlation_record_t* record) {
if (iree_any_bit_set(
record->flags,
IREE_HAL_PROFILE_CLOCK_CORRELATION_FLAG_DEVICE_TICK_UNALIGNED)) {
++device->invalid_clock_alignment_sample_count;
}
if (device->clock_sample_count == 0) {
device->first_clock_sample = *record;
}
device->last_clock_sample = *record;
++device->clock_sample_count;
}
const iree_profile_model_device_t* iree_profile_model_find_device(
const iree_profile_model_t* model, uint32_t physical_device_ordinal) {
if (!model) return NULL;
const iree_profile_model_device_lookup_t lookup = {
.model = model,
.physical_device_ordinal = physical_device_ordinal,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(
&model->device_index,
iree_profile_model_device_hash(physical_device_ordinal),
iree_profile_model_device_matches, &lookup, &index)) {
return &model->devices[index];
}
return NULL;
}
const iree_profile_model_queue_t* iree_profile_model_find_queue(
const iree_profile_model_t* model, uint32_t physical_device_ordinal,
uint32_t queue_ordinal, uint64_t stream_id) {
if (!model) return NULL;
const iree_profile_model_queue_lookup_t lookup = {
.model = model,
.physical_device_ordinal = physical_device_ordinal,
.queue_ordinal = queue_ordinal,
.stream_id = stream_id,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(
&model->queue_index,
iree_profile_model_queue_hash(physical_device_ordinal, queue_ordinal,
stream_id),
iree_profile_model_queue_matches, &lookup, &index)) {
return &model->queues[index];
}
return NULL;
}
const iree_profile_model_executable_t* iree_profile_model_find_executable(
const iree_profile_model_t* model, uint64_t executable_id) {
if (!model) return NULL;
const iree_profile_model_executable_lookup_t lookup = {
.model = model,
.executable_id = executable_id,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(&model->executable_index,
iree_profile_model_executable_hash(executable_id),
iree_profile_model_executable_matches, &lookup,
&index)) {
return &model->executables[index];
}
return NULL;
}
static iree_profile_model_executable_t*
iree_profile_model_find_executable_mutable(iree_profile_model_t* model,
uint64_t executable_id) {
if (!model) return NULL;
const iree_profile_model_executable_lookup_t lookup = {
.model = model,
.executable_id = executable_id,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(&model->executable_index,
iree_profile_model_executable_hash(executable_id),
iree_profile_model_executable_matches, &lookup,
&index)) {
return &model->executables[index];
}
return NULL;
}
const iree_profile_model_function_t* iree_profile_model_find_function(
const iree_profile_model_t* model, uint64_t executable_id,
uint32_t function_ordinal) {
if (!model) return NULL;
const iree_profile_model_function_lookup_t lookup = {
.model = model,
.executable_id = executable_id,
.function_ordinal = function_ordinal,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(
&model->function_index,
iree_profile_model_function_hash(executable_id, function_ordinal),
iree_profile_model_function_matches, &lookup, &index)) {
return &model->functions[index];
}
return NULL;
}
const iree_profile_model_command_buffer_t*
iree_profile_model_find_command_buffer(const iree_profile_model_t* model,
uint64_t command_buffer_id) {
if (!model) return NULL;
const iree_profile_model_command_buffer_lookup_t lookup = {
.model = model,
.command_buffer_id = command_buffer_id,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(
&model->command_buffer_index,
iree_profile_model_command_buffer_hash(command_buffer_id),
iree_profile_model_command_buffer_matches, &lookup, &index)) {
return &model->command_buffers[index];
}
return NULL;
}
const iree_profile_model_metric_source_t* iree_profile_model_find_metric_source(
const iree_profile_model_t* model, uint64_t source_id) {
if (!model) return NULL;
const iree_profile_model_metric_source_lookup_t lookup = {
.model = model,
.source_id = source_id,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(&model->metric_source_index,
iree_profile_model_metric_source_hash(source_id),
iree_profile_model_metric_source_matches, &lookup,
&index)) {
return &model->metric_sources[index];
}
return NULL;
}
const iree_profile_model_metric_descriptor_t*
iree_profile_model_find_metric_descriptor(const iree_profile_model_t* model,
uint64_t source_id,
uint64_t metric_id) {
if (!model) return NULL;
const iree_profile_model_metric_descriptor_lookup_t lookup = {
.model = model,
.source_id = source_id,
.metric_id = metric_id,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(
&model->metric_descriptor_index,
iree_profile_model_metric_descriptor_hash(source_id, metric_id),
iree_profile_model_metric_descriptor_matches, &lookup, &index)) {
return &model->metric_descriptors[index];
}
return NULL;
}
iree_status_t iree_profile_model_resolve_metric_descriptor(
const iree_profile_model_t* model, uint64_t source_id, uint64_t metric_id,
const iree_profile_model_metric_descriptor_t** out_descriptor) {
*out_descriptor =
iree_profile_model_find_metric_descriptor(model, source_id, metric_id);
if (!*out_descriptor) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"device metric sample references missing descriptor source=%" PRIu64
" metric=%" PRIu64,
source_id, metric_id);
}
return iree_ok_status();
}
static iree_profile_model_command_buffer_t*
iree_profile_model_find_command_buffer_mutable(iree_profile_model_t* model,
uint64_t command_buffer_id) {
if (!model) return NULL;
const iree_profile_model_command_buffer_lookup_t lookup = {
.model = model,
.command_buffer_id = command_buffer_id,
};
iree_host_size_t index = 0;
if (iree_profile_index_find(
&model->command_buffer_index,
iree_profile_model_command_buffer_hash(command_buffer_id),
iree_profile_model_command_buffer_matches, &lookup, &index)) {
return &model->command_buffers[index];
}
return NULL;
}
static bool iree_profile_model_host_time_midpoint(
const iree_hal_profile_clock_correlation_record_t* sample,
int64_t* out_time_ns) {
if (!iree_all_bits_set(
sample->flags,
IREE_HAL_PROFILE_CLOCK_CORRELATION_FLAG_HOST_TIME_BRACKET) ||
sample->host_time_begin_ns < 0 ||
sample->host_time_end_ns < sample->host_time_begin_ns) {
return false;
}
*out_time_ns = sample->host_time_begin_ns +
(sample->host_time_end_ns - sample->host_time_begin_ns) / 2;
return true;
}
static bool iree_profile_model_sample_time_ns(
const iree_hal_profile_clock_correlation_record_t* sample,
iree_profile_model_clock_time_domain_t time_domain, int64_t* out_time_ns) {
switch (time_domain) {
case IREE_PROFILE_MODEL_CLOCK_TIME_DOMAIN_HOST_CPU_TIMESTAMP_NS:
if (!iree_all_bits_set(
sample->flags,
IREE_HAL_PROFILE_CLOCK_CORRELATION_FLAG_HOST_CPU_TIMESTAMP) ||
sample->host_cpu_timestamp_ns > INT64_MAX) {
return false;
}
*out_time_ns = (int64_t)sample->host_cpu_timestamp_ns;
return true;
case IREE_PROFILE_MODEL_CLOCK_TIME_DOMAIN_IREE_HOST_TIME_NS:
return iree_profile_model_host_time_midpoint(sample, out_time_ns);
default:
return false;
}
}
bool iree_profile_model_device_try_fit_clock_exact(
const iree_profile_model_device_t* device,
iree_profile_model_clock_time_domain_t time_domain,
iree_profile_model_clock_fit_t* out_fit) {
memset(out_fit, 0, sizeof(*out_fit));
if (!device || device->clock_sample_count < 2) return false;
if (device->invalid_clock_alignment_sample_count != 0) return false;
const iree_hal_profile_clock_correlation_record_t* first =
&device->first_clock_sample;
const iree_hal_profile_clock_correlation_record_t* last =
&device->last_clock_sample;
if (!iree_all_bits_set(first->flags,
IREE_HAL_PROFILE_CLOCK_CORRELATION_FLAG_DEVICE_TICK) ||
!iree_all_bits_set(last->flags,
IREE_HAL_PROFILE_CLOCK_CORRELATION_FLAG_DEVICE_TICK) ||
iree_any_bit_set(
first->flags | last->flags,
IREE_HAL_PROFILE_CLOCK_CORRELATION_FLAG_DEVICE_TICK_UNALIGNED)) {
return false;
}
int64_t first_time_ns = 0;
int64_t last_time_ns = 0;
if (!iree_profile_model_sample_time_ns(first, time_domain, &first_time_ns) ||
!iree_profile_model_sample_time_ns(last, time_domain, &last_time_ns)) {
return false;
}
if (last->device_tick <= first->device_tick ||
last_time_ns <= first_time_ns) {
return false;
}
out_fit->time_domain = time_domain;
out_fit->first_sample_id = first->sample_id;
out_fit->last_sample_id = last->sample_id;
out_fit->first_device_tick = first->device_tick;
out_fit->last_device_tick = last->device_tick;
out_fit->first_time_ns = first_time_ns;
out_fit->last_time_ns = last_time_ns;
out_fit->device_tick_span = last->device_tick - first->device_tick;
out_fit->time_span_ns = (uint64_t)(last_time_ns - first_time_ns);
return true;
}
static bool iree_profile_model_round_mul_div_u64(uint64_t value,
uint64_t numerator,
uint64_t denominator,
uint64_t* out_result) {
*out_result = 0;
if (denominator == 0) return false;
if (value == 0 || numerator == 0) return true;
#if defined(__SIZEOF_INT128__)
__uint128_t product = (__uint128_t)value * (__uint128_t)numerator;
product += denominator / 2;
__uint128_t quotient = product / denominator;
if (quotient > UINT64_MAX) return false;
*out_result = (uint64_t)quotient;
return true;
#else
const uint64_t whole = value / denominator;
const uint64_t remainder = value % denominator;
if (whole > UINT64_MAX / numerator) return false;
uint64_t scaled = whole * numerator;
if (remainder != 0) {
if (remainder > UINT64_MAX / numerator) return false;
uint64_t fractional_product = remainder * numerator;
if (fractional_product > UINT64_MAX - denominator / 2) return false;
uint64_t fractional = (fractional_product + denominator / 2) / denominator;
if (scaled > UINT64_MAX - fractional) return false;
scaled += fractional;
}
*out_result = scaled;
return true;
#endif // defined(__SIZEOF_INT128__)
}
bool iree_profile_model_clock_fit_scale_ticks_to_ns(
const iree_profile_model_clock_fit_t* fit, uint64_t device_tick_count,
int64_t* out_duration_ns) {
*out_duration_ns = 0;
if (!fit || fit->device_tick_span == 0) return false;
uint64_t duration_ns = 0;
if (!iree_profile_model_round_mul_div_u64(
device_tick_count, fit->time_span_ns, fit->device_tick_span,
&duration_ns) ||
duration_ns > INT64_MAX) {
return false;
}
*out_duration_ns = (int64_t)duration_ns;
return true;
}
bool iree_profile_model_clock_fit_map_tick(
const iree_profile_model_clock_fit_t* fit, uint64_t device_tick,
int64_t* out_time_ns) {
*out_time_ns = 0;
if (!fit || fit->device_tick_span == 0) return false;
const bool after_base = device_tick >= fit->first_device_tick;
const uint64_t tick_delta = after_base ? device_tick - fit->first_device_tick
: fit->first_device_tick - device_tick;
int64_t time_delta_ns = 0;
if (!iree_profile_model_clock_fit_scale_ticks_to_ns(fit, tick_delta,
&time_delta_ns)) {
return false;
}
if (after_base) {
if (fit->first_time_ns > INT64_MAX - time_delta_ns) return false;
*out_time_ns = fit->first_time_ns + time_delta_ns;
} else {
if (fit->first_time_ns < INT64_MIN + time_delta_ns) return false;
*out_time_ns = fit->first_time_ns - time_delta_ns;
}
return true;
}
double iree_profile_model_clock_fit_ns_per_tick(
const iree_profile_model_clock_fit_t* fit) {
if (!fit || fit->device_tick_span == 0) return 0.0;
return (double)fit->time_span_ns / (double)fit->device_tick_span;
}
double iree_profile_model_clock_fit_tick_frequency_hz(
const iree_profile_model_clock_fit_t* fit) {
const double ns_per_tick = iree_profile_model_clock_fit_ns_per_tick(fit);
return ns_per_tick > 0.0 ? 1000000000.0 / ns_per_tick : 0.0;
}
bool iree_profile_model_device_try_fit_clock(
const iree_profile_model_device_t* device, double* out_ns_per_tick,
double* out_tick_frequency_hz) {
*out_ns_per_tick = 0.0;
*out_tick_frequency_hz = 0.0;
iree_profile_model_clock_fit_t fit;
if (!iree_profile_model_device_try_fit_clock_exact(
device, IREE_PROFILE_MODEL_CLOCK_TIME_DOMAIN_HOST_CPU_TIMESTAMP_NS,
&fit)) {
return false;
}
*out_ns_per_tick = iree_profile_model_clock_fit_ns_per_tick(&fit);
*out_tick_frequency_hz = iree_profile_model_clock_fit_tick_frequency_hz(&fit);
return true;
}
static iree_string_view_t iree_profile_model_format_numeric_key(
uint32_t physical_device_ordinal, uint64_t executable_id,
uint32_t function_ordinal, char* buffer, iree_host_size_t buffer_capacity) {
if (buffer_capacity == 0) return iree_string_view_empty();
int result = 0;
if (physical_device_ordinal == UINT32_MAX) {
result = snprintf(buffer, buffer_capacity, "executable%" PRIu64 "#%u",
executable_id, function_ordinal);
} else {
result =
snprintf(buffer, buffer_capacity, "device%u/executable%" PRIu64 "#%u",
physical_device_ordinal, executable_id, function_ordinal);
}
if (result < 0) return iree_string_view_empty();
iree_host_size_t length = (iree_host_size_t)result;
if (length >= buffer_capacity) length = buffer_capacity - 1;
return iree_make_string_view(buffer, length);
}
iree_string_view_t iree_profile_model_format_function_key(
const iree_profile_model_function_t* function_info,
uint32_t physical_device_ordinal, char* numeric_buffer,
iree_host_size_t numeric_buffer_capacity) {
if (!iree_string_view_is_empty(function_info->name)) {
return function_info->name;
}
return iree_profile_model_format_numeric_key(
physical_device_ordinal, function_info->executable_id,
function_info->function_ordinal, numeric_buffer, numeric_buffer_capacity);
}
iree_status_t iree_profile_model_resolve_dispatch_key(
const iree_profile_model_t* model, uint32_t physical_device_ordinal,
uint64_t executable_id, uint32_t function_ordinal, char* numeric_buffer,
iree_host_size_t numeric_buffer_capacity, iree_string_view_t* out_key) {
*out_key = iree_string_view_empty();
const iree_profile_model_executable_t* executable_info =
iree_profile_model_find_executable(model, executable_id);
if (!executable_info) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"dispatch event references missing executable metadata "
"device=%u executable=%" PRIu64 " function=%u",
physical_device_ordinal, executable_id, function_ordinal);
}
const iree_profile_model_function_t* function_info =
iree_profile_model_find_function(model, executable_id, function_ordinal);
if (!function_info) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"dispatch event references missing executable function metadata "
"device=%u executable=%" PRIu64 " function=%u",
physical_device_ordinal, executable_id, function_ordinal);
}
*out_key = iree_profile_model_format_function_key(
function_info, physical_device_ordinal, numeric_buffer,
numeric_buffer_capacity);
return iree_ok_status();
}
static iree_status_t iree_profile_model_append_function(
iree_profile_model_t* model,
const iree_profile_model_function_t* function_info) {
iree_profile_model_executable_t* executable =
iree_profile_model_find_executable_mutable(model,
function_info->executable_id);
if (!executable) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"executable function references missing executable metadata "
"executable=%" PRIu64 " function=%u",
function_info->executable_id, function_info->function_ordinal);
}
const iree_profile_model_function_lookup_t lookup = {
.model = model,
.executable_id = function_info->executable_id,
.function_ordinal = function_info->function_ordinal,
};
const uint64_t hash = iree_profile_model_function_hash(
function_info->executable_id, function_info->function_ordinal);
iree_host_size_t existing_index = 0;
if (iree_profile_index_find(&model->function_index, hash,
iree_profile_model_function_matches, &lookup,
&existing_index)) {
return iree_ok_status();
}
if (model->function_count + 1 > model->function_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)16, model->function_count + 1),
sizeof(model->functions[0]), &model->function_capacity,
(void**)&model->functions));
}
const iree_host_size_t function_index = model->function_count;
IREE_RETURN_IF_ERROR(iree_profile_index_insert(
&model->function_index, model->host_allocator, hash, function_index));
model->functions[function_index] = *function_info;
model->functions[function_index].next_function_index = IREE_HOST_SIZE_MAX;
if (executable->first_function_index == IREE_HOST_SIZE_MAX) {
executable->first_function_index = function_index;
} else {
model->functions[executable->last_function_index].next_function_index =
function_index;
}
executable->last_function_index = function_index;
++executable->function_row_count;
++model->function_count;
return iree_ok_status();
}
static iree_status_t iree_profile_model_append_executable(
iree_profile_model_t* model,
const iree_hal_profile_executable_record_t* record) {
const iree_profile_model_executable_lookup_t lookup = {
.model = model,
.executable_id = record->executable_id,
};
const uint64_t hash =
iree_profile_model_executable_hash(record->executable_id);
iree_host_size_t existing_index = 0;
if (iree_profile_index_find(&model->executable_index, hash,
iree_profile_model_executable_matches, &lookup,
&existing_index)) {
return iree_ok_status();
}
if (model->executable_count + 1 > model->executable_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)8, model->executable_count + 1),
sizeof(model->executables[0]), &model->executable_capacity,
(void**)&model->executables));
}
const iree_host_size_t executable_index = model->executable_count;
IREE_RETURN_IF_ERROR(iree_profile_index_insert(
&model->executable_index, model->host_allocator, hash, executable_index));
iree_profile_model_executable_t* executable_info =
&model->executables[executable_index];
executable_info->record = *record;
executable_info->first_function_index = IREE_HOST_SIZE_MAX;
executable_info->last_function_index = IREE_HOST_SIZE_MAX;
executable_info->function_row_count = 0;
++model->executable_count;
return iree_ok_status();
}
static iree_status_t iree_profile_model_append_command_buffer(
iree_profile_model_t* model,
const iree_hal_profile_command_buffer_record_t* record) {
const iree_profile_model_command_buffer_lookup_t lookup = {
.model = model,
.command_buffer_id = record->command_buffer_id,
};
const uint64_t hash =
iree_profile_model_command_buffer_hash(record->command_buffer_id);
iree_host_size_t existing_index = 0;
if (iree_profile_index_find(&model->command_buffer_index, hash,
iree_profile_model_command_buffer_matches,
&lookup, &existing_index)) {
return iree_ok_status();
}
if (model->command_buffer_count + 1 > model->command_buffer_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)16, model->command_buffer_count + 1),
sizeof(model->command_buffers[0]), &model->command_buffer_capacity,
(void**)&model->command_buffers));
}
const iree_host_size_t command_buffer_index = model->command_buffer_count;
IREE_RETURN_IF_ERROR(iree_profile_index_insert(&model->command_buffer_index,
model->host_allocator, hash,
command_buffer_index));
iree_profile_model_command_buffer_t* command_buffer_info =
&model->command_buffers[command_buffer_index];
command_buffer_info->record = *record;
command_buffer_info->first_operation_index = IREE_HOST_SIZE_MAX;
command_buffer_info->last_operation_index = IREE_HOST_SIZE_MAX;
command_buffer_info->operation_count = 0;
++model->command_buffer_count;
return iree_ok_status();
}
static iree_status_t iree_profile_model_append_command_operation(
iree_profile_model_t* model,
const iree_hal_profile_command_operation_record_t* record) {
iree_profile_model_command_buffer_t* command_buffer =
iree_profile_model_find_command_buffer_mutable(model,
record->command_buffer_id);
if (!command_buffer) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"command operation references missing command-buffer metadata "
"command_buffer=%" PRIu64 " command_index=%u",
record->command_buffer_id, record->command_index);
}
if (model->command_operation_count + 1 > model->command_operation_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)64, model->command_operation_count + 1),
sizeof(model->command_operations[0]),
&model->command_operation_capacity,
(void**)&model->command_operations));
}
const iree_host_size_t operation_index = model->command_operation_count;
iree_profile_model_command_operation_t* operation_info =
&model->command_operations[operation_index];
operation_info->record = *record;
operation_info->next_operation_index = IREE_HOST_SIZE_MAX;
if (command_buffer->first_operation_index == IREE_HOST_SIZE_MAX) {
command_buffer->first_operation_index = operation_index;
} else {
model->command_operations[command_buffer->last_operation_index]
.next_operation_index = operation_index;
}
command_buffer->last_operation_index = operation_index;
++command_buffer->operation_count;
++model->command_operation_count;
return iree_ok_status();
}
static iree_status_t iree_profile_model_validate_command_operation(
const iree_hal_profile_command_operation_record_t* record) {
const bool has_block_structure =
iree_hal_profile_command_operation_has_block_structure(record);
if (has_block_structure) {
if (record->block_ordinal == UINT32_MAX ||
record->block_command_ordinal == UINT32_MAX) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"command operation declares block structure without block "
"coordinates command_buffer=%" PRIu64 " command_index=%u",
record->command_buffer_id, record->command_index);
}
} else if (record->block_ordinal != UINT32_MAX ||
record->block_command_ordinal != UINT32_MAX ||
record->target_block_ordinal != UINT32_MAX ||
record->alternate_block_ordinal != UINT32_MAX) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"command operation carries block coordinates without the block "
"structure flag command_buffer=%" PRIu64 " command_index=%u",
record->command_buffer_id, record->command_index);
}
return iree_ok_status();
}
static iree_status_t iree_profile_model_append_queue(
iree_profile_model_t* model,
const iree_hal_profile_queue_record_t* record) {
const iree_profile_model_queue_lookup_t lookup = {
.model = model,
.physical_device_ordinal = record->physical_device_ordinal,
.queue_ordinal = record->queue_ordinal,
.stream_id = record->stream_id,
};
const uint64_t hash =
iree_profile_model_queue_hash(record->physical_device_ordinal,
record->queue_ordinal, record->stream_id);
iree_host_size_t existing_index = 0;
if (iree_profile_index_find(&model->queue_index, hash,
iree_profile_model_queue_matches, &lookup,
&existing_index)) {
return iree_ok_status();
}
if (model->queue_count + 1 > model->queue_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)4, model->queue_count + 1),
sizeof(model->queues[0]), &model->queue_capacity,
(void**)&model->queues));
}
const iree_host_size_t queue_index = model->queue_count;
IREE_RETURN_IF_ERROR(iree_profile_index_insert(
&model->queue_index, model->host_allocator, hash, queue_index));
iree_profile_model_queue_t* queue_info = &model->queues[queue_index];
queue_info->record = *record;
++model->queue_count;
return iree_ok_status();
}
static iree_status_t iree_profile_model_append_metric_source(
iree_profile_model_t* model,
const iree_profile_model_metric_source_t* source_info) {
const iree_profile_model_metric_source_lookup_t lookup = {
.model = model,
.source_id = source_info->record.source_id,
};
const uint64_t hash =
iree_profile_model_metric_source_hash(source_info->record.source_id);
iree_host_size_t existing_index = 0;
if (iree_profile_index_find(&model->metric_source_index, hash,
iree_profile_model_metric_source_matches, &lookup,
&existing_index)) {
return iree_ok_status();
}
if (model->metric_source_count + 1 > model->metric_source_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)4, model->metric_source_count + 1),
sizeof(model->metric_sources[0]), &model->metric_source_capacity,
(void**)&model->metric_sources));
}
const iree_host_size_t source_index = model->metric_source_count;
IREE_RETURN_IF_ERROR(iree_profile_index_insert(
&model->metric_source_index, model->host_allocator, hash, source_index));
model->metric_sources[source_index] = *source_info;
++model->metric_source_count;
return iree_ok_status();
}
static iree_status_t iree_profile_model_append_metric_descriptor(
iree_profile_model_t* model,
const iree_profile_model_metric_descriptor_t* descriptor_info) {
const iree_profile_model_metric_descriptor_lookup_t lookup = {
.model = model,
.source_id = descriptor_info->record.source_id,
.metric_id = descriptor_info->record.metric_id,
};
const uint64_t hash = iree_profile_model_metric_descriptor_hash(
descriptor_info->record.source_id, descriptor_info->record.metric_id);
iree_host_size_t existing_index = 0;
if (iree_profile_index_find(&model->metric_descriptor_index, hash,
iree_profile_model_metric_descriptor_matches,
&lookup, &existing_index)) {
return iree_ok_status();
}
if (model->metric_descriptor_count + 1 > model->metric_descriptor_capacity) {
IREE_RETURN_IF_ERROR(iree_allocator_grow_array(
model->host_allocator,
iree_max((iree_host_size_t)16, model->metric_descriptor_count + 1),
sizeof(model->metric_descriptors[0]),
&model->metric_descriptor_capacity,
(void**)&model->metric_descriptors));
}
const iree_host_size_t descriptor_index = model->metric_descriptor_count;
IREE_RETURN_IF_ERROR(
iree_profile_index_insert(&model->metric_descriptor_index,
model->host_allocator, hash, descriptor_index));
model->metric_descriptors[descriptor_index] = *descriptor_info;
++model->metric_descriptor_count;
return iree_ok_status();
}
static iree_status_t iree_profile_model_process_queue_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_queue_record_t), &iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_queue_record_t record_value;
memcpy(&record_value, typed_record.contents.data, sizeof(record_value));
status = iree_profile_model_append_queue(model, &record_value);
}
return status;
}
static iree_status_t iree_profile_model_process_metric_source_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_device_metric_source_record_t),
&iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_device_metric_source_record_t record_value;
memcpy(&record_value, typed_record.contents.data, sizeof(record_value));
if ((iree_host_size_t)record_value.name_length !=
typed_record.inline_payload.data_length) {
status = iree_make_status(IREE_STATUS_DATA_LOSS,
"device metric source name length is "
"inconsistent with record length");
}
if (iree_status_is_ok(status)) {
iree_profile_model_metric_source_t source_info = {
.record = record_value,
.name = iree_make_string_view(
(const char*)typed_record.inline_payload.data,
typed_record.inline_payload.data_length),
};
status = iree_profile_model_append_metric_source(model, &source_info);
}
}
return status;
}
static iree_status_t iree_profile_model_process_metric_descriptor_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_device_metric_descriptor_record_t),
&iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_device_metric_descriptor_record_t record_value;
memcpy(&record_value, typed_record.contents.data, sizeof(record_value));
iree_host_size_t trailing_length = 0;
if (!iree_host_size_checked_add(record_value.name_length,
record_value.description_length,
&trailing_length) ||
trailing_length != typed_record.inline_payload.data_length) {
status = iree_make_status(
IREE_STATUS_DATA_LOSS,
"device metric descriptor string lengths are inconsistent with "
"record length");
}
if (iree_status_is_ok(status)) {
const char* string_base = (const char*)typed_record.inline_payload.data;
iree_profile_model_metric_descriptor_t descriptor_info = {
.record = record_value,
.name = iree_make_string_view(string_base, record_value.name_length),
.description =
iree_make_string_view(string_base + record_value.name_length,
record_value.description_length),
};
status =
iree_profile_model_append_metric_descriptor(model, &descriptor_info);
}
}
return status;
}
static iree_status_t iree_profile_model_process_executable_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_executable_record_t), &iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_executable_record_t record_value;
memcpy(&record_value, typed_record.contents.data, sizeof(record_value));
status = iree_profile_model_append_executable(model, &record_value);
}
return status;
}
static iree_status_t iree_profile_model_process_function_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_executable_function_record_t), &iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_executable_function_record_t record_value;
memcpy(&record_value, typed_record.contents.data, sizeof(record_value));
if ((iree_host_size_t)record_value.name_length !=
typed_record.inline_payload.data_length) {
status =
iree_make_status(IREE_STATUS_DATA_LOSS,
"executable function name length is inconsistent");
}
if (iree_status_is_ok(status)) {
iree_profile_model_function_t function_info = {
.executable_id = record_value.executable_id,
.flags = record_value.flags,
.function_ordinal = record_value.function_ordinal,
.constant_count = record_value.constant_count,
.binding_count = record_value.binding_count,
.parameter_count = record_value.parameter_count,
.workgroup_size = {record_value.workgroup_size[0],
record_value.workgroup_size[1],
record_value.workgroup_size[2]},
.function_hash = {record_value.function_hash[0],
record_value.function_hash[1]},
.name = iree_make_string_view(
(const char*)typed_record.inline_payload.data,
typed_record.inline_payload.data_length),
};
status = iree_profile_model_append_function(model, &function_info);
}
}
return status;
}
static iree_status_t iree_profile_model_process_command_buffer_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_command_buffer_record_t), &iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_command_buffer_record_t record_value;
memcpy(&record_value, typed_record.contents.data, sizeof(record_value));
status = iree_profile_model_append_command_buffer(model, &record_value);
}
return status;
}
static iree_status_t iree_profile_model_process_command_operation_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_command_operation_record_t), &iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_command_operation_record_t record_value;
memcpy(&record_value, typed_record.contents.data, sizeof(record_value));
status = iree_profile_model_validate_command_operation(&record_value);
if (iree_status_is_ok(status)) {
status =
iree_profile_model_append_command_operation(model, &record_value);
}
}
return status;
}
static iree_status_t iree_profile_model_process_clock_records(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
iree_profile_typed_record_iterator_t iterator;
iree_profile_typed_record_iterator_initialize(
record, sizeof(iree_hal_profile_clock_correlation_record_t), &iterator);
iree_status_t status = iree_ok_status();
while (iree_status_is_ok(status)) {
iree_profile_typed_record_t typed_record;
bool has_record = false;
status = iree_profile_typed_record_iterator_next(&iterator, &typed_record,
&has_record);
if (!iree_status_is_ok(status) || !has_record) break;
iree_hal_profile_clock_correlation_record_t clock_record;
memcpy(&clock_record, typed_record.contents.data, sizeof(clock_record));
iree_profile_model_device_t* device = NULL;
status = iree_profile_model_ensure_device(
model, clock_record.physical_device_ordinal, &device);
if (iree_status_is_ok(status)) {
iree_profile_model_record_clock_sample(device, &clock_record);
}
}
return status;
}
typedef iree_status_t (*iree_profile_model_chunk_processor_fn_t)(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record);
typedef struct iree_profile_model_chunk_route_t {
// Profile chunk content type handled by this route.
iree_string_view_t content_type;
// Processor used to add the chunk's metadata rows to the model.
iree_profile_model_chunk_processor_fn_t process;
} iree_profile_model_chunk_route_t;
iree_status_t iree_profile_model_process_metadata_record(
iree_profile_model_t* model, const iree_hal_profile_file_record_t* record) {
if (record->header.record_type != IREE_HAL_PROFILE_FILE_RECORD_TYPE_CHUNK) {
return iree_ok_status();
}
const iree_profile_model_chunk_route_t routes[] = {
{IREE_HAL_PROFILE_CONTENT_TYPE_QUEUES,
iree_profile_model_process_queue_records},
{IREE_HAL_PROFILE_CONTENT_TYPE_EXECUTABLES,
iree_profile_model_process_executable_records},
{IREE_HAL_PROFILE_CONTENT_TYPE_EXECUTABLE_FUNCTIONS,
iree_profile_model_process_function_records},
{IREE_HAL_PROFILE_CONTENT_TYPE_COMMAND_BUFFERS,
iree_profile_model_process_command_buffer_records},
{IREE_HAL_PROFILE_CONTENT_TYPE_COMMAND_OPERATIONS,
iree_profile_model_process_command_operation_records},
{IREE_HAL_PROFILE_CONTENT_TYPE_CLOCK_CORRELATIONS,
iree_profile_model_process_clock_records},
{IREE_HAL_PROFILE_CONTENT_TYPE_DEVICE_METRIC_SOURCES,
iree_profile_model_process_metric_source_records},
{IREE_HAL_PROFILE_CONTENT_TYPE_DEVICE_METRIC_DESCRIPTORS,
iree_profile_model_process_metric_descriptor_records},
};
for (iree_host_size_t i = 0; i < IREE_ARRAYSIZE(routes); ++i) {
if (iree_string_view_equal(record->content_type, routes[i].content_type)) {
return routes[i].process(model, record);
}
}
return iree_ok_status();
}
const char* iree_profile_command_operation_type_name(
iree_hal_profile_command_operation_type_t type) {
switch (type) {
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_BARRIER:
return "barrier";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_DISPATCH:
return "dispatch";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_FILL:
return "fill";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_COPY:
return "copy";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_UPDATE:
return "update";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_PROFILE_MARKER:
return "profile_marker";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_BRANCH:
return "branch";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_COND_BRANCH:
return "cond_branch";
case IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_RETURN:
return "return";
default:
return "unknown";
}
}
const char* iree_profile_queue_event_type_name(
iree_hal_profile_queue_event_type_t type) {
switch (type) {
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_BARRIER:
return "barrier";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_DISPATCH:
return "dispatch";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_EXECUTE:
return "execute";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_COPY:
return "copy";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_FILL:
return "fill";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_UPDATE:
return "update";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_READ:
return "read";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_WRITE:
return "write";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_ALLOCA:
return "alloca";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_DEALLOCA:
return "dealloca";
case IREE_HAL_PROFILE_QUEUE_EVENT_TYPE_HOST_CALL:
return "host_call";
default:
return "unknown";
}
}
const char* iree_profile_queue_dependency_strategy_name(
iree_hal_profile_queue_dependency_strategy_t strategy) {
switch (strategy) {
case IREE_HAL_PROFILE_QUEUE_DEPENDENCY_STRATEGY_NONE:
return "none";
case IREE_HAL_PROFILE_QUEUE_DEPENDENCY_STRATEGY_INLINE:
return "inline";
case IREE_HAL_PROFILE_QUEUE_DEPENDENCY_STRATEGY_DEVICE_BARRIER:
return "device_barrier";
case IREE_HAL_PROFILE_QUEUE_DEPENDENCY_STRATEGY_SOFTWARE_DEFER:
return "software_defer";
default:
return "unknown";
}
}
const char* iree_profile_event_relationship_type_name(
iree_hal_profile_event_relationship_type_t type) {
switch (type) {
case IREE_HAL_PROFILE_EVENT_RELATIONSHIP_TYPE_QUEUE_SUBMISSION_DISPATCH:
return "queue_submission_dispatch";
case IREE_HAL_PROFILE_EVENT_RELATIONSHIP_TYPE_QUEUE_SUBMISSION_QUEUE_DEVICE_EVENT:
return "queue_submission_queue_device_event";
case IREE_HAL_PROFILE_EVENT_RELATIONSHIP_TYPE_QUEUE_EVENT_HOST_EXECUTION_EVENT:
return "queue_event_host_execution_event";
case IREE_HAL_PROFILE_EVENT_RELATIONSHIP_TYPE_QUEUE_SUBMISSION_HOST_EXECUTION_EVENT:
return "queue_submission_host_execution_event";
default:
return "unknown";
}
}
const char* iree_profile_event_endpoint_type_name(
iree_hal_profile_event_endpoint_type_t type) {
switch (type) {
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_QUEUE_SUBMISSION:
return "queue_submission";
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_QUEUE_EVENT:
return "queue_event";
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_DISPATCH_EVENT:
return "dispatch_event";
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_COMMAND_OPERATION:
return "command_operation";
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_MEMORY_EVENT:
return "memory_event";
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_ARTIFACT:
return "artifact";
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_QUEUE_DEVICE_EVENT:
return "queue_device_event";
case IREE_HAL_PROFILE_EVENT_ENDPOINT_TYPE_HOST_EXECUTION_EVENT:
return "host_execution_event";
default:
return "unknown";
}
}
double iree_profile_model_span_ticks(uint64_t earliest_start_tick,
uint64_t latest_end_tick) {
if (earliest_start_tick == UINT64_MAX || latest_end_tick == 0 ||
latest_end_tick < earliest_start_tick) {
return 0.0;
}
return (double)(latest_end_tick - earliest_start_tick);
}
iree_status_t iree_profile_model_resolve_command_operation_key(
const iree_profile_model_t* model,
const iree_hal_profile_command_operation_record_t* operation,
char* numeric_buffer, iree_host_size_t numeric_buffer_capacity,
iree_string_view_t* out_key) {
*out_key = iree_make_cstring_view(
iree_profile_command_operation_type_name(operation->type));
if (operation->type != IREE_HAL_PROFILE_COMMAND_OPERATION_TYPE_DISPATCH ||
operation->executable_id == 0 ||
operation->function_ordinal == UINT32_MAX) {
return iree_ok_status();
}
const iree_profile_model_command_buffer_t* command_buffer =
iree_profile_model_find_command_buffer(model,
operation->command_buffer_id);
if (!command_buffer) {
return iree_make_status(
IREE_STATUS_DATA_LOSS,
"command operation references missing command-buffer metadata "
"command_buffer=%" PRIu64 " command_index=%u",
operation->command_buffer_id, operation->command_index);
}
return iree_profile_model_resolve_dispatch_key(
model, command_buffer->record.physical_device_ordinal,
operation->executable_id, operation->function_ordinal, numeric_buffer,
numeric_buffer_capacity, out_key);
}