diff --git a/xptifw/CMakeLists.txt b/xptifw/CMakeLists.txt index 99c7e84c43a56..d860705b03a9c 100644 --- a/xptifw/CMakeLists.txt +++ b/xptifw/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.20.0) -set(XPTI_VERSION 1.0.0) +set(XPTI_VERSION 1.0.1) project (xptifw VERSION "${XPTI_VERSION}" LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) @@ -74,8 +74,8 @@ endif() if (XPTI_BUILD_SAMPLES) add_subdirectory(samples/basic_collector) - add_subdirectory(samples/syclpi_collector) add_subdirectory(samples/sycl_perf_collector) + add_subdirectory(samples/syclur_collector) add_subdirectory(basic_test) endif() diff --git a/xptifw/CMakeLists.txt.in b/xptifw/CMakeLists.txt.in index 37b622bf305cd..80262183eaf98 100644 --- a/xptifw/CMakeLists.txt.in +++ b/xptifw/CMakeLists.txt.in @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.2) +cmake_minimum_required(VERSION 3.20.0) project(googletest-download NONE) diff --git a/xptifw/samples/sycl_perf_collector/sycl_perf_collector.cpp b/xptifw/samples/sycl_perf_collector/sycl_perf_collector.cpp index 837aef05fe9d2..b765a05d59dcf 100644 --- a/xptifw/samples/sycl_perf_collector/sycl_perf_collector.cpp +++ b/xptifw/samples/sycl_perf_collector/sycl_perf_collector.cpp @@ -41,6 +41,7 @@ event_instances_t *GRecordsInProgress = nullptr; xpti::utils::timer::measurement_t GMeasure; constexpr const char *GStreamBasic = "sycl"; +constexpr const char *GStreamPerf = "sycl.perf"; constexpr const char *GStreamPI = "ur.call"; constexpr const char *GStreamMemory = "sycl.experimental.mem_alloc"; constexpr const char *GStreamL0 = "sycl.experimental.level_zero.call"; @@ -291,12 +292,14 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int major_version, // In order to determine if the environment variable contains valid stream // names, a catalog of all streams must be check against to validate the // strings - if (ShowVerboseOutput && StreamsToMonitor) { - std::cout << "Monitoring streams: "; + if (StreamsToMonitor) { + if (ShowVerboseOutput) + std::cout << "Monitoring streams: "; auto streams = D.decode(StreamsToMonitor); for (auto &s : streams) { - std::cout << s << ", "; + if (ShowVerboseOutput) + std::cout << s << ", "; GAllStreams.add(s.c_str()); } if (ShowVerboseOutput) @@ -394,17 +397,17 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int major_version, InitStreams = false; } // First time inititalization complete - if (ShowVerboseOutput) - std::cout << "Initializing stream: " << stream_name << "\n"; - // Post initialization: Once the needed data structures are created, we // register callbacks to the streams requsted by the end-user; // // Check == TRUE if the stream has been requested by end-user // auto Check = GAllStreams.check(stream_name); - if (Check) + if (Check) { GStreams->add(stream_name); + if (ShowVerboseOutput) + std::cout << "Initializing stream: " << stream_name << "\n"; + } if (std::string(GStreamBasic) == stream_name && Check) { auto StreamID = xptiRegisterStream(stream_name); @@ -436,10 +439,10 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int major_version, // Handles SelfNotification events xptiRegisterCallback(StreamID, (uint16_t)xpti::trace_point_type_t::function_begin, - syclPiCallback); + syclURCallback); xptiRegisterCallback(StreamID, (uint16_t)xpti::trace_point_type_t::function_end, - syclPiCallback); + syclURCallback); } else if (std::string(GStreamMemory) == stream_name && Check) { auto StreamID = xptiRegisterStream(stream_name); xptiRegisterCallback(StreamID, @@ -468,6 +471,14 @@ XPTI_CALLBACK_API void xptiTraceInit(unsigned int major_version, xptiRegisterCallback(StreamID, (uint16_t)xpti::trace_point_type_t::function_end, syclURCallback); + } else if (std::string(GStreamPerf) == stream_name && Check) { + auto StreamID = xptiRegisterStream(stream_name); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::function_begin, + syclURCallback); + xptiRegisterCallback(StreamID, + (uint16_t)xpti::trace_point_type_t::function_end, + syclURCallback); } else if (std::string(GStreamL0) == stream_name && Check) { auto StreamID = xptiRegisterStream(stream_name); xptiRegisterCallback(StreamID, @@ -515,7 +526,7 @@ std::once_flag GFinalize, GCompaction; // terminated sending events in its stream XPTI_CALLBACK_API void xptiTraceFinish(const char *stream_name) { { - if (ShowVerboseOutput) + if (ShowVerboseOutput && GStreams->check(stream_name)) std::cout << "Unregistering stream: " << stream_name << "\n"; std::lock_guard _{GStreamMutex}; // Filter the streams to what is requested by the user that intersects with diff --git a/xptifw/src/CMakeLists.txt b/xptifw/src/CMakeLists.txt index 2811b73baf833..308f47d962260 100644 --- a/xptifw/src/CMakeLists.txt +++ b/xptifw/src/CMakeLists.txt @@ -1,4 +1,5 @@ # Fetch third party headers +include(FetchContent) set(EMHASH_REPO https://github.com/ktprime/emhash) message(STATUS "Will fetch emhash from ${EMHASH_REPO}") FetchContent_Declare(emhash-headers diff --git a/xptifw/src/xpti_trace_framework.cpp b/xptifw/src/xpti_trace_framework.cpp index 1192a3e861e3f..f0759acdb759d 100644 --- a/xptifw/src/xpti_trace_framework.cpp +++ b/xptifw/src/xpti_trace_framework.cpp @@ -82,8 +82,16 @@ static thread_local xpti_tracepoint_t *g_tls_tracepoint_scope_data; /// Default stream for the trace framework, if none is provided by the user. constexpr const char *g_default_stream = "xpti.framework"; +/// @brief Flag to ensure the default stream is initialized only once. +/// @details Used with `std::call_once` to initialize the default stream in a +/// thread-safe manner. static std::once_flag g_initialize_default_stream_flag; +/// @brief Flag to ensure the default stream is finalized only once. +/// @details Used with `std::call_once` to finalize the default stream in a +/// thread-safe manner. +static std::once_flag g_finalize_default_stream_flag; + namespace xpti { /// @var env_subscribers /// @brief A constant character pointer initialized with the string @@ -1379,7 +1387,7 @@ class Notifications { /// @brief Maps a trace type to its associated callback entries. /// @details This unordered map uses a uint16_t as the key to represent the /// trace point type, and cb_entries_t to store the associated callbacks. - using cb_t = std::unordered_map; + using cb_t = emhash7::HashMap; /// @typedef stream_cb_t /// @brief Maps a stream ID to its corresponding callbacks for different @@ -1387,7 +1395,7 @@ class Notifications { /// @details This unordered map uses a uint16_t as the key for the stream /// ID, and cb_t to map the stream to registered callbacks for each trace /// type - using stream_cb_t = std::unordered_map; + using stream_cb_t = emhash7::HashMap; /// @typedef statistics_t /// @brief Keeps track of statistics, typically counts, associated with @@ -1396,13 +1404,13 @@ class Notifications { /// the type of statistical data and usually not defined by default. To /// enable it, XPTI_STATISTICS has to be defined while compiling the /// frmaework library. - using statistics_t = std::unordered_map; + using statistics_t = emhash7::HashMap; /// @typedef trace_flags_t /// @brief Maps an trace type to a boolean flag indicating its state. /// @details This unordered map uses a uint16_t as the key for the trace /// type, and a boolean value to indicate whether callbacks are registered /// for this trace type (e.g., registered or unregisterted/no callback). - using trace_flags_t = std::unordered_map; + using trace_flags_t = emhash7::HashMap; /// @typedef stream_flags_t /// @brief Maps a stream ID to its corresponding trace flags for different @@ -1411,7 +1419,7 @@ class Notifications { /// and trace_flags_t to map the trace type to their boolean that indiciates /// whether a callback has been registered for this trace type in the given /// stream. - using stream_flags_t = std::unordered_map; + using stream_flags_t = emhash7::HashMap; /// @brief Registers a callback function for a specific trace type and stream /// ID. @@ -2290,6 +2298,9 @@ class Framework { } static Framework &instance() { + // Using std::call_once has the same overhead as the original approach + // std::call_once(g_initialize_framework_flag, + // [&]() { MInstance = new Framework(); }); Framework *TmpFramework = MInstance.load(std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_acquire); if (TmpFramework == nullptr) { @@ -2309,6 +2320,11 @@ class Framework { friend void ::xptiFrameworkFinalize(); static void release() { + // Using std::call_once has the same overhead as the original approach + // std::call_once(g_release_framework_flag, [&]() { + // delete MInstance; + // MInstance = nullptr; + // }); Framework *TmpFramework = MInstance.load(std::memory_order_relaxed); MInstance.store(nullptr, std::memory_order_relaxed); delete TmpFramework; @@ -2482,7 +2498,10 @@ XPTI_EXPORT_API xpti::result_t xptiInitialize(const char *Stream, uint32_t maj, /// when the stream is no longer in use. XPTI_EXPORT_API void xptiFinalize(const char *Stream) { - xpti::Framework::instance().finalizeStream(Stream); + auto &FW = xpti::Framework::instance(); + std::call_once(g_finalize_default_stream_flag, + [&]() { FW.finalizeStream(g_default_stream); }); + FW.finalizeStream(Stream); } /// @brief Retrieves the 64-bit universal ID for the current scope, if published diff --git a/xptifw/unit_test/CMakeLists.txt b/xptifw/unit_test/CMakeLists.txt index 905e993f57e28..37827dabe5e98 100644 --- a/xptifw/unit_test/CMakeLists.txt +++ b/xptifw/unit_test/CMakeLists.txt @@ -7,7 +7,7 @@ include_directories(${XPTI_DIR}/include) if (NOT DEFINED LLVM_EXTERNAL_XPTIFW_SOURCE_DIR) message(STATUS "Building XPTI outside of LLVM Project...") # Download and unpack googletest at configure time - configure_file(../CMakeLists.txt.in googletest-download/CMakeLists.txt) + configure_file(${XPTIFW_DIR}/CMakeLists.txt.in googletest-download/CMakeLists.txt) execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . RESULT_VARIABLE result WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )