Skip to content

Commit d2dfb04

Browse files
jfedorovCopilot
andauthored
[PTI-LIB] Avoid conflict with unitrace for sycl runtime (#644)
* [PTI-LIB] Avoid conflict with unitrace or other subscriber for sycl runtime - not subscribe for XPTI if someone else (e.g. unitrace) already subscribed - removed xpti subscription from pti core library, it goes via pti_view - added xpti_interop_test --------- Signed-off-by: jfedorov <julia.fedorova@intel.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent b13788f commit d2dfb04

File tree

9 files changed

+556
-25
lines changed

9 files changed

+556
-25
lines changed

sdk/src/metrics_handler.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,9 +1502,7 @@ class PtiMetricsCollectorHandler {
15021502
if (!env_string.empty()) {
15031503
spdlog::cfg::helpers::load_levels(env_string);
15041504
}
1505-
1506-
// https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
1507-
spdlog::set_pattern("[%H:%M][%^-%l-%$]%P:%t %s:%# %v");
1505+
utils::SetGlobalSpdLogPattern();
15081506

15091507
// Initialize L0
15101508
ze_result_t status = zeInit(ZE_INIT_FLAG_GPU_ONLY);

sdk/src/pti_lib_handler.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ inline std::string GetPathToWindowsLibraryDirectory() {
4949
}
5050
#endif
5151

52+
// API implemented in PTI Core library
53+
// to pass from PTI Interface library status of detected "foreign" XPTI subscribers,
54+
// if such were detected at the library load time
55+
void PtiSetXPTIEnvironmentDetails(bool is_foreign_subscriber, bool is_likely_unitrace_subscriber);
56+
5257
class PtiLibHandler {
5358
public:
5459
static auto& Instance() {
@@ -94,8 +99,21 @@ class PtiLibHandler {
9499
decltype(&ptiMetricsGetDevices) ptiMetricsGetDevices_ = nullptr; // NOLINT
95100
decltype(&ptiMetricsStartCollection) ptiMetricsStartCollection_ = nullptr; // NOLINT
96101
decltype(&ptiMetricGetCalculatedData) ptiMetricGetCalculatedData_ = nullptr; // NOLINT
102+
decltype(&PtiSetXPTIEnvironmentDetails) PtiSetXPTIEnvironmentDetails_ = nullptr; // NOLINT
97103

98104
private:
105+
inline void CommunicateForeignXPTISubscriber() {
106+
// Passing information about XPTI subscriber to PTI Core library right after it is loaded.
107+
// This should be done before any other call to PTI Core, as it might create Sycl collector
108+
// and it should not enable it, in case if some foreign subscriber already subscribed for XPTI
109+
if (PtiSetXPTIEnvironmentDetails_) {
110+
auto [is_foreign_subscriber, is_likely_unitrace_subscriber] = IsForeignXPTISubscriber();
111+
PtiSetXPTIEnvironmentDetails_(is_foreign_subscriber, is_likely_unitrace_subscriber);
112+
} else {
113+
SPDLOG_DEBUG("PtiSetXPTIEnvironmentDetails_ is not available in the loaded library.");
114+
}
115+
}
116+
99117
PtiLibHandler() {
100118
try {
101119
spdlog::set_level(spdlog::level::off);
@@ -104,6 +122,7 @@ class PtiLibHandler {
104122
if (!env_string.empty()) {
105123
spdlog::cfg::helpers::load_levels(env_string);
106124
}
125+
::utils::SetGlobalSpdLogPattern();
107126

108127
std::string pti_dir;
109128
#if defined(_WIN32)
@@ -148,7 +167,9 @@ class PtiLibHandler {
148167
PTI_VIEW_GET_SYMBOL(ptiMetricsGetDevices);
149168
PTI_VIEW_GET_SYMBOL(ptiMetricsStartCollection);
150169
PTI_VIEW_GET_SYMBOL(ptiMetricGetCalculatedData);
170+
PTI_VIEW_GET_SYMBOL(PtiSetXPTIEnvironmentDetails);
151171
#undef PTI_VIEW_GET_SYMBOL
172+
CommunicateForeignXPTISubscriber();
152173
}
153174
std::unique_ptr<LibraryLoader> pti_view_lib_ = nullptr;
154175
};

sdk/src/sycl/sycl_collector.h

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,21 @@ inline bool InMemoryCoreApis(const char* function_name) {
150150

151151
class SyclCollector {
152152
public:
153+
// Variables to indicate the presence of a foreign subscriber to XPTI.
154+
// To be set via call to ptiSetXPTIEnvironmentDetails before SyclCollector created
155+
static inline bool foreign_subscriber_ = false;
156+
static inline bool likely_unitrace_subscriber_ = false;
157+
153158
inline static auto& Instance() {
154159
static SyclCollector sycl_collector{nullptr};
155160
return sycl_collector;
156161
}
157162

158163
inline void EnableTracing() {
164+
// Do not change the behaviour here depending on foreign_subscriber_!
165+
// The current behavior ensures that in the absense of XPTI subscription (and Sycl records)
166+
// PTI generates to-called Special Records
167+
// About Special Records: see comments in unitrace.h
159168
enabled_ = true;
160169
xptiForceSetTraceEnabled(enabled_);
161170
}
@@ -361,8 +370,24 @@ class SyclCollector {
361370
}
362371

363372
private:
373+
#define WARNING_FOREIGN_SUBSCRIBER \
374+
"Another subscriber already subscribed to Sycl runtime events, " \
375+
"so PTI will not subscribe to them. It will affect correctness of PTI profile: " \
376+
"e.g. report zero XPU time for CPU callers of GPU kernels."
377+
378+
#define WARNING_LIKELY_UNITRACE_SUBSCRIBER \
379+
" Likely the application running under Unitrace. " \
380+
"To get correct PTI profile - run without Unitrace."
381+
364382
explicit SyclCollector(OnSyclRuntimeViewCallback buffer_callback)
365-
: acallback_(buffer_callback), xptiGetStashedKV(GetStashedFuncPtrFromSharedObject()) {}
383+
: acallback_(buffer_callback), xptiGetStashedKV(GetStashedFuncPtrFromSharedObject()) {
384+
static constexpr char warn_foreign_subscriber[] = WARNING_FOREIGN_SUBSCRIBER;
385+
static constexpr char warn_likely_unitrace_subscriber[] = WARNING_LIKELY_UNITRACE_SUBSCRIBER;
386+
if (foreign_subscriber_) {
387+
const char* warn_add = likely_unitrace_subscriber_ ? warn_likely_unitrace_subscriber : "";
388+
SPDLOG_WARN("{}{}", warn_foreign_subscriber, warn_add);
389+
}
390+
}
366391

367392
int32_t trace_all_env_value = utils::IsSetEnv("PTI_VIEW_RUNTIME_API");
368393
inline static thread_local ZeKernelCommandExecutionRecord sycl_runtime_rec_;
@@ -571,18 +596,30 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int major_version, unsigned int mi
571596
}
572597

573598
XPTI_CALLBACK_API void xptiTraceFinish(const char* /*stream_name*/) {}
599+
600+
// clang-format off
601+
extern "C" {
602+
void
603+
#if (defined(_WIN32) || defined(_WIN64))
604+
__declspec(dllexport)
605+
#else
606+
__attribute__((visibility("default")))
607+
#endif
608+
PtiSetXPTIEnvironmentDetails(bool is_foreign_subscriber,
609+
bool is_likely_unitrace_subscriber) {
610+
SyclCollector::foreign_subscriber_ = is_foreign_subscriber;
611+
SyclCollector::likely_unitrace_subscriber_ = is_likely_unitrace_subscriber;
612+
}
613+
}
614+
// clang-format on
615+
574616
#if (defined(_WIN32) || defined(_WIN64))
575617

576618
#include <windows.h>
577619

578-
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID /*lpvReserved*/) {
620+
BOOL WINAPI DllMain(HINSTANCE /*hinstDLL*/, DWORD fwdReason, LPVOID /*lpvReserved*/) {
579621
switch (fwdReason) {
580622
case DLL_PROCESS_ATTACH: {
581-
utils::SetEnv("XPTI_SUBSCRIBERS", utils::GetPathToSharedObject(hinstDLL).c_str());
582-
utils::SetEnv("XPTI_FRAMEWORK_DISPATCHER",
583-
utils::GetPathToSharedObject(pti::strings::kXptiLibName).c_str());
584-
utils::SetEnv("XPTI_TRACE_ENABLE", "1");
585-
utils::SetEnv("UR_ENABLE_LAYERS", "UR_LAYER_TRACING");
586623
break;
587624
}
588625
case DLL_THREAD_ATTACH:
@@ -599,16 +636,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdReason, LPVOID /*lpvReserved*/)
599636

600637
#else // Linux (possibly macOS?)
601638

602-
// Work-around for ensuring XPTI_SUBSCRIBERS and XPTI_FRAMEWORK_DISPATCHER are
603-
// set before xptiTraceInit() is called.
604-
__attribute__((constructor)) static void framework_init() {
605-
utils::SetEnv("XPTI_SUBSCRIBERS", utils::GetPathToSharedObject(Truncate).c_str());
606-
utils::SetEnv("XPTI_FRAMEWORK_DISPATCHER", utils::GetPathToSharedObject(xptiReset).c_str());
607-
utils::SetEnv("XPTI_TRACE_ENABLE", "1");
608-
609-
utils::SetEnv("UR_ENABLE_LAYERS", "UR_LAYER_TRACING");
610-
}
611-
612639
__attribute__((destructor)) static void framework_fini() { framework_finalized = true; }
613640

614641
#endif

sdk/src/utils/utils.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,17 @@ inline void* GetFunctionPtr(HMODULE lib_handle, const char* func_name) {
460460
#endif /* _WIN32 */
461461
}
462462

463+
inline std::pair<bool, bool> IsSubscriberToXPTI() {
464+
auto current_xpti_subscriber = utils::GetEnv("XPTI_SUBSCRIBERS");
465+
// and may be it is unitrace
466+
return {!current_xpti_subscriber.empty(),
467+
current_xpti_subscriber.find("unitrace") != std::string::npos};
468+
}
469+
470+
inline void SetGlobalSpdLogPattern() {
471+
// https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
472+
spdlog::set_pattern("PTI:[%H:%M][%^-%l-%$]%P:%t %s:%# %v");
473+
}
463474
} // namespace utils
464475

465476
#endif // PTI_UTILS_UTILS_H_

sdk/src/view_handler.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,7 @@ struct PtiViewRecordHandler {
278278
if (!env_string.empty()) {
279279
spdlog::cfg::helpers::load_levels(env_string);
280280
}
281-
// https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
282-
spdlog::set_pattern("[%H:%M][%^-%l-%$]%P:%t %s:%# %v");
281+
utils::SetGlobalSpdLogPattern();
283282

284283
if (!collector_) {
285284
CollectorOptions collector_options{};

sdk/src/xpti_adapter.cc

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,34 @@
99

1010
class GlobalSyclInitializer {
1111
public:
12+
// variables to store if XPTI is subscribed by some other subscriber
13+
// and if this subscriber is likely unitrace
14+
inline static bool foreign_subscriber_ = false;
15+
inline static bool likely_unitrace_subscriber_ = false;
16+
1217
inline static bool Initialize() {
13-
utils::SetEnv("XPTI_SUBSCRIBERS", utils::GetPathToSharedObject(Initialize).c_str());
14-
utils::SetEnv("XPTI_FRAMEWORK_DISPATCHER", pti::strings::kXptiLibName);
15-
utils::SetEnv("XPTI_TRACE_ENABLE", "1");
18+
// respecting another XPTI subscriber:
19+
// if someone already subscribed (e.g. might be that the app runs under unitrace) -
20+
// we do not subscribe for XPTI
21+
std::tie(foreign_subscriber_, likely_unitrace_subscriber_) = utils::IsSubscriberToXPTI();
22+
if (!foreign_subscriber_) {
23+
utils::SetEnv("XPTI_SUBSCRIBERS", utils::GetPathToSharedObject(Initialize).c_str());
24+
utils::SetEnv("XPTI_FRAMEWORK_DISPATCHER", pti::strings::kXptiLibName);
25+
utils::SetEnv("XPTI_TRACE_ENABLE", "1");
26+
27+
utils::SetEnv("UR_ENABLE_LAYERS", "UR_LAYER_TRACING");
28+
}
1629
return true;
1730
}
1831

1932
inline static bool result_ = Initialize();
2033
};
2134

35+
std::pair<bool, bool> IsForeignXPTISubscriber() {
36+
return {GlobalSyclInitializer::foreign_subscriber_,
37+
GlobalSyclInitializer::likely_unitrace_subscriber_};
38+
}
39+
2240
void xptiTraceInit(unsigned int major_version, unsigned int minor_version, const char* version_str,
2341
const char* stream_name) {
2442
if (!pti::PtiLibHandler::Instance().xptiTraceInit_) {

sdk/src/xpti_adapter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,6 @@ PTI_XPTI_HOOK_VISIBILITY void xptiTraceInit(unsigned int major_version, unsigned
1919
PTI_XPTI_HOOK_VISIBILITY void xptiTraceFinish(const char* stream_name); // NOLINT
2020
}
2121

22+
std::pair<bool, bool> IsForeignXPTISubscriber();
23+
2224
#endif // SRC_XPTI_ADAPTER_H_

sdk/test/CMakeLists.txt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,23 +257,33 @@ if(HAVE_SYCL)
257257
add_executable(dpc_gemm_threaded_profiled perf_dpc_gemm_threaded.cc)
258258
add_executable(dpc_gemm_threaded_baseline perf_dpc_gemm_threaded.cc)
259259
add_executable(dpc_gemm_threaded_linkonly perf_dpc_gemm_threaded.cc)
260+
add_executable(dpc_gemm_threaded_prof_print perf_dpc_gemm_threaded.cc)
260261

261262
target_include_directories(
262263
dpc_gemm_threaded_profiled
263264
PUBLIC "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/include"
264265
"${PROJECT_SOURCE_DIR}/samples/samples_utilities"
265266
"${PROJECT_SOURCE_DIR}/src/utils")
266267

268+
target_include_directories(
269+
dpc_gemm_threaded_prof_print
270+
PUBLIC "${CMAKE_BINARY_DIR}" "${PROJECT_SOURCE_DIR}/include"
271+
"${PROJECT_SOURCE_DIR}/samples/samples_utilities"
272+
"${PROJECT_SOURCE_DIR}/src/utils")
273+
267274
target_compile_options(dpc_gemm_threaded_profiled PRIVATE -fsycl -gline-tables-only)
268275
target_compile_options(dpc_gemm_threaded_baseline PRIVATE -fsycl -gline-tables-only)
269276
target_compile_options(dpc_gemm_threaded_linkonly PRIVATE -fsycl -gline-tables-only)
277+
target_compile_options(dpc_gemm_threaded_prof_print PRIVATE -fsycl -gline-tables-only)
270278

271279
target_compile_definitions(dpc_gemm_threaded_baseline PRIVATE NO_PTI)
272280
target_compile_definitions(dpc_gemm_threaded_linkonly PRIVATE NO_PTI)
281+
target_compile_definitions(dpc_gemm_threaded_prof_print PRIVATE RECORD_PARSE_AND_PRINT)
273282

274283
target_link_options(dpc_gemm_threaded_profiled PRIVATE -fsycl -gline-tables-only)
275284
target_link_options(dpc_gemm_threaded_baseline PRIVATE -fsycl -gline-tables-only)
276285
target_link_options(dpc_gemm_threaded_linkonly PRIVATE -fsycl -gline-tables-only)
286+
target_link_options(dpc_gemm_threaded_prof_print PRIVATE -fsycl -gline-tables-only)
277287

278288
target_link_libraries(dpc_gemm_threaded_profiled PUBLIC spdlog::spdlog
279289
Threads::Threads Pti::pti_view)
@@ -283,6 +293,9 @@ if(HAVE_SYCL)
283293

284294
target_link_libraries(dpc_gemm_threaded_baseline PUBLIC Threads::Threads)
285295

296+
target_link_libraries(dpc_gemm_threaded_prof_print PUBLIC spdlog::spdlog
297+
Threads::Threads Pti::pti_view)
298+
286299
gtest_discover_tests(
287300
dpcgemm_suite
288301
DISCOVERY_TIMEOUT 60
@@ -415,6 +428,14 @@ if(HAVE_SYCL)
415428
set_tests_properties(
416429
perf-overhead-view PROPERTIES LABELS "performance; functional")
417430

431+
# Add interoperability test
432+
add_test(
433+
NAME xpti_interop_test
434+
COMMAND ${Python_EXECUTABLE} ${PROJECT_SOURCE_DIR}/test/xpti_interop_test.py "${PTI_TEST_BIN_DIR}"
435+
)
436+
set_tests_properties(
437+
xpti_interop_test PROPERTIES LABELS "interop; functional")
438+
418439
endif()
419440

420441
if (HAVE_SYCL AND TARGET unified-runtime::loader)

0 commit comments

Comments
 (0)