blob: de7df5509e6f6fbeeeec31e987a898fc6636162c [file]
// Copyright 2024 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
#ifndef IREE_HAL_UTILS_STREAM_TRACING_H_
#define IREE_HAL_UTILS_STREAM_TRACING_H_
#include "iree/base/api.h"
#include "iree/base/internal/arena.h"
#include "iree/base/threading/mutex.h"
#include "iree/hal/api.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// Per-stream tracing context.
// No-op if IREE tracing is not enabled.
//
// Use the IREE_TRACE_* macros to trace a contiguous set of stream
// operations. Unlike the normal tracy macros there are no zone IDs and instead
// each stream gets an ID allocated once and passed to all tracing macros.
//
// Usage:
// IREE_HAL_STREAM_TRACE_ZONE_BEGIN(queue->tracing_context, stream);
// *LaunchKernel(..., stream);
// IREE_HAL_STREAM_TRACE_ZONE_END(queue->tracing_context, stream);
// ...
// iree_hal_stream_tracing_context_collect(queue->tracing_context);
//
// NOTE: timestamps can have non-trivial side-effecting behavior and may
// introduce serialization in graph execution.
//
// TODO: expose event reservation separate from recording. For
// graphs we will need to insert the events but in order to reuse the graphs
// we'll need to reserve and patch new events each graph launch.
//
// Thread-compatible: external synchronization is required if using from
// multiple threads (same as with the streams themselves).
typedef struct iree_hal_stream_tracing_context_t
iree_hal_stream_tracing_context_t;
typedef struct iree_hal_stream_tracing_context_event_t
iree_hal_stream_tracing_context_event_t;
// This is used when tracing is enabled. Calls to dispatch and event related
// functions will update the pointers to keep the list up to date.
typedef struct iree_hal_stream_tracing_context_event_list_t {
iree_hal_stream_tracing_context_event_t* head;
iree_hal_stream_tracing_context_event_t* tail;
} iree_hal_stream_tracing_context_event_list_t;
typedef enum iree_hal_stream_tracing_verbosity_e {
IREE_HAL_STREAM_TRACING_VERBOSITY_OFF = 0,
IREE_HAL_STREAM_TRACING_VERBOSITY_COARSE,
IREE_HAL_STREAM_TRACING_VERBOSITY_FINE,
IREE_HAL_STREAM_TRACING_VERBOSITY_MAX
} iree_hal_stream_tracing_verbosity_t;
typedef struct iree_hal_stream_tracing_device_interface_vtable_t
iree_hal_stream_tracing_device_interface_vtable_t;
typedef struct iree_hal_stream_tracing_device_interface_t {
const iree_hal_stream_tracing_device_interface_vtable_t* vtable;
} iree_hal_stream_tracing_device_interface_t;
typedef void* iree_hal_stream_tracing_native_event_t;
typedef void* iree_hal_stream_tracing_native_graph_node_t;
typedef void* iree_hal_stream_tracing_native_graph_t;
typedef struct iree_hal_stream_tracing_device_interface_vtable_t {
// Destroys the iree_hal_stream_tracing_device_interface_t.
// Called when the iree_hal_stream_tracing_context_t is done with it.
void(IREE_API_PTR* destroy)(
iree_hal_stream_tracing_device_interface_t* device_interface);
// Causes the CPU to wait on the |event| to complete.
iree_status_t(IREE_API_PTR* synchronize_native_event)(
iree_hal_stream_tracing_device_interface_t* device_interface,
iree_hal_stream_tracing_native_event_t event);
// Returns a new native event to be used for timing.
iree_status_t(IREE_API_PTR* create_native_event)(
iree_hal_stream_tracing_device_interface_t* device_interface,
iree_hal_stream_tracing_native_event_t* event);
// Returns iree_status_ok if the event is completed.
iree_status_t(IREE_API_PTR* query_native_event)(
iree_hal_stream_tracing_device_interface_t* device_interface,
iree_hal_stream_tracing_native_event_t event);
// Returns the difference in milliseconds between the
// completed events |start_event| and |end_event|.
void(IREE_API_PTR* event_elapsed_time)(
iree_hal_stream_tracing_device_interface_t* device_interface,
float* relative_millis,
iree_hal_stream_tracing_native_event_t start_event,
iree_hal_stream_tracing_native_event_t end_event);
// Destroys the native event.
void(IREE_API_PTR* destroy_native_event)(
iree_hal_stream_tracing_device_interface_t* device_interface,
iree_hal_stream_tracing_native_event_t event);
// Records the native event into the stream associated
// with the device.
iree_status_t(IREE_API_PTR* record_native_event)(
iree_hal_stream_tracing_device_interface_t* device_interface,
iree_hal_stream_tracing_native_event_t event);
// Adds a record of the native event into the given graph.
iree_status_t(IREE_API_PTR* add_graph_event_record_node)(
iree_hal_stream_tracing_device_interface_t* device_interface,
iree_hal_stream_tracing_native_graph_node_t* out_node,
iree_hal_stream_tracing_native_graph_t graph,
iree_hal_stream_tracing_native_graph_node_t* dependency_nodes,
size_t dependency_nodes_count,
iree_hal_stream_tracing_native_event_t event);
} iree_hal_stream_tracing_device_interface_vtable_t;
// Allocates a tracing context for the given |interface|.
// Each context must only be used with the interface it was
// created for.
// The tracing context takes ownership of the interface,
// and the interface's destroy method will be called
// when cleanup is required.
iree_status_t iree_hal_stream_tracing_context_allocate(
iree_hal_stream_tracing_device_interface_t* interface,
iree_string_view_t queue_name,
iree_hal_stream_tracing_verbosity_t stream_tracing_verbosity,
iree_arena_block_pool_t* block_pool, iree_allocator_t host_allocator,
iree_hal_stream_tracing_context_t** out_context);
// Frees a tracing context and all associated resources.
// All submissions using the resources must be completed prior to calling.
void iree_hal_stream_tracing_context_free(
iree_hal_stream_tracing_context_t* context);
// Collects in-flight timestamp queries from the stream and feeds them to tracy.
// Must be called frequently (every submission, etc) to drain the backlog;
// tracing may start failing if the internal ringbuffer is exceeded.
iree_status_t iree_hal_stream_tracing_context_collect(
iree_hal_stream_tracing_context_t* context);
// Notifies that the given list of events has been dispatched on to the gpu.
void iree_hal_stream_tracing_notify_submitted(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_list_t* event_list);
// Manually collects the events for a specified event list.
// Callers must free the `events` to release them back into the context.
//
// Use this instead of `iree_hal_stream_tracing_notify_submitted` if
// you don't want the stream tracing to manually handle manually
// handle collecting events, (because it may cause more blocking than
// you would prefer)
iree_status_t iree_hal_stream_tracing_context_collect_list(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_t* event_list_head);
// Frees the events and returns them back into the tracing context.
void iree_hal_stream_tracing_free(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_list_t* event_list);
#if IREE_TRACING_FEATURES & IREE_TRACING_FEATURE_INSTRUMENTATION_DEVICE
// Begins a normal zone derived on the calling |src_loc|.
// Must be perfectly nested and paired with a corresponding zone end.
void iree_hal_stream_tracing_zone_begin_impl(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_list_t* event_list,
iree_hal_stream_tracing_verbosity_t verbosity,
const iree_tracing_location_t* src_loc);
// Begins an external zone using the given source information.
// The provided strings will be copied into the tracy buffer.
void iree_hal_stream_tracing_zone_begin_external_impl(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_list_t* event_list,
iree_hal_stream_tracing_verbosity_t verbosity, const char* file_name,
size_t file_name_length, uint32_t line, const char* function_name,
size_t function_name_length, const char* name, size_t name_length);
void iree_hal_graph_tracing_zone_begin_external_impl(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_list_t* event_list,
iree_hal_stream_tracing_native_graph_node_t* out_node,
iree_hal_stream_tracing_native_graph_t graph,
iree_hal_stream_tracing_verbosity_t verbosity,
iree_hal_stream_tracing_native_graph_node_t* dependency_nodes,
size_t dependency_nodes_count, const char* file_name,
size_t file_name_length, uint32_t line, const char* function_name,
size_t function_name_length, const char* name, size_t name_length);
void iree_hal_stream_tracing_zone_end_impl(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_list_t* event_list,
iree_hal_stream_tracing_verbosity_t verbosity);
void iree_hal_graph_tracing_zone_end_impl(
iree_hal_stream_tracing_context_t* context,
iree_hal_stream_tracing_context_event_list_t* event_list,
iree_hal_stream_tracing_native_graph_node_t* out_node,
iree_hal_stream_tracing_native_graph_t graph,
iree_hal_stream_tracing_verbosity_t verbosity,
iree_hal_stream_tracing_native_graph_node_t* dependency_nodes,
size_t dependency_nodes_count);
// Begins a new zone with the parent function name.
#define IREE_HAL_STREAM_TRACE_ZONE_BEGIN(context, event_list, verbosity) \
static const iree_tracing_location_t TracyConcat( \
__tracy_source_location, __LINE__) = {NULL, __FUNCTION__, __FILE__, \
(uint32_t)__LINE__, 0}; \
iree_hal_stream_tracing_zone_begin_impl( \
context, event_list, verbosity, \
&TracyConcat(__tracy_source_location, __LINE__));
// Begins an externally defined zone with a dynamic source location.
// The |file_name|, |function_name|, and optional |name| strings will be copied
// into the trace buffer and do not need to persist.
#define IREE_HAL_STREAM_TRACE_ZONE_BEGIN_EXTERNAL( \
context, event_list, verbosity, file_name, file_name_length, line, \
function_name, function_name_length, name, name_length) \
iree_hal_stream_tracing_zone_begin_external_impl( \
context, event_list, verbosity, file_name, file_name_length, line, \
function_name, function_name_length, name, name_length)
#define IREE_HAL_GRAPH_TRACE_ZONE_BEGIN_EXTERNAL( \
context, event_list, out_node, graph, verbosity, dependency_nodes, \
dependency_nodes_count, file_name, file_name_length, line, function_name, \
function_name_length, name, name_length) \
iree_hal_graph_tracing_zone_begin_external_impl( \
context, event_list, out_node, graph, verbosity, dependency_nodes, \
dependency_nodes_count, file_name, file_name_length, line, \
function_name, function_name_length, name, name_length)
#define IREE_HAL_STREAM_TRACE_ZONE_END(context, event_list, verbosity) \
iree_hal_stream_tracing_zone_end_impl(context, event_list, verbosity)
#define IREE_HAL_GRAPH_TRACE_ZONE_END(context, event_list, out_node, graph, \
verbosity, dependency_nodes, \
dependency_nodes_count) \
iree_hal_graph_tracing_zone_end_impl(context, event_list, out_node, graph, \
verbosity, dependency_nodes, \
dependency_nodes_count)
#else
#define IREE_HAL_STREAM_TRACE_ZONE_BEGIN(context, event_list, verbosity)
#define IREE_HAL_STREAM_TRACE_ZONE_BEGIN_EXTERNAL( \
context, event_list, verbosity, file_name, file_name_length, line, \
function_name, function_name_length, name, name_length)
#define IREE_HAL_GRAPH_TRACE_ZONE_BEGIN_EXTERNAL( \
context, event_list, out_node, graph, verbosity, dependency_nodes, \
dependency_nodes_count, file_name, file_name_length, line, function_name, \
function_name_length, name, name_length)
#define IREE_HAL_STREAM_TRACE_ZONE_END(context, event_list, verbosity)
#define IREE_HAL_GRAPH_TRACE_ZONE_END(context, event_list, out_node, graph, \
verbosity, dependency_nodes, \
dependency_nodes_count)
#endif // IREE_TRACING_FEATURES & IREE_TRACING_FEATURE_INSTRUMENTATION_DEVICE
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // IREE_HAL_UTILS_STREAM_TRACING_H_