Skip to content

Commit 49e9851

Browse files
gzadica1gzadicario
andauthored
L0 Tracer - dynamic load API register functions at runtime. (#473)
Changed tracer to use L0 tracer register API rather then using prolog/epilog set API for all functions (previously used only for experimental APIs). Load the register APIs dynamically at runtime and only register callbacks for APIs that exist in running ze loader. Changed Cmake to download L0 headers, regardless if exist on build system. Co-authored-by: Guy Zadicario <[email protected]>
1 parent b51157f commit 49e9851

File tree

7 files changed

+256
-115
lines changed

7 files changed

+256
-115
lines changed

build_utils/CMakeLists.txt

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -614,18 +614,21 @@ macro(GetLevelZeroHeaders TARGET)
614614
set(L0_INC_PATH "${CMAKE_BINARY_DIR}")
615615
RequirePythonInterp()
616616

617-
add_custom_target(level_zero_headers ALL
618-
DEPENDS ${L0_INC_PATH}/level_zero/ze_api.h
619-
${L0_INC_PATH}/level_zero/zes_api.h
620-
${L0_INC_PATH}/level_zero/zet_api.h
621-
${L0_INC_PATH}/level_zero/layers/zel_tracing_api.h
622-
${L0_INC_PATH}/level_zero/layers/zel_tracing_register_cb.h)
623-
add_custom_command(OUTPUT ${L0_INC_PATH}/level_zero/ze_api.h
624-
${L0_INC_PATH}/level_zero/zes_api.h
625-
${L0_INC_PATH}/level_zero/zet_api.h
626-
${L0_INC_PATH}/level_zero/layers/zel_tracing_api.h
627-
${L0_INC_PATH}/level_zero/layers/zel_tracing_register_cb.h
628-
COMMAND "${PYTHON_EXECUTABLE}" "${PTI_CMAKE_MACRO_DIR}/get_ze_headers.py" ${L0_INC_PATH} ${CMAKE_BINARY_DIR})
617+
if (NOT TARGET level_zero_headers)
618+
add_custom_target(level_zero_headers ALL
619+
DEPENDS ${L0_INC_PATH}/level_zero/ze_api.h
620+
${L0_INC_PATH}/level_zero/zes_api.h
621+
${L0_INC_PATH}/level_zero/zet_api.h
622+
${L0_INC_PATH}/level_zero/layers/zel_tracing_api.h
623+
${L0_INC_PATH}/level_zero/layers/zel_tracing_register_cb.h)
624+
add_custom_command(OUTPUT ${L0_INC_PATH}/level_zero/ze_api.h
625+
${L0_INC_PATH}/level_zero/zes_api.h
626+
${L0_INC_PATH}/level_zero/zet_api.h
627+
${L0_INC_PATH}/level_zero/layers/zel_tracing_api.h
628+
${L0_INC_PATH}/level_zero/layers/zel_tracing_register_cb.h
629+
COMMAND "${PYTHON_EXECUTABLE}" "${PTI_CMAKE_MACRO_DIR}/get_ze_headers.py" ${L0_INC_PATH} ${CMAKE_BINARY_DIR})
630+
endif()
631+
629632
target_include_directories(${TARGET}
630633
PUBLIC "${L0_INC_PATH}")
631634
add_dependencies(${TARGET}

tools/unitrace/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ macro(FindHeadersPath TARGET L0_GEN_SCRIPT GEN_FILE_NAME custom_target)
5050
PUBLIC "${L0_GEN_INC_PATH}")
5151
add_dependencies(${TARGET}
5252
${custom_target})
53+
add_dependencies(${custom_target} level_zero_headers) # level_zero_headers target added in GetLevelZeroHeaders macro
5354
endmacro()
5455

5556
# Get Git Commit Hash
@@ -131,10 +132,11 @@ FindOpenCLHeaders(unitrace_tool)
131132
GetOpenCLTracingHeaders(unitrace_tool)
132133

133134
FindL0Library(unitrace_tool)
134-
FindL0Headers(unitrace_tool)
135+
GetLevelZeroHeaders(unitrace_tool)
135136

136137
FindHeadersPath(unitrace_tool "${PROJECT_SOURCE_DIR}/scripts/gen_tracing_common_header.py" "common_header.gen" gen_common_header)
137138
FindHeadersPath(unitrace_tool "${PROJECT_SOURCE_DIR}/scripts/gen_tracing_callbacks.py" "tracing.gen" gen_tracing_header)
139+
FindHeadersPath(unitrace_tool "${PROJECT_SOURCE_DIR}/scripts/gen_l0_loader.py" "l0_loader.gen" gen_l0_loader_header)
138140

139141
add_dependencies(gen_common_header
140142
cl_tracing_headers)
@@ -215,7 +217,7 @@ if(UNIX)
215217
endif()
216218

217219
FindL0Library(unitrace)
218-
FindL0Headers(unitrace)
220+
GetLevelZeroHeaders(unitrace)
219221
GetGitCommitHash(unitrace "${PROJECT_SOURCE_DIR}/scripts/get_commit_hash.py" "unitrace_commit_hash.h" get_git_commit_hash_unitrace)
220222
GetGitCommitHash(unitrace_tool "${PROJECT_SOURCE_DIR}/scripts/get_commit_hash.py" "unitrace_tool_commit_hash.h" get_git_commit_hash_unitrace_tool)
221223
if(WIN32)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#==============================================================
2+
# Copyright (C) Intel Corporation
3+
#
4+
# SPDX-License-Identifier: MIT
5+
# =============================================================
6+
7+
import os
8+
import sys
9+
import re
10+
11+
def get_func_list(f, func_list):
12+
f.seek(0)
13+
for line in f.readlines():
14+
if line.find("ZE_APICALL") != -1 and line.find("ze_pfn") != -1:
15+
items = line.split("ze_pfn")
16+
assert len(items) == 2
17+
assert items[1].find("Cb_t") != -1
18+
items = items[1].split("Cb_t")
19+
assert len(items) == 2
20+
func_list.append("ze" + items[0].strip())
21+
22+
def gen_loader(f, func_list):
23+
f.write("public:\n");
24+
for func in func_list:
25+
reg_fname = "zelTracer" + func[2:] + "RegisterCallback"
26+
f.write(" decltype(&" + reg_fname + ") " + reg_fname + "_ = nullptr;\n");
27+
28+
f.write("private:\n");
29+
f.write(" void init() {\n");
30+
for func in func_list:
31+
reg_fname = "zelTracer" + func[2:] + "RegisterCallback"
32+
f.write(" LEVEL_ZERO_LOADER_GET_SYMBOL(" + reg_fname + ");\n");
33+
f.write("}\n");
34+
35+
def main():
36+
if len(sys.argv) < 3:
37+
print("Usage: python gen_l0_loader.py <output_include_path> <l0_include_path>")
38+
return
39+
40+
dst_path = sys.argv[1]
41+
if (not os.path.exists(dst_path)):
42+
os.mkdir(dst_path)
43+
44+
dst_loader_file_path = os.path.join(dst_path, "l0_loader.gen")
45+
if (os.path.isfile(dst_loader_file_path)):
46+
os.remove(dst_loader_file_path)
47+
48+
dst_loader_file = open(dst_loader_file_path, "wt")
49+
50+
l0_path = sys.argv[2]
51+
l0_file_path = os.path.join(l0_path, "ze_api.h")
52+
53+
func_list = []
54+
55+
l0_file = open(l0_file_path, "rt")
56+
get_func_list(l0_file, func_list)
57+
58+
l0_exp_path = os.path.join(l0_path, "layers", "zel_tracing_register_cb.h")
59+
l0_exp_file = open(l0_exp_path, "rt")
60+
get_func_list(l0_exp_file, func_list)
61+
62+
gen_loader(dst_loader_file, func_list)
63+
64+
l0_exp_file.close()
65+
l0_file.close()
66+
dst_loader_file.close()
67+
68+
if __name__ == "__main__":
69+
main()

tools/unitrace/scripts/gen_tracing_callbacks.py

Lines changed: 28 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,8 @@ def get_param_struct_name(func_name):
189189
struct_name += "params_t"
190190
return struct_name
191191

192-
def get_func_list(f):
192+
def get_func_list(f, func_list):
193193
f.seek(0)
194-
func_list = []
195194
for line in f.readlines():
196195
if line.find("ZE_APICALL") != -1 and line.find("ze_pfn") != -1:
197196
items = line.split("ze_pfn")
@@ -200,22 +199,6 @@ def get_func_list(f):
200199
items = items[1].split("Cb_t")
201200
assert len(items) == 2
202201
func_list.append("ze" + items[0].strip())
203-
return func_list
204-
205-
def get_callback_group_map(f):
206-
group_map = {}
207-
208-
base_map = get_callback_struct_map(f, "ze_callbacks_t")
209-
assert len(base_map) > 0
210-
211-
for key, value in base_map.items():
212-
func_map = get_callback_struct_map(f, key)
213-
for fkey, fvalue in func_map.items():
214-
func_name = get_func_name(fkey)
215-
assert not (func_name in group_map)
216-
group_map[func_name] = (value, fvalue)
217-
218-
return group_map
219202

220203
def add_param_map(f, func_list, param_map):
221204
for func in func_list:
@@ -238,53 +221,24 @@ def get_enum_map(include_path):
238221

239222
# Generate Callbacks ##########################################################
240223

241-
def gen_set_prologues(f, func_list, group_map):
224+
def gen_register(f, func_list):
242225
for func in func_list:
243-
if not func in group_map:
244-
continue
226+
reg_fname = "ZeLoader::get().zelTracer" + func[2:] + "RegisterCallback_"
227+
f.write(" if (" + reg_fname + " != nullptr) {\n");
228+
f.write(" status = " + reg_fname + "(tracer, ZEL_REGISTER_PROLOGUE, " + func + "OnEnter);\n")
229+
f.write(" PTI_ASSERT(status == ZE_RESULT_SUCCESS);\n")
230+
f.write(" status = " + reg_fname + "(tracer, ZEL_REGISTER_EPILOGUE, " + func + "OnExit);\n")
231+
f.write(" PTI_ASSERT(status == ZE_RESULT_SUCCESS);\n")
232+
f.write(" }\n")
245233

246-
group, callback = group_map[func]
247-
group_name = group[0]
248-
group_cond = group[1]
249-
assert not group_cond
250-
callback_name = callback[0]
251-
callback_cond = callback[1]
252-
if callback_cond:
253-
f.write("#if " + callback_cond + "\n")
254-
f.write(" prologue." + group_name + "." + callback_name + " = " + func + "OnEnter;\n")
255-
f.write(" epilogue." + group_name + "." + callback_name + " = " + func + "OnExit;\n")
256-
if callback_cond:
257-
f.write("#endif //" + callback_cond + "\n")
258-
259-
def gen_exp_register(f, exp_func_list):
260-
for func in exp_func_list:
261-
f.write(" status = zelTracer" + func[2:] + "RegisterCallback(tracer, ZEL_REGISTER_PROLOGUE, " + func + "OnEnter);\n")
262-
f.write(" PTI_ASSERT(status == ZE_RESULT_SUCCESS);\n")
263-
f.write(" status = zelTracer" + func[2:] + "RegisterCallback(tracer, ZEL_REGISTER_EPILOGUE, " + func + "OnExit);\n")
264-
f.write(" PTI_ASSERT(status == ZE_RESULT_SUCCESS);\n")
265-
266-
def gen_api(f, func_list, kfunc_list, group_map, exp_func_list, kexp_func_list):
234+
def gen_api(f, func_list, kfunc_list):
267235
f.write("void EnableTracing(zel_tracer_handle_t tracer) {\n")
268-
f.write(" zet_core_callbacks_t prologue = {};\n")
269-
f.write(" zet_core_callbacks_t epilogue = {};\n")
270-
f.write("\n")
271-
f.write(" if (options_.api_tracing) {\n")
272-
gen_set_prologues(f, func_list, group_map)
273-
f.write(" }\n")
274-
f.write(" else if (options_.kernel_tracing) {\n")
275-
gen_set_prologues(f, kfunc_list, group_map)
276-
f.write(" }\n")
277-
f.write("\n")
278236
f.write(" ze_result_t status = ZE_RESULT_SUCCESS;\n")
279-
f.write(" status = zelTracerSetPrologues(tracer, &prologue);\n")
280-
f.write(" PTI_ASSERT(status == ZE_RESULT_SUCCESS);\n")
281-
f.write(" status = zelTracerSetEpilogues(tracer, &epilogue);\n")
282-
f.write(" PTI_ASSERT(status == ZE_RESULT_SUCCESS);\n")
283237
f.write(" if (options_.api_tracing) {\n")
284-
gen_exp_register(f, exp_func_list)
238+
gen_register(f, func_list)
285239
f.write(" }\n")
286240
f.write(" else if (options_.kernel_tracing) {\n")
287-
gen_exp_register(f, kexp_func_list)
241+
gen_register(f, kfunc_list)
288242
f.write(" }\n")
289243
f.write("\n")
290244
f.write(" status = zelTracerSetEnabled(tracer, true);\n")
@@ -822,38 +776,8 @@ def gen_exit_callback(f, func, submission_func_list, synchronize_func_list_on_en
822776
f.write(" start_time_host, end_time_host);\n")
823777
f.write(" }\n")
824778

825-
def gen_callbacks(f, func_list, command_list_func_list, command_queue_func_list, submission_func_list, synchronize_func_list_on_enter, synchronize_func_list_on_exit, group_map, param_map, enum_map):
779+
def gen_callbacks(f, func_list, command_list_func_list, command_queue_func_list, submission_func_list, synchronize_func_list_on_enter, synchronize_func_list_on_exit, param_map, enum_map):
826780
for func in func_list:
827-
if not func in group_map:
828-
continue
829-
830-
assert func in param_map
831-
group, callback = group_map[func]
832-
callback_name = callback[0]
833-
callback_cond = callback[1]
834-
if callback_cond:
835-
f.write("#if " + callback_cond + "\n")
836-
f.write("static void " + func + "OnEnter(\n")
837-
f.write(" " + get_param_struct_name(func) + "* params,\n")
838-
f.write(" ze_result_t result,\n")
839-
f.write(" void* global_user_data,\n")
840-
f.write(" void** instance_user_data) {\n")
841-
gen_enter_callback(f, func, command_list_func_list, command_queue_func_list, synchronize_func_list_on_enter, param_map[func], enum_map)
842-
f.write("}\n")
843-
f.write("\n")
844-
f.write("static void " + func + "OnExit(\n")
845-
f.write(" " + get_param_struct_name(func) + "* params,\n")
846-
f.write(" ze_result_t result,\n")
847-
f.write(" void* global_user_data,\n")
848-
f.write(" void** instance_user_data) {\n")
849-
gen_exit_callback(f, func, submission_func_list, synchronize_func_list_on_enter, synchronize_func_list_on_exit, param_map[func], enum_map)
850-
f.write("}\n")
851-
if callback_cond:
852-
f.write("#endif //" + callback_cond + "\n")
853-
f.write("\n")
854-
855-
def gen_exp_callbacks(f, exp_func_list, command_list_func_list, command_queue_func_list, submission_func_list, synchronize_func_list_on_enter, synchronize_func_list_on_exit, group_map, param_map, enum_map):
856-
for func in exp_func_list:
857781
assert func in param_map
858782
f.write("static void " + func + "OnEnter(\n")
859783
f.write(" " + get_param_struct_name(func) + "* params,\n")
@@ -890,13 +814,21 @@ def main():
890814
l0_path = sys.argv[2]
891815
l0_file_path = os.path.join(l0_path, "ze_api.h")
892816

817+
func_list = []
818+
param_map = {}
819+
893820
l0_file = open(l0_file_path, "rt")
894-
func_list = get_func_list(l0_file)
821+
get_func_list(l0_file, func_list)
822+
add_param_map(l0_file, func_list, param_map)
895823

896824
l0_exp_path = os.path.join(l0_path, "layers", "zel_tracing_register_cb.h")
897825
l0_exp_file = open(l0_exp_path, "rt")
898-
exp_func_list = get_func_list(l0_exp_file)
899-
826+
exp_func_list = []
827+
get_func_list(l0_exp_file, exp_func_list)
828+
add_param_map(l0_exp_file, exp_func_list, param_map)
829+
830+
func_list += exp_func_list
831+
900832
kfunc_list = [
901833
"zeEventDestroy",
902834
"zeEventHostReset",
@@ -934,9 +866,9 @@ def main():
934866
"zeEventHostSynchronize",
935867
"zeEventQueryStatus",
936868
"zeFenceHostSynchronize",
937-
"zeContextDestroy"]
938-
kexp_func_list = [
869+
"zeContextDestroy",
939870
"zeCommandListImmediateAppendCommandListsExp"]
871+
940872
command_list_func_list = [
941873
"zeCommandListAppendEventReset",
942874
"zeCommandListAppendLaunchKernel",
@@ -973,17 +905,12 @@ def main():
973905
"zeFenceHostSynchronize",
974906
"zeCommandQueueSynchronize"]
975907

976-
group_map = get_callback_group_map(l0_file)
977-
param_map = {}
978-
add_param_map(l0_file, func_list, param_map)
979-
add_param_map(l0_exp_file, exp_func_list, param_map)
980908
enum_map = get_enum_map(l0_path)
981909

982910
gen_result_converter(dst_file, enum_map)
983911
gen_structure_type_converter(dst_file, enum_map)
984-
gen_callbacks(dst_file, func_list, command_list_func_list, command_queue_func_list, submission_func_list, synchronize_func_list_on_enter, synchronize_func_list_on_exit, group_map, param_map, enum_map)
985-
gen_exp_callbacks(dst_file, exp_func_list, command_list_func_list, command_queue_func_list, submission_func_list, synchronize_func_list_on_enter, synchronize_func_list_on_exit, group_map, param_map, enum_map)
986-
gen_api(dst_file, func_list, kfunc_list, group_map, exp_func_list, kexp_func_list)
912+
gen_callbacks(dst_file, func_list, command_list_func_list, command_queue_func_list, submission_func_list, synchronize_func_list_on_enter, synchronize_func_list_on_exit, param_map, enum_map)
913+
gen_api(dst_file, func_list, kfunc_list)
987914

988915
l0_exp_file.close()
989916
l0_file.close()

tools/unitrace/src/levelzero/ze_collector.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "unicontrol.h"
3939
#include "unimemory.h"
4040

41+
#include "ze_loader.h"
4142
#include "common_header.gen"
4243

4344
struct ZeMetricQueryPoolKey {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//==============================================================
2+
// Copyright (C) Intel Corporation
3+
//
4+
// SPDX-License-Identifier: MIT
5+
// =============================================================
6+
#ifndef PTI_TOOLS_UNITRACE_LEVEL_ZERO_LEADER_H_
7+
#define PTI_TOOLS_UNITRACE_LEVEL_ZERO_LEADER_H_
8+
9+
#include <iostream>
10+
#include <memory>
11+
12+
#include "utils/library_loader.h"
13+
14+
class ZeLoader {
15+
public:
16+
static auto& get() {
17+
static ZeLoader instance{};
18+
return instance;
19+
}
20+
21+
void Unload() { lib_.reset(nullptr); }
22+
23+
bool Loaded() const { return lib_ != nullptr; }
24+
25+
private:
26+
ZeLoader() {
27+
#if defined(_WIN32)
28+
static constexpr const char* const kLevelZeroLoaderName = "ze_loader.dll";
29+
#else
30+
static constexpr const char* const kLevelZeroLoaderName = "libze_loader.so.1";
31+
#endif
32+
33+
try {
34+
lib_ = std::make_unique<LibraryLoader>(kLevelZeroLoaderName);
35+
} catch (const std::exception& e) {
36+
std::cerr << "[ERROR] Failed to load " << kLevelZeroLoaderName
37+
<< " Reason: " << e.what() << std::endl;
38+
lib_ = nullptr;
39+
return;
40+
}
41+
42+
init();
43+
}
44+
45+
std::unique_ptr<LibraryLoader> lib_ = nullptr;
46+
47+
#define LEVEL_ZERO_LOADER_GET_SYMBOL(X) \
48+
this->X##_ = lib_->GetSymbol<decltype(&X)>(#X) // NOLINT
49+
#include <l0_loader.gen> // Auto-generated callbacks
50+
#undef LEVEL_ZERO_LOADER_GET_SYMBOL
51+
};
52+
53+
#endif // PTI_TOOLS_UNITRACE_LEVEL_ZERO_LEADER_H_

0 commit comments

Comments
 (0)