From 67dc249faf9e94d26546c3b6f105ee87d76358fc Mon Sep 17 00:00:00 2001 From: Alexander Batashev Date: Tue, 25 Jan 2022 16:46:04 +0300 Subject: [PATCH 1/6] [SYCL] Introduce XPTI-based tooling for SYCL applications sycl-trace - tracing tool that prints SYCL PI calls, analog to SYCL_PI_TRACE env variable sycl-prof - dumps profiling information from SYCL runtime and saves it to Chrome-compatible JSON file sycl-sanitize - provides some diagnostics based on SYCL PI calls. Currently this tool can diagnose USM memory leaks and abuse of USM pointers in SYCL buffers --- sycl/CMakeLists.txt | 10 + sycl/tools/CMakeLists.txt | 6 +- sycl/tools/pi-trace/CMakeLists.txt | 14 -- sycl/tools/sycl-prof/CMakeLists.txt | 36 +++ sycl/tools/sycl-prof/collector.cpp | 152 ++++++++++++ sycl/tools/sycl-prof/main.cpp | 61 +++++ sycl/tools/sycl-prof/writer.hpp | 88 +++++++ sycl/tools/sycl-sanitize/CMakeLists.txt | 34 +++ sycl/tools/sycl-sanitize/collector.cpp | 216 ++++++++++++++++++ sycl/tools/sycl-sanitize/main.cpp | 47 ++++ sycl/tools/sycl-trace/CMakeLists.txt | 35 +++ sycl/tools/sycl-trace/main.cpp | 56 +++++ .../pi_trace_collector.cpp} | 2 +- sycl/tools/xpti_helpers/launch.hpp | 24 ++ 14 files changed, 765 insertions(+), 16 deletions(-) delete mode 100644 sycl/tools/pi-trace/CMakeLists.txt create mode 100644 sycl/tools/sycl-prof/CMakeLists.txt create mode 100644 sycl/tools/sycl-prof/collector.cpp create mode 100644 sycl/tools/sycl-prof/main.cpp create mode 100644 sycl/tools/sycl-prof/writer.hpp create mode 100644 sycl/tools/sycl-sanitize/CMakeLists.txt create mode 100644 sycl/tools/sycl-sanitize/collector.cpp create mode 100644 sycl/tools/sycl-sanitize/main.cpp create mode 100644 sycl/tools/sycl-trace/CMakeLists.txt create mode 100644 sycl/tools/sycl-trace/main.cpp rename sycl/tools/{pi-trace/pi_trace.cpp => sycl-trace/pi_trace_collector.cpp} (99%) create mode 100644 sycl/tools/xpti_helpers/launch.hpp diff --git a/sycl/CMakeLists.txt b/sycl/CMakeLists.txt index 2f4043761e2c1..732151ebc3d66 100644 --- a/sycl/CMakeLists.txt +++ b/sycl/CMakeLists.txt @@ -308,6 +308,16 @@ set( SYCL_TOOLCHAIN_DEPLOY_COMPONENTS ${XPTIFW_LIBS} ) +if (TARGET sycl-prof) + list(APPEND SYCL_TOOLCHAIN_DEPLOY_COMPONENTS sycl-prof) +endif() +if (TARGET sycl-sanitize) + list(APPEND SYCL_TOOLCHAIN_DEPLOY_COMPONENTS sycl-sanitize) +endif() +if (TARGET sycl-trace) + list(APPEND SYCL_TOOLCHAIN_DEPLOY_COMPONENTS sycl-trace) +endif() + if(OpenCL_INSTALL_KHRONOS_ICD_LOADER AND TARGET OpenCL-ICD) list(APPEND SYCL_TOOLCHAIN_DEPLOY_COMPONENTS OpenCL-ICD) endif() diff --git a/sycl/tools/CMakeLists.txt b/sycl/tools/CMakeLists.txt index a4f5674826721..6164b24181718 100644 --- a/sycl/tools/CMakeLists.txt +++ b/sycl/tools/CMakeLists.txt @@ -1,7 +1,11 @@ add_subdirectory(sycl-ls) if (SYCL_ENABLE_XPTI_TRACING) - add_subdirectory(pi-trace) + if (UNIX) + add_subdirectory(sycl-prof) + add_subdirectory(sycl-trace) + # add_subdirectory(sycl-sanitize) + endif() endif() # TODO: move each tool in its own sub-directory diff --git a/sycl/tools/pi-trace/CMakeLists.txt b/sycl/tools/pi-trace/CMakeLists.txt deleted file mode 100644 index e305fd22dbede..0000000000000 --- a/sycl/tools/pi-trace/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -add_library(pi_trace SHARED pi_trace.cpp) -target_compile_definitions(pi_trace PRIVATE XPTI_CALLBACK_API_EXPORTS) -target_link_libraries(pi_trace PRIVATE xptifw) -if (TARGET OpenCL-Headers) - target_link_libraries(pi_trace PRIVATE OpenCL-Headers) -endif() - -target_include_directories(pi_trace PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}/../xpti_helpers/" - "${sycl_inc_dir}" - "${sycl_src_dir}" -) - -add_dependencies(sycl-toolchain pi_trace) diff --git a/sycl/tools/sycl-prof/CMakeLists.txt b/sycl/tools/sycl-prof/CMakeLists.txt new file mode 100644 index 0000000000000..87a8b0d3c8ed0 --- /dev/null +++ b/sycl/tools/sycl-prof/CMakeLists.txt @@ -0,0 +1,36 @@ +add_executable(sycl-prof + main.cpp +) + +target_include_directories(sycl-prof PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/../xpti_helpers/" +) + +target_link_libraries(sycl-prof PRIVATE + LLVMSupport +) + +target_compile_options(sycl-prof PRIVATE -fno-exceptions -fno-rtti) + +add_library(sycl_profiler_collector SHARED collector.cpp) +target_compile_definitions(sycl_profiler_collector PRIVATE XPTI_CALLBACK_API_EXPORTS) +target_link_libraries(sycl_profiler_collector PRIVATE xptifw) +if (TARGET OpenCL-Headers) + target_link_libraries(sycl_profiler_collector PRIVATE OpenCL-Headers) +endif() +target_include_directories(sycl_profiler_collector PRIVATE + "${sycl_inc_dir}" + "${sycl_src_dir}" +) + +target_compile_options(sycl_profiler_collector PRIVATE -g) + +add_dependencies(sycl-prof sycl_profiler_collector) +add_dependencies(sycl-toolchain sycl-prof) + +include(GNUInstallDirs) +install(TARGETS sycl-prof sycl_profiler_collector + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT sycl-prof + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT sycl-prof + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT sycl-prof +) diff --git a/sycl/tools/sycl-prof/collector.cpp b/sycl/tools/sycl-prof/collector.cpp new file mode 100644 index 0000000000000..763c0d4d8d62a --- /dev/null +++ b/sycl/tools/sycl-prof/collector.cpp @@ -0,0 +1,152 @@ +//==-------------- collector.cpp -------------------------------------------==// +// +// 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 "writer.hpp" +#include "xpti/xpti_data_types.h" + +#include +#include + +#include +#include +#include +#include +#include + +unsigned long process_id() { return static_cast(getpid()); } + +namespace chrono = std::chrono; + +Writer *GWriter = nullptr; + +XPTI_CALLBACK_API void piBeginEndCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t /*Instance*/, + const void *UserData); +XPTI_CALLBACK_API void taskBeginEndCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t /*Instance*/, + const void *UserData); +XPTI_CALLBACK_API void waitBeginEndCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t /*Instance*/, + const void *UserData); + +XPTI_CALLBACK_API void xptiTraceInit(unsigned int /*major_version*/, + unsigned int /*minor_version*/, + const char * /*version_str*/, + const char *StreamName) { + if (GWriter == nullptr) { + GWriter = new JSONWriter(std::getenv("SYCL_PROF_OUT_FILE")); + GWriter->init(); + } + + if (std::string_view(StreamName) == "sycl.pi") { + uint8_t StreamID = xptiRegisterStream(StreamName); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::function_begin, + piBeginEndCallback); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::function_end, + piBeginEndCallback); + } else if (std::string_view(StreamName) == "sycl") { + uint8_t StreamID = xptiRegisterStream(StreamName); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::task_begin, + taskBeginEndCallback); + xptiRegisterCallback(StreamID, (uint16_t)xpti::trace_point_type_t::task_end, + taskBeginEndCallback); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::wait_begin, + waitBeginEndCallback); + xptiRegisterCallback(StreamID, (uint16_t)xpti::trace_point_type_t::wait_end, + waitBeginEndCallback); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::barrier_begin, + waitBeginEndCallback); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::barrier_end, + waitBeginEndCallback); + } +} + +XPTI_CALLBACK_API void xptiTraceFinish(const char *) { GWriter->finalize(); } + +XPTI_CALLBACK_API void piBeginEndCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t /*Instance*/, + const void *UserData) { + unsigned long TID = std::hash{}(std::this_thread::get_id()); + unsigned long PID = process_id(); + auto Now = chrono::high_resolution_clock::now(); + auto TS = chrono::time_point_cast(Now) + .time_since_epoch() + .count(); + if (TraceType == (uint16_t)xpti::trace_point_type_t::function_begin) { + GWriter->writeBegin(static_cast(UserData), "Plugin", PID, TID, + TS); + } else { + GWriter->writeEnd(static_cast(UserData), "Plugin", PID, TID, + TS); + } +} + +XPTI_CALLBACK_API void taskBeginEndCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *Event, + uint64_t /*Instance*/, + const void *) { + unsigned long TID = std::hash{}(std::this_thread::get_id()); + unsigned long PID = process_id(); + + std::string_view Name = "unknown"; + + xpti::metadata_t *Metadata = xptiQueryMetadata(Event); + for (auto &Item : *Metadata) { + std::string_view Key{xptiLookupString(Item.first)}; + if (Key == "kernel_name" || Key == "memory_object") { + Name = xptiLookupString(Item.second); + } + } + + auto Now = chrono::high_resolution_clock::now(); + auto TS = chrono::time_point_cast(Now) + .time_since_epoch() + .count(); + + if (TraceType == (uint16_t)xpti::trace_point_type_t::task_begin) { + GWriter->writeBegin(Name, "SYCL", PID, TID, TS); + } else { + GWriter->writeEnd(Name, "SYCL", PID, TID, TS); + } +} + +XPTI_CALLBACK_API void waitBeginEndCallback(uint16_t TraceType, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, + uint64_t /*Instance*/, + const void *UserData) { + unsigned long TID = std::hash{}(std::this_thread::get_id()); + unsigned long PID = process_id(); + auto Now = chrono::high_resolution_clock::now(); + auto TS = chrono::time_point_cast(Now) + .time_since_epoch() + .count(); + if (TraceType == (uint16_t)xpti::trace_point_type_t::wait_begin || + TraceType == (uint16_t)xpti::trace_point_type_t::barrier_begin) { + GWriter->writeBegin(static_cast(UserData), "SYCL", PID, TID, + TS); + } else { + GWriter->writeEnd(static_cast(UserData), "SYCL", PID, TID, + TS); + } +} diff --git a/sycl/tools/sycl-prof/main.cpp b/sycl/tools/sycl-prof/main.cpp new file mode 100644 index 0000000000000..826d9373983ac --- /dev/null +++ b/sycl/tools/sycl-prof/main.cpp @@ -0,0 +1,61 @@ +#include "launch.hpp" +#include "llvm/Support/CommandLine.h" + +#include +#include + +using namespace llvm; + +enum OutputFormatKind { JSON }; + +int main(int argc, char **argv, char *env[]) { + cl::opt OutputFormat( + "format", cl::desc("Set profiler output format:"), + cl::values( + // TODO performance summary + clEnumValN(JSON, "json", + "JSON file, compatible with chrome://tracing"))); + cl::opt OutputFilename("o", cl::desc("Specify output filename"), + cl::value_desc("filename"), cl::Required); + cl::opt TargetExecutable( + cl::Positional, cl::desc(""), cl::Required); + cl::list Argv(cl::ConsumeAfter, + cl::desc("...")); + + cl::ParseCommandLineOptions(argc, argv); + + std::vector NewEnv; + + { + size_t I = 0; + while (env[I] != nullptr) + NewEnv.push_back(env[I++]); + } + + std::string ProfOutFile = "SYCL_PROF_OUT_FILE=" + OutputFilename; + NewEnv.push_back(ProfOutFile.c_str()); + NewEnv.push_back("XPTI_FRAMEWORK_DISPATCHER=libxptifw.so"); + NewEnv.push_back("XPTI_SUBSCRIBERS=libsycl_profiler_collector.so"); + NewEnv.push_back("XPTI_TRACE_ENABLE=1"); + NewEnv.push_back(nullptr); + + std::vector Args; + + Args.push_back(TargetExecutable.c_str()); + + for (auto Arg : Argv) { + Args.push_back(Arg.c_str()); + } + + Args.push_back(nullptr); + + int Err = launch(TargetExecutable.c_str(), Args, NewEnv); + + if (Err) { + std::cerr << "Failed to launch target application. Error code " << Err + << "\n"; + return Err; + } + + return 0; +} diff --git a/sycl/tools/sycl-prof/writer.hpp b/sycl/tools/sycl-prof/writer.hpp new file mode 100644 index 0000000000000..72b6b40ba5e7f --- /dev/null +++ b/sycl/tools/sycl-prof/writer.hpp @@ -0,0 +1,88 @@ +//==----------------- writer.hpp -------------------------------------------==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include +#include +#include + +class Writer { +public: + virtual void init() = 0; + virtual void finalize() = 0; + virtual void writeBegin(std::string_view Name, std::string_view Category, + unsigned long PID, unsigned long TID, + unsigned long TimeStamp) = 0; + virtual void writeEnd(std::string_view Name, std::string_view Category, + unsigned long PID, unsigned long TID, + unsigned long TimeStamp) = 0; + virtual ~Writer() = default; +}; + +class JSONWriter : public Writer { +public: + explicit JSONWriter(std::filesystem::path OutPath) : MOutFile(OutPath) {} + + void init() final { + std::lock_guard _{MWriteMutex}; + + MOutFile << "{\n"; + MOutFile << " \"traceEvents\": [\n"; + } + + void writeBegin(std::string_view Name, std::string_view Category, + unsigned long PID, unsigned long TID, + unsigned long TimeStamp) override { + std::lock_guard _{MWriteMutex}; + + if (!MOutFile.is_open()) + return; + + MOutFile << "{\"name\": \"" << Name << "\", "; + MOutFile << "\"cat\": \"" << Category << "\", "; + MOutFile << "\"ph\": \"B\", "; + MOutFile << "\"pid\": \"" << PID << "\", "; + MOutFile << "\"tid\": \"" << TID << "\", "; + MOutFile << "\"ts\": \"" << TimeStamp << "\"},\n"; + } + + void writeEnd(std::string_view Name, std::string_view Category, + unsigned long PID, unsigned long TID, + unsigned long TimeStamp) override { + std::lock_guard _{MWriteMutex}; + + if (!MOutFile.is_open()) + return; + + MOutFile << "{\"name\": \"" << Name << "\", "; + MOutFile << "\"cat\": \"" << Category << "\", "; + MOutFile << "\"ph\": \"E\", "; + MOutFile << "\"pid\": \"" << PID << "\", "; + MOutFile << "\"tid\": \"" << TID << "\", "; + MOutFile << "\"ts\": \"" << TimeStamp << "\"},\n"; + } + + void finalize() final { + std::lock_guard _{MWriteMutex}; + + if (!MOutFile.is_open()) + return; + + MOutFile << "],\n"; + MOutFile << "\"displayTimeUnit\":\"ns\"\n}\n"; + MOutFile.close(); + } + + ~JSONWriter() { finalize(); } + +private: + std::mutex MWriteMutex; + std::ofstream MOutFile; +}; diff --git a/sycl/tools/sycl-sanitize/CMakeLists.txt b/sycl/tools/sycl-sanitize/CMakeLists.txt new file mode 100644 index 0000000000000..9e21065a83415 --- /dev/null +++ b/sycl/tools/sycl-sanitize/CMakeLists.txt @@ -0,0 +1,34 @@ +add_executable(sycl-sanitize main.cpp) + +target_include_directories(sycl-sanitize PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/../xpti_helpers/" +) + +target_link_libraries(sycl-sanitize PRIVATE + LLVMSupport +) + +target_compile_options(sycl-sanitize PRIVATE -fno-exceptions -fno-rtti) + +add_library(sycl_sanitizer_collector SHARED collector.cpp) +target_compile_definitions(sycl_sanitizer_collector PRIVATE XPTI_CALLBACK_API_EXPORTS) +target_link_libraries(sycl_sanitizer_collector PRIVATE xptifw) +if (TARGET OpenCL-Headers) + target_link_libraries(sycl_sanitizer_collector PRIVATE OpenCL-Headers) +endif() + +target_include_directories(sycl_sanitizer_collector PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/../xpti_helpers/" + "${sycl_inc_dir}" + "${sycl_src_dir}" +) + +add_dependencies(sycl-sanitize sycl_sanitizer_collector) +add_dependencies(sycl-toolchain sycl-sanitize) + +include(GNUInstallDirs) +install(TARGETS sycl-sanitize sycl_sanitizer_collector + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT sycl-sanitize + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT sycl-sanitize + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT sycl-sanitize +) diff --git a/sycl/tools/sycl-sanitize/collector.cpp b/sycl/tools/sycl-sanitize/collector.cpp new file mode 100644 index 0000000000000..d0766f2230c6b --- /dev/null +++ b/sycl/tools/sycl-sanitize/collector.cpp @@ -0,0 +1,216 @@ +//==-------------- collector.cpp -------------------------------------------==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +/// \file collector.cpp +/// The SYCL sanitizer collector intercepts PI calls to find memory leaks in +/// usages of USM pointers. + +#include "xpti/xpti_trace_framework.h" + +#include "pi_arguments_handler.hpp" + +#include + +#include +#include +#include +#include +#include +#include + +struct TracepointInfo { + std::string Source; + std::string Function; + uint32_t Line; +}; + +enum class AllocKind { host, device, shared }; + +struct AllocationInfo { + size_t Length; + AllocKind Kind; + TracepointInfo Location; +}; + +struct GlobalState { + std::mutex IOMutex; + std::map ActivePointers; + TracepointInfo LastTracepoint; + sycl::xpti_helpers::PiArgumentsHandler ArgHandlerPostCall; + sycl::xpti_helpers::PiArgumentsHandler ArgHandlerPreCall; +}; + +GlobalState *GS = nullptr; + +static void handleUSMHostAlloc(const pi_plugin &, std::optional, + void **ResultPtr, pi_context, + pi_usm_mem_properties *, size_t Size, + pi_uint32) { + AllocationInfo Info; + Info.Location = GS->LastTracepoint; + Info.Length = Size; + Info.Kind = AllocKind::host; + GS->ActivePointers[*ResultPtr] = Info; +} + +static void handleUSMDeviceAlloc(const pi_plugin &, std::optional, + void **ResultPtr, pi_context, pi_device, + pi_usm_mem_properties *, size_t Size, + pi_uint32) { + AllocationInfo Info; + Info.Location = GS->LastTracepoint; + Info.Length = Size; + Info.Kind = AllocKind::device; + GS->ActivePointers[*ResultPtr] = Info; +} + +static void handleUSMSharedAlloc(const pi_plugin &, std::optional, + void **ResultPtr, pi_context, pi_device, + pi_usm_mem_properties *, size_t Size, + pi_uint32) { + AllocationInfo Info; + Info.Location = GS->LastTracepoint; + Info.Length = Size; + Info.Kind = AllocKind::shared; + GS->ActivePointers[*ResultPtr] = Info; +} + +static void handleUSMFree(const pi_plugin &, std::optional, + pi_context, void *Ptr) { + if (GS->ActivePointers.count(Ptr) == 0) { + std::cerr << "Attempt to free pointer " << std::hex << Ptr; + std::cerr << " that was not allocated with SYCL USM APIs.\n"; + std::cerr << " Location: function " << GS->LastTracepoint.Function; + std::cerr << " at " << GS->LastTracepoint.Source << ":"; + std::cerr << std::dec << GS->LastTracepoint.Line << "\n"; + std::terminate(); + } + GS->ActivePointers.erase(Ptr); +} + +static void handleMemBufferCreate(const pi_plugin &, std::optional, + pi_context, pi_mem_flags, size_t Size, + void *HostPtr, pi_mem *, + const pi_mem_properties *) { + for (const auto &Alloc : GS->ActivePointers) { + const void *Begin = Alloc.first; + const void *End = + static_cast(Alloc.first) + Alloc.second.Length; + // Host pointer was allocated with USM APIs + if (HostPtr >= Begin && HostPtr <= End) { + bool NeedsTerminate = false; + if (Alloc.second.Kind != AllocKind::host) { + std::cerr << "Attempt to construct a buffer with non-host pointer.\n"; + NeedsTerminate = true; + } + + const void *HostEnd = static_cast(HostPtr) + Size; + if (HostEnd > End) { + std::cerr << "Buffer size exceeds allocated host memory size.\n"; + NeedsTerminate = true; + } + + if (NeedsTerminate) { + std::cerr << " Allocation location: "; + std::cerr << " function " << Alloc.second.Location.Function << " at "; + std::cerr << Alloc.second.Location.Source << ":" + << Alloc.second.Location.Line << "\n"; + std::cerr << " Buffer location: "; + std::cerr << " function " << GS->LastTracepoint.Function << " at "; + std::cerr << GS->LastTracepoint.Source << ":" << GS->LastTracepoint.Line + << "\n"; + std::terminate(); + } + break; + } + } +} + +XPTI_CALLBACK_API void tpCallback(uint16_t trace_type, + xpti::trace_event_data_t *parent, + xpti::trace_event_data_t *event, + uint64_t instance, const void *user_data); + +XPTI_CALLBACK_API void xptiTraceInit(unsigned int /*major_version*/, + unsigned int /*minor_version*/, + const char * /*version_str*/, + const char *StreamName) { + if (std::string_view(StreamName) == "sycl.pi.debug") { + GS = new GlobalState; + uint8_t StreamID = xptiRegisterStream(StreamName); + xptiRegisterCallback( + StreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_begin, + tpCallback); + xptiRegisterCallback( + StreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_end, + tpCallback); + + GS->ArgHandlerPostCall.set_piextUSMHostAlloc(handleUSMHostAlloc); + GS->ArgHandlerPostCall.set_piextUSMDeviceAlloc(handleUSMDeviceAlloc); + GS->ArgHandlerPostCall.set_piextUSMSharedAlloc(handleUSMSharedAlloc); + GS->ArgHandlerPreCall.set_piextUSMFree(handleUSMFree); + GS->ArgHandlerPreCall.set_piMemBufferCreate(handleMemBufferCreate); + } +} + +XPTI_CALLBACK_API void xptiTraceFinish(const char *StreamName) { + if (std::string_view(StreamName) == "sycl.pi.debug") { + bool hadLeak = false; + if (GS->ActivePointers.size() > 0) { + hadLeak = true; + std::cerr << "Found " << GS->ActivePointers.size() + << " leaked memory allocations\n"; + for (const auto &Ptr : GS->ActivePointers) { + std::cerr << "Leaked pointer: " << std::hex << Ptr.first << "\n"; + std::cerr << " Location: " + << "function " << Ptr.second.Location.Function << " at " + << Ptr.second.Location.Source << ":" << std::dec + << Ptr.second.Location.Line << "\n"; + } + } + + delete GS; + if (hadLeak) + exit(-1); + } +} + +XPTI_CALLBACK_API void tpCallback(uint16_t TraceType, + xpti::trace_event_data_t *Parent, + xpti::trace_event_data_t *Event, + uint64_t /*Instance*/, const void *UserData) { + auto *Payload = xptiQueryPayloadByUID(xptiGetUniversalId()); + + if (Payload) { + if (Payload->source_file) + GS->LastTracepoint.Source = Payload->source_file; + else + GS->LastTracepoint.Source = ""; + GS->LastTracepoint.Function = Payload->name; + GS->LastTracepoint.Line = Payload->line_no; + } else { + GS->LastTracepoint.Function = ""; + GS->LastTracepoint.Source = ""; + GS->LastTracepoint.Line = 0; + } + + auto Type = static_cast(TraceType); + // Lock while we capture information + std::lock_guard Lock(GS->IOMutex); + + const auto *Data = static_cast(UserData); + const auto *Plugin = static_cast(Data->user_data); + if (Type == xpti::trace_point_type_t::function_with_args_begin) { + GS->ArgHandlerPreCall.handle(Data->function_id, *Plugin, std::nullopt, + Data->args_data); + } else if (Type == xpti::trace_point_type_t::function_with_args_end) { + const pi_result Result = *static_cast(Data->ret_data); + GS->ArgHandlerPostCall.handle(Data->function_id, *Plugin, Result, + Data->args_data); + } +} diff --git a/sycl/tools/sycl-sanitize/main.cpp b/sycl/tools/sycl-sanitize/main.cpp new file mode 100644 index 0000000000000..86bfee15ce40f --- /dev/null +++ b/sycl/tools/sycl-sanitize/main.cpp @@ -0,0 +1,47 @@ +#include "llvm/Support/CommandLine.h" + +#include + +using namespace llvm; + +int main(int argc, char **argv, char *env[]) { + cl::opt TargetExecutable( + cl::Positional, cl::desc(""), cl::Required); + cl::list Argv(cl::ConsumeAfter, + cl::desc("...")); + + cl::ParseCommandLineOptions(argc, argv); + + std::vector NewEnv; + + { + size_t I = 0; + while (env[I] != nullptr) + NewEnv.push_back(env[I++]); + } + + NewEnv.push_back("XPTI_FRAMEWORK_DISPATCHER=libxptifw.so"); + NewEnv.push_back("XPTI_SUBSCRIBERS=libsycl_sanitizer_collector.so"); + NewEnv.push_back("XPTI_TRACE_ENABLE=1"); + NewEnv.push_back(nullptr); + + std::vector Args; + + Args.push_back(TargetExecutable.c_str()); + + for (auto Arg : Argv) { + Args.push_back(Arg.c_str()); + } + + Args.push_back(nullptr); + + int Err = launch(TargetExecutable.c_str(), Args, NewEnv); + + if (Err) { + std::cerr << "Failed to launch target application. Error code " << Err + << "\n"; + return Err; + } + + return 0; +} diff --git a/sycl/tools/sycl-trace/CMakeLists.txt b/sycl/tools/sycl-trace/CMakeLists.txt new file mode 100644 index 0000000000000..f07bc587b8490 --- /dev/null +++ b/sycl/tools/sycl-trace/CMakeLists.txt @@ -0,0 +1,35 @@ +add_executable(sycl-trace main.cpp) + +target_include_directories(sycl-trace PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/../xpti_helpers/" +) + +target_compile_options(sycl-trace PRIVATE -fno-exceptions -fno-rtti) + +target_link_libraries(sycl-trace PRIVATE + LLVMSupport +) + +add_library(sycl_pi_trace_collector SHARED pi_trace_collector.cpp) +target_compile_definitions(sycl_pi_trace_collector PRIVATE XPTI_CALLBACK_API_EXPORTS) +target_link_libraries(sycl_pi_trace_collector PRIVATE xptifw) +if (TARGET OpenCL-Headers) + target_link_libraries(sycl_pi_trace_collector PRIVATE OpenCL-Headers) +endif() + +target_include_directories(sycl_pi_trace_collector PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/../xpti_helpers/" + "${sycl_inc_dir}" + "${sycl_src_dir}" +) + +add_dependencies(sycl-trace sycl_pi_trace_collector) +add_dependencies(sycl-toolchain sycl-trace) + +include(GNUInstallDirs) +install(TARGETS sycl-trace sycl_pi_trace_collector + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT sycl-trace + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT sycl-trace + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT sycl-trace +) + diff --git a/sycl/tools/sycl-trace/main.cpp b/sycl/tools/sycl-trace/main.cpp new file mode 100644 index 0000000000000..bc699be3a935a --- /dev/null +++ b/sycl/tools/sycl-trace/main.cpp @@ -0,0 +1,56 @@ +#include "launch.hpp" +#include "llvm/Support/CommandLine.h" + +#include +#include + +using namespace llvm; + +enum ModeKind { PI }; + +int main(int argc, char **argv, char *env[]) { + cl::opt Mode( + "mode", cl::desc("Set tracing mode:"), + cl::values( + // TODO graph dot + clEnumValN(PI, "plugin", "Trace Plugin Interface calls"))); + cl::opt TargetExecutable( + cl::Positional, cl::desc(""), cl::Required); + cl::list Argv(cl::ConsumeAfter, + cl::desc("...")); + + cl::ParseCommandLineOptions(argc, argv); + + std::vector NewEnv; + + { + size_t I = 0; + while (env[I] != nullptr) + NewEnv.push_back(env[I++]); + } + + NewEnv.push_back("XPTI_FRAMEWORK_DISPATCHER=libxptifw.so"); + NewEnv.push_back("XPTI_SUBSCRIBERS=libsycl_pi_trace_collector.so"); + NewEnv.push_back("XPTI_TRACE_ENABLE=1"); + NewEnv.push_back(nullptr); + + std::vector Args; + + Args.push_back(TargetExecutable.c_str()); + + for (auto Arg : Argv) { + Args.push_back(Arg.c_str()); + } + + Args.push_back(nullptr); + + int Err = launch(TargetExecutable.c_str(), Args, NewEnv); + + if (Err) { + std::cerr << "Failed to launch target application. Error code " << Err + << "\n"; + return Err; + } + + return 0; +} diff --git a/sycl/tools/pi-trace/pi_trace.cpp b/sycl/tools/sycl-trace/pi_trace_collector.cpp similarity index 99% rename from sycl/tools/pi-trace/pi_trace.cpp rename to sycl/tools/sycl-trace/pi_trace_collector.cpp index d75b3eebf3bc1..7bab30a66e7af 100644 --- a/sycl/tools/pi-trace/pi_trace.cpp +++ b/sycl/tools/sycl-trace/pi_trace_collector.cpp @@ -52,7 +52,7 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int /*major_version*/, #define _PI_API(api) \ ArgHandler.set##_##api( \ - [](const pi_plugin &, std::optional, auto &&... Args) { \ + [](const pi_plugin &, std::optional, auto &&...Args) { \ std::cout << "---> " << #api << "(" \ << "\n"; \ sycl::detail::pi::printArgs(Args...); \ diff --git a/sycl/tools/xpti_helpers/launch.hpp b/sycl/tools/xpti_helpers/launch.hpp new file mode 100644 index 0000000000000..239d9252e376c --- /dev/null +++ b/sycl/tools/xpti_helpers/launch.hpp @@ -0,0 +1,24 @@ +//==----------------- launch.hpp -------------------------------------------==// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +/// Launches external application. +/// +/// \param Cmd is a path (full, relative, executable name in PATH) to executable +/// \param Args is program arguments. First argument is executable name. Last +/// argument is nullptr. +/// \param Env is program environment variables. Last variable is nullptr. +int launch(const char *Cmd, const std::vector &Args, + const std::vector &Env) { + return execve(Cmd, const_cast(Args.data()), + const_cast(Env.data())); +} From 9da103dd6c932d245eb59c381b341107815fe283 Mon Sep 17 00:00:00 2001 From: Alexander Batashev Date: Mon, 7 Feb 2022 18:56:52 +0300 Subject: [PATCH 2/6] some fixes --- sycl/tools/CMakeLists.txt | 2 +- sycl/tools/sycl-prof/main.cpp | 10 +++++++++- sycl/tools/sycl-prof/writer.hpp | 9 +++++---- sycl/tools/sycl-sanitize/main.cpp | 10 +++++++++- sycl/tools/sycl-trace/main.cpp | 10 +++++++++- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/sycl/tools/CMakeLists.txt b/sycl/tools/CMakeLists.txt index 6164b24181718..39805d41b9497 100644 --- a/sycl/tools/CMakeLists.txt +++ b/sycl/tools/CMakeLists.txt @@ -4,7 +4,7 @@ if (SYCL_ENABLE_XPTI_TRACING) if (UNIX) add_subdirectory(sycl-prof) add_subdirectory(sycl-trace) - # add_subdirectory(sycl-sanitize) + add_subdirectory(sycl-sanitize) endif() endif() diff --git a/sycl/tools/sycl-prof/main.cpp b/sycl/tools/sycl-prof/main.cpp index 826d9373983ac..31ec0813dcb3f 100644 --- a/sycl/tools/sycl-prof/main.cpp +++ b/sycl/tools/sycl-prof/main.cpp @@ -1,3 +1,11 @@ +//==------------ main.cpp - SYCL Profiler Tool -----------------------------==// +// +// 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 "launch.hpp" #include "llvm/Support/CommandLine.h" @@ -43,7 +51,7 @@ int main(int argc, char **argv, char *env[]) { Args.push_back(TargetExecutable.c_str()); - for (auto Arg : Argv) { + for (auto &Arg : Argv) { Args.push_back(Arg.c_str()); } diff --git a/sycl/tools/sycl-prof/writer.hpp b/sycl/tools/sycl-prof/writer.hpp index 72b6b40ba5e7f..98b7e4fbcbbc0 100644 --- a/sycl/tools/sycl-prof/writer.hpp +++ b/sycl/tools/sycl-prof/writer.hpp @@ -8,7 +8,6 @@ #pragma once -#include #include #include #include @@ -28,7 +27,7 @@ class Writer { class JSONWriter : public Writer { public: - explicit JSONWriter(std::filesystem::path OutPath) : MOutFile(OutPath) {} + explicit JSONWriter(const std::string &OutPath) : MOutFile(OutPath) {} void init() final { std::lock_guard _{MWriteMutex}; @@ -50,7 +49,8 @@ class JSONWriter : public Writer { MOutFile << "\"ph\": \"B\", "; MOutFile << "\"pid\": \"" << PID << "\", "; MOutFile << "\"tid\": \"" << TID << "\", "; - MOutFile << "\"ts\": \"" << TimeStamp << "\"},\n"; + MOutFile << "\"ts\": \"" << TimeStamp << "\"},"; + MOutFile << std::endl; } void writeEnd(std::string_view Name, std::string_view Category, @@ -66,7 +66,8 @@ class JSONWriter : public Writer { MOutFile << "\"ph\": \"E\", "; MOutFile << "\"pid\": \"" << PID << "\", "; MOutFile << "\"tid\": \"" << TID << "\", "; - MOutFile << "\"ts\": \"" << TimeStamp << "\"},\n"; + MOutFile << "\"ts\": \"" << TimeStamp << "\"},"; + MOutFile << std::endl; } void finalize() final { diff --git a/sycl/tools/sycl-sanitize/main.cpp b/sycl/tools/sycl-sanitize/main.cpp index 86bfee15ce40f..d6c0eb54ecc81 100644 --- a/sycl/tools/sycl-sanitize/main.cpp +++ b/sycl/tools/sycl-sanitize/main.cpp @@ -1,3 +1,11 @@ +//==------------ main.cpp - SYCL Sanitizer Tool ----------------------------==// +// +// 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 "llvm/Support/CommandLine.h" #include @@ -29,7 +37,7 @@ int main(int argc, char **argv, char *env[]) { Args.push_back(TargetExecutable.c_str()); - for (auto Arg : Argv) { + for (auto &Arg : Argv) { Args.push_back(Arg.c_str()); } diff --git a/sycl/tools/sycl-trace/main.cpp b/sycl/tools/sycl-trace/main.cpp index bc699be3a935a..23a37a6bd17df 100644 --- a/sycl/tools/sycl-trace/main.cpp +++ b/sycl/tools/sycl-trace/main.cpp @@ -1,3 +1,11 @@ +//==------------ main.cpp - SYCL Tracing Tool ------------------------------==// +// +// 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 "launch.hpp" #include "llvm/Support/CommandLine.h" @@ -38,7 +46,7 @@ int main(int argc, char **argv, char *env[]) { Args.push_back(TargetExecutable.c_str()); - for (auto Arg : Argv) { + for (auto &Arg : Argv) { Args.push_back(Arg.c_str()); } From ac51c0a8acdf104195e6580d96c100f890f5489e Mon Sep 17 00:00:00 2001 From: Alexander Batashev Date: Tue, 8 Feb 2022 09:36:47 +0300 Subject: [PATCH 3/6] More fixes --- sycl/tools/sycl-sanitize/collector.cpp | 4 ++-- sycl/tools/sycl-sanitize/main.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sycl/tools/sycl-sanitize/collector.cpp b/sycl/tools/sycl-sanitize/collector.cpp index d0766f2230c6b..de5b233c87851 100644 --- a/sycl/tools/sycl-sanitize/collector.cpp +++ b/sycl/tools/sycl-sanitize/collector.cpp @@ -181,8 +181,8 @@ XPTI_CALLBACK_API void xptiTraceFinish(const char *StreamName) { } XPTI_CALLBACK_API void tpCallback(uint16_t TraceType, - xpti::trace_event_data_t *Parent, - xpti::trace_event_data_t *Event, + xpti::trace_event_data_t *, + xpti::trace_event_data_t *, uint64_t /*Instance*/, const void *UserData) { auto *Payload = xptiQueryPayloadByUID(xptiGetUniversalId()); diff --git a/sycl/tools/sycl-sanitize/main.cpp b/sycl/tools/sycl-sanitize/main.cpp index d6c0eb54ecc81..2586a7a32240e 100644 --- a/sycl/tools/sycl-sanitize/main.cpp +++ b/sycl/tools/sycl-sanitize/main.cpp @@ -6,8 +6,10 @@ // //===----------------------------------------------------------------------===// +#include "launch.hpp" #include "llvm/Support/CommandLine.h" +#include #include using namespace llvm; From b6a5997e8bdc156d15231d82f7e0bd44f79b711f Mon Sep 17 00:00:00 2001 From: Alexander Batashev Date: Wed, 23 Feb 2022 10:13:54 +0300 Subject: [PATCH 4/6] address comments --- sycl/tools/sycl-prof/collector.cpp | 75 +++++++++----------- sycl/tools/sycl-prof/writer.hpp | 16 ++--- sycl/tools/sycl-sanitize/collector.cpp | 15 ++-- sycl/tools/sycl-trace/pi_trace_collector.cpp | 13 ++-- xpti/include/xpti/xpti_data_types.h | 8 +++ 5 files changed, 59 insertions(+), 68 deletions(-) diff --git a/sycl/tools/sycl-prof/collector.cpp b/sycl/tools/sycl-prof/collector.cpp index 763c0d4d8d62a..1830e4a730b99 100644 --- a/sycl/tools/sycl-prof/collector.cpp +++ b/sycl/tools/sycl-prof/collector.cpp @@ -18,12 +18,30 @@ #include #include -unsigned long process_id() { return static_cast(getpid()); } namespace chrono = std::chrono; Writer *GWriter = nullptr; +struct Measurements { + size_t TID; + size_t PID; + size_t TimeStamp; +}; + +unsigned long process_id() { return static_cast(getpid()); } + +static Measurements measure() { + size_t TID = std::hash{}(std::this_thread::get_id()); + size_t PID = process_id(); + auto Now = chrono::high_resolution_clock::now(); + size_t TS = chrono::time_point_cast(Now) + .time_since_epoch() + .count(); + + return Measurements{TID, PID, TS}; +} + XPTI_CALLBACK_API void piBeginEndCallback(uint16_t TraceType, xpti::trace_event_data_t *, xpti::trace_event_data_t *, @@ -51,29 +69,21 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int /*major_version*/, if (std::string_view(StreamName) == "sycl.pi") { uint8_t StreamID = xptiRegisterStream(StreamName); - xptiRegisterCallback(StreamID, - (uint16_t)xpti::trace_point_type_t::function_begin, + xptiRegisterCallback(StreamID, xpti::trace_function_begin, piBeginEndCallback); - xptiRegisterCallback(StreamID, - (uint16_t)xpti::trace_point_type_t::function_end, + xptiRegisterCallback(StreamID, xpti::trace_function_end, piBeginEndCallback); } else if (std::string_view(StreamName) == "sycl") { uint8_t StreamID = xptiRegisterStream(StreamName); - xptiRegisterCallback(StreamID, - (uint16_t)xpti::trace_point_type_t::task_begin, + xptiRegisterCallback(StreamID, xpti::trace_task_begin, taskBeginEndCallback); - xptiRegisterCallback(StreamID, (uint16_t)xpti::trace_point_type_t::task_end, - taskBeginEndCallback); - xptiRegisterCallback(StreamID, - (uint16_t)xpti::trace_point_type_t::wait_begin, - waitBeginEndCallback); - xptiRegisterCallback(StreamID, (uint16_t)xpti::trace_point_type_t::wait_end, + xptiRegisterCallback(StreamID, xpti::trace_task_end, taskBeginEndCallback); + xptiRegisterCallback(StreamID, xpti::trace_wait_begin, waitBeginEndCallback); - xptiRegisterCallback(StreamID, - (uint16_t)xpti::trace_point_type_t::barrier_begin, + xptiRegisterCallback(StreamID, xpti::trace_wait_end, waitBeginEndCallback); + xptiRegisterCallback(StreamID, xpti::trace_barrier_begin, waitBeginEndCallback); - xptiRegisterCallback(StreamID, - (uint16_t)xpti::trace_point_type_t::barrier_end, + xptiRegisterCallback(StreamID, xpti::trace_barrier_end, waitBeginEndCallback); } } @@ -85,13 +95,8 @@ XPTI_CALLBACK_API void piBeginEndCallback(uint16_t TraceType, xpti::trace_event_data_t *, uint64_t /*Instance*/, const void *UserData) { - unsigned long TID = std::hash{}(std::this_thread::get_id()); - unsigned long PID = process_id(); - auto Now = chrono::high_resolution_clock::now(); - auto TS = chrono::time_point_cast(Now) - .time_since_epoch() - .count(); - if (TraceType == (uint16_t)xpti::trace_point_type_t::function_begin) { + auto [TID, PID, TS] = measure(); + if (TraceType == xpti::trace_function_begin) { GWriter->writeBegin(static_cast(UserData), "Plugin", PID, TID, TS); } else { @@ -105,9 +110,6 @@ XPTI_CALLBACK_API void taskBeginEndCallback(uint16_t TraceType, xpti::trace_event_data_t *Event, uint64_t /*Instance*/, const void *) { - unsigned long TID = std::hash{}(std::this_thread::get_id()); - unsigned long PID = process_id(); - std::string_view Name = "unknown"; xpti::metadata_t *Metadata = xptiQueryMetadata(Event); @@ -118,12 +120,8 @@ XPTI_CALLBACK_API void taskBeginEndCallback(uint16_t TraceType, } } - auto Now = chrono::high_resolution_clock::now(); - auto TS = chrono::time_point_cast(Now) - .time_since_epoch() - .count(); - - if (TraceType == (uint16_t)xpti::trace_point_type_t::task_begin) { + auto [TID, PID, TS] = measure(); + if (TraceType == xpti::trace_task_begin) { GWriter->writeBegin(Name, "SYCL", PID, TID, TS); } else { GWriter->writeEnd(Name, "SYCL", PID, TID, TS); @@ -135,14 +133,9 @@ XPTI_CALLBACK_API void waitBeginEndCallback(uint16_t TraceType, xpti::trace_event_data_t *, uint64_t /*Instance*/, const void *UserData) { - unsigned long TID = std::hash{}(std::this_thread::get_id()); - unsigned long PID = process_id(); - auto Now = chrono::high_resolution_clock::now(); - auto TS = chrono::time_point_cast(Now) - .time_since_epoch() - .count(); - if (TraceType == (uint16_t)xpti::trace_point_type_t::wait_begin || - TraceType == (uint16_t)xpti::trace_point_type_t::barrier_begin) { + auto [TID, PID, TS] = measure(); + if (TraceType == xpti::trace_wait_begin || + TraceType == xpti::trace_barrier_begin) { GWriter->writeBegin(static_cast(UserData), "SYCL", PID, TID, TS); } else { diff --git a/sycl/tools/sycl-prof/writer.hpp b/sycl/tools/sycl-prof/writer.hpp index 98b7e4fbcbbc0..9870065beb35e 100644 --- a/sycl/tools/sycl-prof/writer.hpp +++ b/sycl/tools/sycl-prof/writer.hpp @@ -17,11 +17,9 @@ class Writer { virtual void init() = 0; virtual void finalize() = 0; virtual void writeBegin(std::string_view Name, std::string_view Category, - unsigned long PID, unsigned long TID, - unsigned long TimeStamp) = 0; + size_t PID, size_t TID, size_t TimeStamp) = 0; virtual void writeEnd(std::string_view Name, std::string_view Category, - unsigned long PID, unsigned long TID, - unsigned long TimeStamp) = 0; + size_t PID, size_t TID, size_t TimeStamp) = 0; virtual ~Writer() = default; }; @@ -36,9 +34,8 @@ class JSONWriter : public Writer { MOutFile << " \"traceEvents\": [\n"; } - void writeBegin(std::string_view Name, std::string_view Category, - unsigned long PID, unsigned long TID, - unsigned long TimeStamp) override { + void writeBegin(std::string_view Name, std::string_view Category, size_t PID, + size_t TID, size_t TimeStamp) override { std::lock_guard _{MWriteMutex}; if (!MOutFile.is_open()) @@ -53,9 +50,8 @@ class JSONWriter : public Writer { MOutFile << std::endl; } - void writeEnd(std::string_view Name, std::string_view Category, - unsigned long PID, unsigned long TID, - unsigned long TimeStamp) override { + void writeEnd(std::string_view Name, std::string_view Category, size_t PID, + size_t TID, size_t TimeStamp) override { std::lock_guard _{MWriteMutex}; if (!MOutFile.is_open()) diff --git a/sycl/tools/sycl-sanitize/collector.cpp b/sycl/tools/sycl-sanitize/collector.cpp index de5b233c87851..86b5bb74b6939 100644 --- a/sycl/tools/sycl-sanitize/collector.cpp +++ b/sycl/tools/sycl-sanitize/collector.cpp @@ -143,12 +143,10 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int /*major_version*/, if (std::string_view(StreamName) == "sycl.pi.debug") { GS = new GlobalState; uint8_t StreamID = xptiRegisterStream(StreamName); - xptiRegisterCallback( - StreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_begin, - tpCallback); - xptiRegisterCallback( - StreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_end, - tpCallback); + xptiRegisterCallback(StreamID, xpti::trace_function_with_args_begin, + tpCallback); + xptiRegisterCallback(StreamID, xpti::trace_function_with_args_end, + tpCallback); GS->ArgHandlerPostCall.set_piextUSMHostAlloc(handleUSMHostAlloc); GS->ArgHandlerPostCall.set_piextUSMDeviceAlloc(handleUSMDeviceAlloc); @@ -199,16 +197,15 @@ XPTI_CALLBACK_API void tpCallback(uint16_t TraceType, GS->LastTracepoint.Line = 0; } - auto Type = static_cast(TraceType); // Lock while we capture information std::lock_guard Lock(GS->IOMutex); const auto *Data = static_cast(UserData); const auto *Plugin = static_cast(Data->user_data); - if (Type == xpti::trace_point_type_t::function_with_args_begin) { + if (TraceType == xpti::trace_function_with_args_begin) { GS->ArgHandlerPreCall.handle(Data->function_id, *Plugin, std::nullopt, Data->args_data); - } else if (Type == xpti::trace_point_type_t::function_with_args_end) { + } else if (TraceType == xpti::trace_function_with_args_end) { const pi_result Result = *static_cast(Data->ret_data); GS->ArgHandlerPostCall.handle(Data->function_id, *Plugin, Result, Data->args_data); diff --git a/sycl/tools/sycl-trace/pi_trace_collector.cpp b/sycl/tools/sycl-trace/pi_trace_collector.cpp index 7bab30a66e7af..2f277ef3e4598 100644 --- a/sycl/tools/sycl-trace/pi_trace_collector.cpp +++ b/sycl/tools/sycl-trace/pi_trace_collector.cpp @@ -43,12 +43,10 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int /*major_version*/, const char *stream_name) { if (std::string_view(stream_name) == "sycl.pi.debug") { GStreamID = xptiRegisterStream(stream_name); - xptiRegisterCallback( - GStreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_begin, - tpCallback); - xptiRegisterCallback( - GStreamID, (uint16_t)xpti::trace_point_type_t::function_with_args_end, - tpCallback); + xptiRegisterCallback(GStreamID, xpti::trace_function_with_args_begin, + tpCallback); + xptiRegisterCallback(GStreamID, xpti::trace_function_with_args_end, + tpCallback); #define _PI_API(api) \ ArgHandler.set##_##api( \ @@ -71,8 +69,7 @@ XPTI_CALLBACK_API void tpCallback(uint16_t TraceType, xpti::trace_event_data_t * /*Parent*/, xpti::trace_event_data_t * /*Event*/, uint64_t /*Instance*/, const void *UserData) { - auto Type = static_cast(TraceType); - if (Type == xpti::trace_point_type_t::function_with_args_end) { + if (TraceType == xpti::trace_function_with_args_end) { // Lock while we print information std::lock_guard Lock(GIOMutex); diff --git a/xpti/include/xpti/xpti_data_types.h b/xpti/include/xpti/xpti_data_types.h index 86f92ad54167f..40348aa10ed00 100644 --- a/xpti/include/xpti/xpti_data_types.h +++ b/xpti/include/xpti/xpti_data_types.h @@ -668,6 +668,14 @@ constexpr uint16_t trace_edge_create = static_cast(xpti::trace_point_type_t::edge_create); constexpr uint16_t trace_signal = static_cast(xpti::trace_point_type_t::signal); +constexpr uint16_t trace_function_begin = + static_cast(xpti::trace_point_type_t::function_begin); +constexpr uint16_t trace_function_end = + static_cast(xpti::trace_point_type_t::function_end); +constexpr uint16_t trace_function_with_args_begin = + static_cast(xpti::trace_point_type_t::function_with_args_begin); +constexpr uint16_t trace_function_with_args_end = + static_cast(xpti::trace_point_type_t::function_with_args_end); constexpr uint16_t trace_offload_alloc_construct = static_cast(xpti::trace_point_type_t::offload_alloc_construct); constexpr uint16_t trace_offload_alloc_associate = From 8956b5cb2cf82e4450dd3b58b72cb09f480b4ea5 Mon Sep 17 00:00:00 2001 From: Alexander Batashev Date: Wed, 23 Feb 2022 10:32:28 +0300 Subject: [PATCH 5/6] more comments --- sycl/tools/sycl-prof/main.cpp | 20 +++++++------------- sycl/tools/sycl-sanitize/main.cpp | 16 +++++----------- sycl/tools/sycl-trace/main.cpp | 16 +++++----------- sycl/tools/xpti_helpers/launch.hpp | 23 +++++++++++++++++++---- 4 files changed, 36 insertions(+), 39 deletions(-) diff --git a/sycl/tools/sycl-prof/main.cpp b/sycl/tools/sycl-prof/main.cpp index 31ec0813dcb3f..6b1a96080f25e 100644 --- a/sycl/tools/sycl-prof/main.cpp +++ b/sycl/tools/sycl-prof/main.cpp @@ -32,32 +32,26 @@ int main(int argc, char **argv, char *env[]) { cl::ParseCommandLineOptions(argc, argv); - std::vector NewEnv; + std::vector NewEnv; { size_t I = 0; while (env[I] != nullptr) - NewEnv.push_back(env[I++]); + NewEnv.emplace_back(env[I++]); } std::string ProfOutFile = "SYCL_PROF_OUT_FILE=" + OutputFilename; - NewEnv.push_back(ProfOutFile.c_str()); + NewEnv.push_back(ProfOutFile); NewEnv.push_back("XPTI_FRAMEWORK_DISPATCHER=libxptifw.so"); NewEnv.push_back("XPTI_SUBSCRIBERS=libsycl_profiler_collector.so"); NewEnv.push_back("XPTI_TRACE_ENABLE=1"); - NewEnv.push_back(nullptr); - std::vector Args; + std::vector Args; - Args.push_back(TargetExecutable.c_str()); + Args.push_back(TargetExecutable); + std::copy(Argv.begin(), Argv.end(), std::back_inserter(Args)); - for (auto &Arg : Argv) { - Args.push_back(Arg.c_str()); - } - - Args.push_back(nullptr); - - int Err = launch(TargetExecutable.c_str(), Args, NewEnv); + int Err = launch(TargetExecutable, Args, NewEnv); if (Err) { std::cerr << "Failed to launch target application. Error code " << Err diff --git a/sycl/tools/sycl-sanitize/main.cpp b/sycl/tools/sycl-sanitize/main.cpp index 2586a7a32240e..3a89d8132f232 100644 --- a/sycl/tools/sycl-sanitize/main.cpp +++ b/sycl/tools/sycl-sanitize/main.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv, char *env[]) { cl::ParseCommandLineOptions(argc, argv); - std::vector NewEnv; + std::vector NewEnv; { size_t I = 0; @@ -33,19 +33,13 @@ int main(int argc, char **argv, char *env[]) { NewEnv.push_back("XPTI_FRAMEWORK_DISPATCHER=libxptifw.so"); NewEnv.push_back("XPTI_SUBSCRIBERS=libsycl_sanitizer_collector.so"); NewEnv.push_back("XPTI_TRACE_ENABLE=1"); - NewEnv.push_back(nullptr); - std::vector Args; + std::vector Args; - Args.push_back(TargetExecutable.c_str()); + Args.push_back(TargetExecutable); + std::copy(Argv.begin(), Argv.end(), std::back_inserter(Args)); - for (auto &Arg : Argv) { - Args.push_back(Arg.c_str()); - } - - Args.push_back(nullptr); - - int Err = launch(TargetExecutable.c_str(), Args, NewEnv); + int Err = launch(TargetExecutable, Args, NewEnv); if (Err) { std::cerr << "Failed to launch target application. Error code " << Err diff --git a/sycl/tools/sycl-trace/main.cpp b/sycl/tools/sycl-trace/main.cpp index 23a37a6bd17df..13a9524a54c3c 100644 --- a/sycl/tools/sycl-trace/main.cpp +++ b/sycl/tools/sycl-trace/main.cpp @@ -29,28 +29,22 @@ int main(int argc, char **argv, char *env[]) { cl::ParseCommandLineOptions(argc, argv); - std::vector NewEnv; + std::vector NewEnv; { size_t I = 0; while (env[I] != nullptr) - NewEnv.push_back(env[I++]); + NewEnv.emplace_back(env[I++]); } NewEnv.push_back("XPTI_FRAMEWORK_DISPATCHER=libxptifw.so"); NewEnv.push_back("XPTI_SUBSCRIBERS=libsycl_pi_trace_collector.so"); NewEnv.push_back("XPTI_TRACE_ENABLE=1"); - NewEnv.push_back(nullptr); - std::vector Args; + std::vector Args; - Args.push_back(TargetExecutable.c_str()); - - for (auto &Arg : Argv) { - Args.push_back(Arg.c_str()); - } - - Args.push_back(nullptr); + Args.push_back(TargetExecutable); + std::copy(Argv.begin(), Argv.end(), std::back_inserter(Args)); int Err = launch(TargetExecutable.c_str(), Args, NewEnv); diff --git a/sycl/tools/xpti_helpers/launch.hpp b/sycl/tools/xpti_helpers/launch.hpp index 239d9252e376c..1e077f6964e9f 100644 --- a/sycl/tools/xpti_helpers/launch.hpp +++ b/sycl/tools/xpti_helpers/launch.hpp @@ -8,17 +8,32 @@ #pragma once +#include +#include #include #include +inline std::vector toCStyle(const std::vector &Arr) { + std::vector CArr; + CArr.reserve(Arr.size() + 1); + std::transform(Arr.begin(), Arr.end(), std::back_inserter(CArr), + [](const std::string &str) { return str.data(); }); + + CArr.push_back(nullptr); + + return CArr; +} + /// Launches external application. /// /// \param Cmd is a path (full, relative, executable name in PATH) to executable /// \param Args is program arguments. First argument is executable name. Last /// argument is nullptr. /// \param Env is program environment variables. Last variable is nullptr. -int launch(const char *Cmd, const std::vector &Args, - const std::vector &Env) { - return execve(Cmd, const_cast(Args.data()), - const_cast(Env.data())); +int launch(const std::string &Cmd, const std::vector &Args, + const std::vector &Env) { + std::vector CArgs = toCStyle(Args); + std::vector CEnv = toCStyle(Env); + return execve(Cmd.data(), const_cast(CArgs.data()), + const_cast(CEnv.data())); } From 6dcafe503eb2dfc6359e5fd699c455a15ca14120 Mon Sep 17 00:00:00 2001 From: Alexander Batashev Date: Wed, 23 Feb 2022 10:36:57 +0300 Subject: [PATCH 6/6] clang-format --- sycl/tools/sycl-prof/collector.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/sycl/tools/sycl-prof/collector.cpp b/sycl/tools/sycl-prof/collector.cpp index 1830e4a730b99..0bcadfd67d072 100644 --- a/sycl/tools/sycl-prof/collector.cpp +++ b/sycl/tools/sycl-prof/collector.cpp @@ -18,7 +18,6 @@ #include #include - namespace chrono = std::chrono; Writer *GWriter = nullptr;