-
Notifications
You must be signed in to change notification settings - Fork 787
[SYCL][XPTI] Add support for tracing Level Zero API calls #6023
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7618be1
e9240be
5b567c0
65efb46
0889bac
0fdca92
12f599a
b142ff9
9818ff9
9d0b6fe
25c222f
821aa16
38e0246
3e9d5fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,20 +99,46 @@ target_include_directories(LevelZeroLoader-Headers | |
INTERFACE "${LEVEL_ZERO_INCLUDE_DIR}" | ||
) | ||
|
||
find_package(Threads REQUIRED) | ||
if (SYCL_ENABLE_XPTI_TRACING) | ||
set(XPTI_PROXY_SRC "${CMAKE_SOURCE_DIR}/../xpti/src/xpti_proxy.cpp") | ||
endif() | ||
|
||
add_sycl_plugin(level_zero | ||
SOURCES | ||
"${sycl_inc_dir}/CL/sycl/detail/pi.h" | ||
"${CMAKE_CURRENT_SOURCE_DIR}/pi_level_zero.cpp" | ||
"${CMAKE_CURRENT_SOURCE_DIR}/pi_level_zero.hpp" | ||
"${CMAKE_CURRENT_SOURCE_DIR}/usm_allocator.cpp" | ||
"${CMAKE_CURRENT_SOURCE_DIR}/usm_allocator.hpp" | ||
"${CMAKE_CURRENT_SOURCE_DIR}/tracing.cpp" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should include tracing.cpp into pi_level_zero.so only if (SYCL_ENABLE_XPTI_TRACING) is true. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I think we should do the opposite, i.e. remove the SYCL_ENABLE_XPTI_TRACING and always include the tracing capabilities. The "sycl-prof" and "sycl-trace" tools are meant to be available to the end-user, and should always produce the traces. FWIW, I already removed the SYCL_PI_LEVEL_ZERO_ENABLE_TRACING (made it to "1" always). Do you agree? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see. Yes, I agree. |
||
${XPTI_PROXY_SRC} | ||
LIBRARIES | ||
"${LEVEL_ZERO_LOADER}" | ||
Threads::Threads | ||
) | ||
|
||
find_package(Python3 REQUIRED) | ||
|
||
add_custom_target(ze-api | ||
COMMAND ${Python3_EXECUTABLE} | ||
${CMAKE_CURRENT_SOURCE_DIR}/ze_api_generator.py | ||
${LEVEL_ZERO_INCLUDE_DIR}/level_zero/ze_api.h | ||
BYPRODUCTS | ||
${CMAKE_CURRENT_BINARY_DIR}/ze_api.def | ||
) | ||
target_include_directories(pi_level_zero PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) | ||
add_dependencies(pi_level_zero ze-api) | ||
|
||
if (SYCL_ENABLE_XPTI_TRACING) | ||
target_compile_definitions(pi_level_zero PRIVATE | ||
XPTI_ENABLE_INSTRUMENTATION | ||
XPTI_STATIC_LIBRARY | ||
) | ||
target_include_directories(pi_level_zero PRIVATE "${CMAKE_SOURCE_DIR}/../xpti/include") | ||
target_link_libraries(pi_level_zero PRIVATE ${CMAKE_DL_LIBS}) | ||
endif() | ||
|
||
Comment on lines
+120
to
+140
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should put this under if (SYCL_ENABLE_XPTI_TRACING) too. |
||
if (TARGET level-zero-loader) | ||
add_dependencies(ze-api level-zero-loader) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should put this under if (SYCL_ENABLE_XPTI_TRACING) too. |
||
add_dependencies(pi_level_zero level-zero-loader) | ||
endif() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
//===-------------- tracing.cpp - Level-Zero Host API Tracing --------------==// | ||
// | ||
// Part of the LLVM Project, 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 "xpti/xpti_data_types.h" | ||
#include <exception> | ||
#include <level_zero/layers/zel_tracing_api.h> | ||
#include <level_zero/ze_api.h> | ||
#include <xpti/xpti_trace_framework.h> | ||
|
||
#include <iostream> | ||
|
||
constexpr auto ZE_CALL_STREAM_NAME = "sycl.experimental.level_zero.call"; | ||
constexpr auto ZE_DEBUG_STREAM_NAME = "sycl.experimental.level_zero.debug"; | ||
|
||
thread_local uint64_t CallCorrelationID = 0; | ||
thread_local uint64_t DebugCorrelationID = 0; | ||
|
||
constexpr auto GVerStr = "0.1"; | ||
constexpr int GMajVer = 0; | ||
constexpr int GMinVer = 1; | ||
|
||
#ifdef XPTI_ENABLE_INSTRUMENTATION | ||
static xpti_td *GCallEvent = nullptr; | ||
static xpti_td *GDebugEvent = nullptr; | ||
#endif // XPTI_ENABLE_INSTRUMENTATION | ||
|
||
enum class ZEApiKind { | ||
#define _ZE_API(call, domain, cb, params_type) call, | ||
#include "ze_api.def" | ||
#undef _ZE_API | ||
}; | ||
|
||
void enableZeTracing() { | ||
#ifdef XPTI_ENABLE_INSTRUMENTATION | ||
if (!xptiTraceEnabled()) | ||
return; | ||
|
||
xptiRegisterStream(ZE_CALL_STREAM_NAME); | ||
xptiInitialize(ZE_CALL_STREAM_NAME, GMajVer, GMinVer, GVerStr); | ||
xptiRegisterStream(ZE_DEBUG_STREAM_NAME); | ||
xptiInitialize(ZE_DEBUG_STREAM_NAME, GMajVer, GMinVer, GVerStr); | ||
|
||
uint64_t Dummy; | ||
xpti::payload_t ZePayload("Level Zero Plugin Layer"); | ||
GCallEvent = | ||
xptiMakeEvent("Level Zero Plugin Layer", &ZePayload, | ||
xpti::trace_algorithm_event, xpti_at::active, &Dummy); | ||
|
||
xpti::payload_t ZeDebugPayload("Level Zero Plugin Debug Layer"); | ||
GDebugEvent = | ||
xptiMakeEvent("Level Zero Plugin Debug Layer", &ZeDebugPayload, | ||
xpti::trace_algorithm_event, xpti_at::active, &Dummy); | ||
|
||
ze_result_t Status = zeInit(0); | ||
if (Status != ZE_RESULT_SUCCESS) { | ||
// Most likey there are no Level Zero devices. | ||
return; | ||
} | ||
|
||
int Foo = 0; | ||
zel_tracer_desc_t TracerDesc = {ZEL_STRUCTURE_TYPE_TRACER_EXP_DESC, nullptr, | ||
&Foo}; | ||
zel_tracer_handle_t Tracer = nullptr; | ||
|
||
Status = zelTracerCreate(&TracerDesc, &Tracer); | ||
|
||
if (Status != ZE_RESULT_SUCCESS || Tracer == nullptr) { | ||
std::cerr << "[WARNING] Failed to create Level Zero tracer: " << Status | ||
<< "\n"; | ||
return; | ||
} | ||
|
||
zel_core_callbacks_t Prologue = {}; | ||
zel_core_callbacks_t Epilogue = {}; | ||
|
||
#define _ZE_API(call, domain, cb, params_type) \ | ||
Prologue.domain.cb = [](params_type *Params, ze_result_t, void *, void **) { \ | ||
if (xptiTraceEnabled()) { \ | ||
uint8_t CallStreamID = xptiRegisterStream(ZE_CALL_STREAM_NAME); \ | ||
uint8_t DebugStreamID = xptiRegisterStream(ZE_DEBUG_STREAM_NAME); \ | ||
CallCorrelationID = xptiGetUniqueId(); \ | ||
DebugCorrelationID = xptiGetUniqueId(); \ | ||
const char *FuncName = #call; \ | ||
xptiNotifySubscribers( \ | ||
CallStreamID, (uint16_t)xpti::trace_point_type_t::function_begin, \ | ||
GCallEvent, nullptr, CallCorrelationID, FuncName); \ | ||
uint32_t FuncID = static_cast<uint32_t>(ZEApiKind::call); \ | ||
xpti::function_with_args_t Payload{FuncID, FuncName, Params, nullptr, \ | ||
nullptr}; \ | ||
xptiNotifySubscribers( \ | ||
DebugStreamID, \ | ||
(uint16_t)xpti::trace_point_type_t::function_with_args_begin, \ | ||
GDebugEvent, nullptr, DebugCorrelationID, &Payload); \ | ||
} \ | ||
}; \ | ||
Epilogue.domain.cb = [](params_type *Params, ze_result_t Result, void *, \ | ||
void **) { \ | ||
if (xptiTraceEnabled()) { \ | ||
uint8_t CallStreamID = xptiRegisterStream(ZE_CALL_STREAM_NAME); \ | ||
uint8_t DebugStreamID = xptiRegisterStream(ZE_DEBUG_STREAM_NAME); \ | ||
const char *FuncName = #call; \ | ||
xptiNotifySubscribers(CallStreamID, \ | ||
(uint16_t)xpti::trace_point_type_t::function_end, \ | ||
GCallEvent, nullptr, CallCorrelationID, FuncName); \ | ||
uint32_t FuncID = static_cast<uint32_t>(ZEApiKind::call); \ | ||
xpti::function_with_args_t Payload{FuncID, FuncName, Params, &Result, \ | ||
nullptr}; \ | ||
xptiNotifySubscribers( \ | ||
DebugStreamID, \ | ||
(uint16_t)xpti::trace_point_type_t::function_with_args_end, \ | ||
GDebugEvent, nullptr, DebugCorrelationID, &Payload); \ | ||
} \ | ||
}; | ||
|
||
#include "ze_api.def" | ||
|
||
#undef _ZE_API | ||
|
||
Status = zelTracerSetPrologues(Tracer, &Prologue); | ||
if (Status != ZE_RESULT_SUCCESS) { | ||
std::cerr << "Failed to enable Level Zero tracing\n"; | ||
std::terminate(); | ||
} | ||
Status = zelTracerSetEpilogues(Tracer, &Epilogue); | ||
if (Status != ZE_RESULT_SUCCESS) { | ||
std::cerr << "Failed to enable Level Zero tracing\n"; | ||
std::terminate(); | ||
} | ||
|
||
Status = zelTracerSetEnabled(Tracer, true); | ||
if (Status != ZE_RESULT_SUCCESS) { | ||
std::cerr << "Failed to enable Level Zero tracing\n"; | ||
std::terminate(); | ||
} | ||
#endif // XPTI_ENABLE_INSTRUMENTATION | ||
} | ||
|
||
void disableZeTracing() { | ||
#ifdef XPTI_ENABLE_INSTRUMENTATION | ||
if (!xptiTraceEnabled()) | ||
return; | ||
|
||
xptiFinalize(ZE_CALL_STREAM_NAME); | ||
xptiFinalize(ZE_DEBUG_STREAM_NAME); | ||
#endif // XPTI_ENABLE_INSTRUMENTATION | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import re | ||
import sys | ||
|
||
def camel_to_snake(src): | ||
return re.sub(r'(?<!^)(?=[A-Z])', '_', src).lower() | ||
|
||
def snake_to_camel(src): | ||
temp = src.split('_') | ||
return ''.join(x.title() for x in temp) | ||
|
||
|
||
def extract_ze_apis(header): | ||
""" | ||
Emit file with contents of | ||
_ZE_API(api_name, api_domain, cb, param_type) | ||
""" | ||
api = open("ze_api.def", "w") | ||
|
||
matches = re.finditer(r'typedef struct _ze_([_a-z]+)_callbacks_t\n\{\n([a-zA-Z_;\s\n]+)\n\} ze_([_a-z]+)_callbacks_t;', header) | ||
|
||
for match in matches: | ||
api_domain = snake_to_camel(match.group(1)) | ||
for l in match.group(2).splitlines(): | ||
parts = l.split() | ||
api_match = re.match(r'ze_pfn([a-zA-Z]+)Cb_t', parts[0]) | ||
api_name_tail = api_match.group(1) | ||
api_name = 'ze' + api_name_tail | ||
|
||
param_type = 'ze_' + camel_to_snake(api_name_tail) + '_params_t' | ||
|
||
cb = 'pfn' + api_name_tail.replace(api_domain, '') + 'Cb' | ||
|
||
api.write("_ZE_API({}, {}, {}, {})\n".format(api_name, api_domain, cb, param_type)) | ||
|
||
api.close() | ||
|
||
if __name__ == "__main__": | ||
with open(sys.argv[1], 'r') as f: | ||
header = f.read() | ||
extract_ze_apis(header) |
Uh oh!
There was an error while loading. Please reload this page.