Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/generate_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ def _mako_loader_cpp(path, namespace, tags, version, specs, meta):
'handle_lifetime.h.mako' : ('handle_lifetime_tracking', 'handle_lifetime.h'),
'handle_lifetime.cpp.mako' : ('handle_lifetime_tracking', 'handle_lifetime.cpp'),
'certification.h.mako' : ('checkers/certification/generated', 'certification.h'),
'timing.h.mako' : ('checkers/timing/generated', 'timing.h'),
'to_string.h.mako' : ('../../utils', 'to_string.h'),
}

Expand Down
63 changes: 63 additions & 0 deletions scripts/templates/validation/timing.h.mako
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<%!
import re
from templates import helper as th
%><%
n=namespace
N=n.upper()
%>/*
* ***THIS FILE IS GENERATED. ***
* See timing.h.mako for modifications
*
* Copyright (C) 2026 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
* @file ${name}
*
*/
#pragma once
#include "../zel_global_timing_state.h"
#include "${n}_entry_points.h"

namespace validation_layer {
class ${N}timingCheckerGenerated : public ${N}ValidationEntryPoints {
public:
%for obj in th.extract_objs(specs, r"function"):
<%
param_lines = [line for line in th.make_param_lines(n, tags, obj, format=["type", "name", "delim"])]
is_void_params = len(param_lines) == 1 and "void" in param_lines[0]
func_name = th.make_func_name(n, tags, obj)
%>virtual ze_result_t ${func_name}Prologue( \
%for line in param_lines:
${line} \
%endfor
) override {
GlobalTimingState::getInstance().recordStart();
return ZE_RESULT_SUCCESS;
}
virtual ze_result_t ${func_name}Epilogue( \
%if not is_void_params:
%for line in param_lines:
${line} \
%endfor
, ${obj['return_type']} result) override {
%else:
${obj['return_type']} result ) override {
%endif
GlobalTimingState::getInstance().recordEnd("${func_name}");
return ZE_RESULT_SUCCESS;
}
%endfor
%if n == 'ze':
// Experimental Intel extension for counter-based events
virtual ze_result_t zexCounterBasedEventCreate2Prologue( ze_context_handle_t hContext, ze_device_handle_t hDevice, const void* desc, ze_event_handle_t* phEvent ) override {
GlobalTimingState::getInstance().recordStart();
return ZE_RESULT_SUCCESS;
}
virtual ze_result_t zexCounterBasedEventCreate2Epilogue( ze_context_handle_t hContext, ze_device_handle_t hDevice, const void* desc, ze_event_handle_t* phEvent , ze_result_t result) override {
GlobalTimingState::getInstance().recordEnd("zexCounterBasedEventCreate2");
return ZE_RESULT_SUCCESS;
}
%endif
};
} // namespace validation_layer
36 changes: 36 additions & 0 deletions source/layers/validation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ By default, no validation modes will be enabled. The individual validation modes
- `ZE_ENABLE_THREADING_VALIDATION` (Not yet Implemented)
- `ZEL_ENABLE_CERTIFICATION_CHECKER`
- `ZEL_ENABLE_SYSTEM_RESOURCE_TRACKER_CHECKER`
- `ZEL_ENABLE_TIMING_CHECKER`

## Validation Modes

Expand Down Expand Up @@ -141,6 +142,41 @@ export ZEL_LOADER_LOGGING_LEVEL=debug

See [System Resource Tracker documentation](checkers/system_resource_tracker/system_resource_tracker.md) for detailed usage and CSV format.

### `ZEL_ENABLE_TIMING_CHECKER`

The Timing Checker measures the host-side (CPU) duration of every Level Zero API
call and aggregates per-API statistics (call count, total, min, max and average
time in nanoseconds).

For each API call the checker stamps a high-resolution monotonic timestamp in the
Prologue and reads it again in the Epilogue. The clock is
`QueryPerformanceCounter` on Windows and `clock_gettime(CLOCK_MONOTONIC_RAW)`
elsewhere. The measured span is dominated by the underlying driver call and is
consistent across calls, making it suitable for relative host-cost analysis.

To enable, set:
```bash
export ZE_ENABLE_VALIDATION_LAYER=1
export ZEL_ENABLE_TIMING_CHECKER=1
```

Output modes (each independently controlled):

| Environment Variable | Default | Description |
|---|---|---|
| `ZEL_ENABLE_TIMING_CHECKER` | `0` | Enable the checker; a per-API summary table is printed at teardown |
| `ZEL_TIMING_CHECKER_CSV` | (unset) | Also export the per-API statistics to a CSV file (the process id is appended to the filename) |
| `ZEL_TIMING_CHECKER_LIVE` | `0` | Also print each call's duration as it happens (verbose) |

The summary and live output are written directly to `stderr` and the rows are
sorted by their share of total host time (highest first). The Timing Checker does
not use the loader logging system, so the `ZEL_ENABLE_LOADER_LOGGING` /
`ZEL_LOADER_LOGGING_LEVEL` variables are **not** required (in particular you do
not need to set logging to `trace`, which would also enable API-call logging).

See [Timing Checker documentation](checkers/timing/timing_checker.md) for detailed
usage, output examples, and the CSV format.

## Testing

There is a small set of negative test cases designed to test the validation layer in the [level zero tests repo](https://github.com/oneapi-src/level-zero-tests/tree/master/negative_tests).
Expand Down
1 change: 1 addition & 0 deletions source/layers/validation/checkers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ add_subdirectory(performance)
add_subdirectory(parameter_validation)
add_subdirectory(template)
add_subdirectory(system_resource_tracker)
add_subdirectory(timing)
13 changes: 13 additions & 0 deletions source/layers/validation/checkers/timing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (C) 2026 Intel Corporation
# SPDX-License-Identifier: MIT

target_sources(${TARGET_NAME}
PRIVATE
${CMAKE_CURRENT_LIST_DIR}/zel_timing_checker.h
${CMAKE_CURRENT_LIST_DIR}/zel_timing_checker.cpp
${CMAKE_CURRENT_LIST_DIR}/zel_global_timing_state.h
${CMAKE_CURRENT_LIST_DIR}/generated/ze_timing.h
${CMAKE_CURRENT_LIST_DIR}/generated/zes_timing.h
${CMAKE_CURRENT_LIST_DIR}/generated/zet_timing.h
${CMAKE_CURRENT_LIST_DIR}/generated/zer_timing.h
)
Loading
Loading