From 2af0599deb7025eb77e695d3eca299c1c5dd6e20 Mon Sep 17 00:00:00 2001 From: Alexander Batashev Date: Wed, 28 Jul 2021 13:23:49 +0300 Subject: [PATCH] [SYCL][XPTI] Pass plugin information to subscribers (#4121) This patch makes the following additional information available to XPTI subscribers. All streams: - Actual major and minor versions of SYCL runtime (instead of dummy values) as well as their string variant. `sycl.pi.debug` stream: - Backend type, which is defined as a `uint8_t` value of `sycl::backend` enum. - Pointer to PI plugin to provide some degree of application flow variance (e.g. query additional info about device, USM pointers, memory, etc). --- sycl/include/CL/sycl/detail/pi.hpp | 7 ++++-- sycl/source/detail/pi.cpp | 20 +++++++++++------ sycl/source/detail/plugin.hpp | 4 ++-- sycl/tools/pi-trace/pi_trace.cpp | 17 ++++++++------ .../xpti_helpers/pi_arguments_handler.hpp | 22 ++++++++++++++----- sycl/unittests/pi/pi_arguments_handler.cpp | 16 ++++++++------ 6 files changed, 55 insertions(+), 31 deletions(-) diff --git a/sycl/include/CL/sycl/detail/pi.hpp b/sycl/include/CL/sycl/detail/pi.hpp index a0f553309b5cf..3651c67cf0e56 100644 --- a/sycl/include/CL/sycl/detail/pi.hpp +++ b/sycl/include/CL/sycl/detail/pi.hpp @@ -189,8 +189,10 @@ void emitFunctionEndTrace(uint64_t CorrelationID, const char *FName); /// \param FuncID is the API hash ID from PiApiID type trait. /// \param FName The name of the PI API call. /// \param ArgsData is a pointer to packed function call arguments. +/// \param Plugin is the plugin, which is used to make call. uint64_t emitFunctionWithArgsBeginTrace(uint32_t FuncID, const char *FName, - unsigned char *ArgsData); + unsigned char *ArgsData, + pi_plugin Plugin); /// Notifies XPTI subscribers about PI function call result. /// @@ -200,9 +202,10 @@ uint64_t emitFunctionWithArgsBeginTrace(uint32_t FuncID, const char *FName, /// \param FName The name of the PI API call. /// \param ArgsData is a pointer to packed function call arguments. /// \param Result is function call result value. +/// \param Plugin is the plugin, which is used to make call. void emitFunctionWithArgsEndTrace(uint64_t CorrelationID, uint32_t FuncID, const char *FName, unsigned char *ArgsData, - pi_result Result); + pi_result Result, pi_plugin Plugin); // A wrapper for passing around byte array properties class ByteArray { diff --git a/sycl/source/detail/pi.cpp b/sycl/source/detail/pi.cpp index 29172be0891b8..7db4a3f073704 100644 --- a/sycl/source/detail/pi.cpp +++ b/sycl/source/detail/pi.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,10 @@ #include "xpti_trace_framework.h" #endif +#define STR(x) #x +#define SYCL_VERSION_STR \ + "sycl " STR(__LIBSYCL_MAJOR_VERSION) "." STR(__LIBSYCL_MINOR_VERSION) + __SYCL_INLINE_NAMESPACE(cl) { namespace sycl { namespace detail { @@ -50,9 +55,9 @@ xpti_td *GPICallEvent = nullptr; xpti_td *GPIArgCallEvent = nullptr; /// Constants being used as placeholder until one is able to reliably get the /// version of the SYCL runtime -constexpr uint32_t GMajVer = 1; -constexpr uint32_t GMinVer = 0; -constexpr const char *GVerStr = "sycl 1.0"; +constexpr uint32_t GMajVer = __LIBSYCL_MAJOR_VERSION; +constexpr uint32_t GMinVer = __LIBSYCL_MINOR_VERSION; +constexpr const char *GVerStr = SYCL_VERSION_STR; #endif // XPTI_ENABLE_INSTRUMENTATION template @@ -138,7 +143,8 @@ void emitFunctionEndTrace(uint64_t CorrelationID, const char *FName) { } uint64_t emitFunctionWithArgsBeginTrace(uint32_t FuncID, const char *FuncName, - unsigned char *ArgsData) { + unsigned char *ArgsData, + pi_plugin Plugin) { uint64_t CorrelationID = 0; #ifdef XPTI_ENABLE_INSTRUMENTATION if (xptiTraceEnabled()) { @@ -146,7 +152,7 @@ uint64_t emitFunctionWithArgsBeginTrace(uint32_t FuncID, const char *FuncName, CorrelationID = xptiGetUniqueId(); xpti::function_with_args_t Payload{FuncID, FuncName, ArgsData, nullptr, - nullptr}; + &Plugin}; xptiNotifySubscribers( StreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_begin, @@ -158,13 +164,13 @@ uint64_t emitFunctionWithArgsBeginTrace(uint32_t FuncID, const char *FuncName, void emitFunctionWithArgsEndTrace(uint64_t CorrelationID, uint32_t FuncID, const char *FuncName, unsigned char *ArgsData, - pi_result Result) { + pi_result Result, pi_plugin Plugin) { #ifdef XPTI_ENABLE_INSTRUMENTATION if (xptiTraceEnabled()) { uint8_t StreamID = xptiRegisterStream(SYCL_PIDEBUGCALL_STREAM_NAME); xpti::function_with_args_t Payload{FuncID, FuncName, ArgsData, &Result, - nullptr}; + &Plugin}; xptiNotifySubscribers( StreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_end, diff --git a/sycl/source/detail/plugin.hpp b/sycl/source/detail/plugin.hpp index 0e490c992e908..bfd614893f221 100644 --- a/sycl/source/detail/plugin.hpp +++ b/sycl/source/detail/plugin.hpp @@ -144,7 +144,7 @@ class plugin { auto ArgsData = packCallArguments(std::forward(Args)...); uint64_t CorrelationIDWithArgs = pi::emitFunctionWithArgsBeginTrace( - static_cast(PiApiOffset), PIFnName, ArgsData.data()); + static_cast(PiApiOffset), PIFnName, ArgsData.data(), MPlugin); #endif RT::PiResult R; if (pi::trace(pi::TraceLevel::PI_TRACE_CALLS)) { @@ -165,7 +165,7 @@ class plugin { pi::emitFunctionEndTrace(CorrelationID, PIFnName); pi::emitFunctionWithArgsEndTrace(CorrelationIDWithArgs, static_cast(PiApiOffset), - PIFnName, ArgsData.data(), R); + PIFnName, ArgsData.data(), R, MPlugin); #endif return R; } diff --git a/sycl/tools/pi-trace/pi_trace.cpp b/sycl/tools/pi-trace/pi_trace.cpp index 78cc1165808f1..5a355e407a484 100644 --- a/sycl/tools/pi-trace/pi_trace.cpp +++ b/sycl/tools/pi-trace/pi_trace.cpp @@ -51,12 +51,13 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int /*major_version*/, tpCallback); #define _PI_API(api) \ - ArgHandler.set##_##api([](auto &&... Args) { \ - std::cout << "---> " << #api << "(" \ - << "\n"; \ - sycl::detail::pi::printArgs(Args...); \ - std::cout << ") ---> "; \ - }); + ArgHandler.set##_##api( \ + [](const pi_plugin &, std::optional, auto &&... Args) { \ + std::cout << "---> " << #api << "(" \ + << "\n"; \ + sycl::detail::pi::printArgs(Args...); \ + std::cout << ") ---> "; \ + }); #include #undef _PI_API } @@ -77,8 +78,10 @@ XPTI_CALLBACK_API void tpCallback(uint16_t TraceType, const auto *Data = static_cast(UserData); + const auto *Plugin = static_cast(Data->user_data); - ArgHandler.handle(Data->function_id, Data->args_data); + ArgHandler.handle(Data->function_id, *Plugin, std::nullopt, + Data->args_data); std::cout << *static_cast(Data->ret_data) << "\n"; } } diff --git a/sycl/tools/xpti_helpers/pi_arguments_handler.hpp b/sycl/tools/xpti_helpers/pi_arguments_handler.hpp index 4cad50ba90c66..08049cef70d20 100644 --- a/sycl/tools/xpti_helpers/pi_arguments_handler.hpp +++ b/sycl/tools/xpti_helpers/pi_arguments_handler.hpp @@ -1,4 +1,5 @@ //==---------- pi_arguments_handler.hpp - PI call arguments handler --------==// +// i // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -12,6 +13,7 @@ #include #include +#include #include __SYCL_INLINE_NAMESPACE(cl) { @@ -41,7 +43,8 @@ inline TupleT unpack(char *Data, template struct to_function {}; template struct to_function> { - using type = std::function; + using type = + std::function, Args...)>; }; /// PiArgumentsHandler is a helper class to process incoming XPTI function call @@ -59,10 +62,11 @@ template struct to_function> { /// See sycl/tools/pi-trace/ for an example. class PiArgumentsHandler { public: - void handle(uint32_t ID, void *ArgsData) { + void handle(uint32_t ID, const pi_plugin &Plugin, + std::optional Result, void *ArgsData) { #define _PI_API(api) \ if (ID == static_cast(detail::PiApiKind::api)) { \ - MHandler##_##api(ArgsData); \ + MHandler##_##api(Plugin, Result, ArgsData); \ return; \ } #include @@ -73,13 +77,17 @@ class PiArgumentsHandler { void set##_##api( \ const typename to_function::args_type>::type &Handler) { \ - MHandler##_##api = [Handler](void *Data) { \ + MHandler##_##api = [Handler](const pi_plugin &Plugin, \ + std::optional Res, void *Data) { \ using TupleT = \ typename detail::function_traits::args_type; \ TupleT Tuple = unpack( \ (char *)Data, \ std::make_index_sequence::value>{}); \ - std::apply(Handler, Tuple); \ + const auto Wrapper = [&Plugin, Res, Handler](auto &... Args) { \ + Handler(Plugin, Res, Args...); \ + }; \ + std::apply(Wrapper, Tuple); \ }; \ } #include @@ -87,7 +95,9 @@ class PiArgumentsHandler { private: #define _PI_API(api) \ - std::function MHandler##_##api = [](void *) {}; + std::function, void *)> \ + MHandler##_##api = \ + [](const pi_plugin &, std::optional, void *) {}; #include #undef _PI_API }; diff --git a/sycl/unittests/pi/pi_arguments_handler.cpp b/sycl/unittests/pi/pi_arguments_handler.cpp index ce9d817b8a628..ca43ceb039b37 100644 --- a/sycl/unittests/pi/pi_arguments_handler.cpp +++ b/sycl/unittests/pi/pi_arguments_handler.cpp @@ -20,12 +20,13 @@ TEST(PiArgumentsHandlerTest, CanUnpackArguments) { const pi_uint32 NumPlatforms = 42; pi_platform *Platforms = new pi_platform[NumPlatforms]; - Handler.set_piPlatformsGet( - [&](pi_uint32 NP, pi_platform *Plts, pi_uint32 *Ret) { - EXPECT_EQ(NP, NumPlatforms); - EXPECT_EQ(Platforms, Plts); - EXPECT_EQ(Ret, nullptr); - }); + Handler.set_piPlatformsGet([&](const pi_plugin &, std::optional, + pi_uint32 NP, pi_platform *Plts, + pi_uint32 *Ret) { + EXPECT_EQ(NP, NumPlatforms); + EXPECT_EQ(Platforms, Plts); + EXPECT_EQ(Ret, nullptr); + }); constexpr size_t Size = sizeof(pi_uint32) + 2 * sizeof(void *); std::array Data{0}; @@ -33,8 +34,9 @@ TEST(PiArgumentsHandlerTest, CanUnpackArguments) { *reinterpret_cast(Data.data() + sizeof(pi_uint32)) = Platforms; + pi_plugin Plugin{}; uint32_t ID = static_cast(sycl::detail::PiApiKind::piPlatformsGet); - Handler.handle(ID, Data.data()); + Handler.handle(ID, Plugin, std::nullopt, Data.data()); delete[] Platforms; }