Correlation ID Retirement + misc (#527)

* Correlation ID Retirement

- include/rocprofiler-sdk/buffer_tracing.h
  - add rocprofiler_buffer_tracing_correlation_id_retirement_record_t
- include/rocprofiler-sdk/fwd.h
  - ROCPROFILER_BUFFER_TRACING_CORRELATION_ID_RETIREMENT
- lib/rocprofiler-sdk/buffer_tracing.cpp
  - kind string for correlation id retirement
- lib/rocprofiler-sdk/buffer.hpp
  - emplace returns bool
- lib/rocprofiler-sdk/registration.cpp
  - pass lib_instance to copy_table functions
- lib/rocprofiler-sdk/context/context.*
  - update correlation_id struct
    - make ref_count private
    - {get,add,sub}_ref_count() functions
      - sub_ref_count() performs correlation id retirement
    - use stack for "latest" thread-local correlation id
- lib/rocprofiler-sdk/hip/hip.*
  - migrate to new {get,add,sub}_ref_count() for correlation ids
  - return in iterate_args
  - handle table instance in copy_table
- lib/rocprofiler-sdk/hsa/hsa.*
  - migrate to new {get,add,sub}_ref_count() for correlation ids
  - return in iterate_args
  - handle table instance in copy_table
- lib/rocprofiler-sdk/marker/marker.*
  - migrate to new {get,add,sub}_ref_count() for correlation ids
  - return in iterate_args
  - handle table instance in copy_table
- lib/rocprofiler-sdk/hsa/async_copy.cpp
  - migrate to new {get,add,sub}_ref_count() for correlation ids
  - handle table instance in async_copy_init / async_copy_save
- lib/rocprofiler-sdk/hsa/queue.cpp
  - migrate to new {get,add,sub}_ref_count() for correlation ids
  - tweak to external correlation id mapping in WriteInterceptor
- tests/async-copy-tracing/validate.py
  - check retired_correlation_ids
- tests/common/serialization.hpp
  - support rocprofiler_buffer_tracing_correlation_id_retirement_record_t
- tests/kernel-tracing/validate.py
  - check retired_correlation_ids
- tests/common/CMakeLists.txt
  - perfetto external project
- tests/common/perfetto.hpp
  - perfetto categories + aliases
  - add_perfetto_annotation
  - metaprogramming helpers
- tests/tools/CMakeLists.txt
  - link to tests-perfetto
- tests/tools/json-tool.cpp
  - demangling functions
  - serialization of marker API callback args
  - reduce parallel bottleneck in tool_tracing_callback
  - support correlation id retirement
  - Multiple threads for buffers
  - Support ROCPROFILER_TOOL_CONTEXTS_EXCLUDE env variable
  - write_perfetto() function

* Update tests/rocprofv3/tracing/validate.py

- tweak test_hsa_api_trace

* Update PTL submodule

- fixes for data race during destruction of task

* Update lib/rocprofiler-sdk/buffer.*

- unique_buffer_vec_t uses std::unique_ptr instead of allocator::unique_static_ptr_t

* Reduce timeouts in counter collection samples [skip ci]

* Update tests/tools/json-tool.cpp

- tweak demangle(string_view, int*) -> demangle(string_view, int&)

* Update lib/rocprofiler-sdk/hsa/async_copy.cpp

- move sub_ref_count() to later in async_copy_handler to delay retirement slightly more

[ROCm/rocprofiler-sdk commit: 875f53b608]
Dieser Commit ist enthalten in:
Jonathan R. Madsen
2024-02-23 10:30:33 -06:00
committet von GitHub
Ursprung a651f1e215
Commit a360de4550
27 geänderte Dateien mit 1217 neuen und 184 gelöschten Zeilen
@@ -2,6 +2,10 @@
# common utilities for tests
#
include(FetchContent)
set(FETCHCONTENT_BASE_DIR ${PROJECT_BINARY_DIR}/external)
# build flags
add_library(rocprofiler-tests-build-flags INTERFACE)
add_library(rocprofiler::tests-build-flags ALIAS rocprofiler-tests-build-flags)
@@ -35,10 +39,6 @@ if(NOT TARGET rocprofiler::cereal)
INTERFACE $<BUILD_INTERFACE:${ROCPROFILER_SOURCE_DIR}/external/cereal/include>
)
else()
include(FetchContent)
set(FETCHCONTENT_BASE_DIR ${PROJECT_BINARY_DIR}/external)
fetchcontent_declare(
cereal
GIT_REPOSITORY https://github.com/jrmadsen/cereal.git
@@ -60,6 +60,32 @@ if(NOT TARGET rocprofiler::cereal)
endif()
endif()
# perfetto
fetchcontent_declare(
perfetto
GIT_REPOSITORY https://android.googlesource.com/platform/external/perfetto
GIT_TAG v42.0
SOURCE_DIR ${PROJECT_BINARY_DIR}/external/perfetto BINARY_DIR
${PROJECT_BINARY_DIR}/external/build/perfetto-build SUBBUILD_DIR
${PROJECT_BINARY_DIR}/external/build/perfetto-subdir)
fetchcontent_getproperties(perfetto)
if(NOT perfetto_POPULATED)
fetchcontent_populate(perfetto)
endif()
add_library(rocprofiler-tests-perfetto STATIC)
add_library(rocprofiler::tests-perfetto ALIAS rocprofiler-tests-perfetto)
target_sources(
rocprofiler-tests-perfetto
PRIVATE ${PROJECT_BINARY_DIR}/external/perfetto/sdk/perfetto.h
${PROJECT_BINARY_DIR}/external/perfetto/sdk/perfetto.cc)
target_include_directories(
rocprofiler-tests-perfetto SYSTEM
INTERFACE $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/external/perfetto/sdk>)
set_target_properties(rocprofiler-tests-perfetto PROPERTIES POSITION_INDEPENDENT_CODE ON)
# common utilities
cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH COMMON_LIBRARY_INCLUDE_DIR)
@@ -0,0 +1,225 @@
// MIT License
//
// Copyright (c) 2023 Advanced Micro Devices, Inc. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#pragma once
#include <cstddef>
#include <ostream>
#include <sstream>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#define ROCPROFILER_DEFINE_NAME_TRAIT(NAME, DESC, ...) \
namespace rocprofiler \
{ \
template <> \
struct perfetto_category<__VA_ARGS__> \
{ \
static constexpr auto value = NAME; \
static constexpr auto description = DESC; \
}; \
}
namespace rocprofiler
{
template <typename Tp>
struct perfetto_category;
namespace trait
{
template <typename... Tp>
using name = perfetto_category<Tp...>;
}
} // namespace rocprofiler
#define ROCPROFILER_DEFINE_NS_API(NS, NAME) \
namespace rocprofiler \
{ \
namespace NS \
{ \
struct NAME; \
} \
}
#define ROCPROFILER_DEFINE_CATEGORY(NS, VALUE, DESC) \
ROCPROFILER_DEFINE_NS_API(NS, VALUE) \
ROCPROFILER_DEFINE_NAME_TRAIT(#VALUE, DESC, NS::VALUE)
ROCPROFILER_DEFINE_CATEGORY(category, hsa_api, "HSA API function")
ROCPROFILER_DEFINE_CATEGORY(category, hip_api, "HIP API function")
ROCPROFILER_DEFINE_CATEGORY(category, marker_api, "Marker API region")
ROCPROFILER_DEFINE_CATEGORY(category, kernel_dispatch, "GPU kernel dispatch")
ROCPROFILER_DEFINE_CATEGORY(category, memory_copy, "Async memory copy")
#define ROCPROFILER_PERFETTO_CATEGORY(TYPE) \
::perfetto::Category(::rocprofiler::perfetto_category<::rocprofiler::TYPE>::value) \
.SetDescription(::rocprofiler::perfetto_category<::rocprofiler::TYPE>::description)
#define ROCPROFILER_PERFETTO_CATEGORIES \
ROCPROFILER_PERFETTO_CATEGORY(category::hsa_api), \
ROCPROFILER_PERFETTO_CATEGORY(category::hip_api), \
ROCPROFILER_PERFETTO_CATEGORY(category::marker_api), \
ROCPROFILER_PERFETTO_CATEGORY(category::kernel_dispatch), \
ROCPROFILER_PERFETTO_CATEGORY(category::memory_copy)
#include <perfetto.h>
PERFETTO_DEFINE_CATEGORIES(ROCPROFILER_PERFETTO_CATEGORIES);
namespace concepts
{
template <typename Tp>
struct is_string_type : std::false_type
{};
template <>
struct is_string_type<std::string> : std::true_type
{};
template <>
struct is_string_type<char*> : std::true_type
{};
template <>
struct is_string_type<const char*> : std::true_type
{};
template <>
struct is_string_type<std::string_view> : std::true_type
{};
template <typename Tp>
struct is_string_type<const Tp> : is_string_type<std::decay_t<Tp>>
{};
template <typename Tp>
struct is_string_type<Tp&> : is_string_type<std::decay_t<Tp>>
{};
template <typename Tp>
struct is_string_type<volatile Tp> : is_string_type<std::decay_t<Tp>>
{};
template <typename Tp, size_t N>
struct is_string_type<Tp[N]> : is_string_type<std::decay_t<Tp[N]>>
{};
template <typename Tp, size_t N>
struct is_string_type<const Tp[N]> : is_string_type<std::decay_t<Tp[N]>>
{};
template <typename Tp, size_t N>
struct is_string_type<volatile Tp[N]> : is_string_type<std::decay_t<Tp[N]>>
{};
template <typename Tp>
struct unqualified_type
{
using type = std::remove_reference_t<std::remove_cv_t<std::decay_t<Tp>>>;
};
template <typename Tp>
using unqualified_type_t = typename unqualified_type<Tp>::type;
template <typename Tp>
struct can_stringify
{
private:
static constexpr auto sfinae(int)
-> decltype(std::declval<std::ostream&>() << std::declval<Tp>(), bool())
{
return true;
}
static constexpr auto sfinae(long) { return false; }
public:
static constexpr bool value = sfinae(0);
constexpr auto operator()() const { return sfinae(0); }
};
} // namespace concepts
using perfetto_event_context_t = ::perfetto::EventContext;
template <typename Np, typename Tp>
auto
add_perfetto_annotation(perfetto_event_context_t& ctx, Np&& _name, Tp&& _val)
{
using named_type = concepts::unqualified_type_t<Np>;
using value_type = concepts::unqualified_type_t<Tp>;
static_assert(concepts::is_string_type<named_type>::value, "Error! name is not a string type");
auto _get_dbg = [&]() {
auto* _dbg = ctx.event()->add_debug_annotations();
_dbg->set_name(std::string_view{std::forward<Np>(_name)}.data());
return _dbg;
};
if constexpr(std::is_same<value_type, std::string_view>::value)
{
_get_dbg()->set_string_value(_val.data());
}
else if constexpr(concepts::is_string_type<value_type>::value)
{
_get_dbg()->set_string_value(std::forward<Tp>(_val));
}
else if constexpr(std::is_same<value_type, bool>::value)
{
_get_dbg()->set_bool_value(_val);
}
else if constexpr(std::is_enum<value_type>::value)
{
_get_dbg()->set_int_value(static_cast<int64_t>(_val));
}
else if constexpr(std::is_floating_point<value_type>::value)
{
_get_dbg()->set_double_value(static_cast<double>(_val));
}
else if constexpr(std::is_integral<value_type>::value)
{
if constexpr(std::is_unsigned<value_type>::value)
{
_get_dbg()->set_uint_value(_val);
}
else
{
_get_dbg()->set_int_value(_val);
}
}
else if constexpr(std::is_pointer<value_type>::value)
{
_get_dbg()->set_pointer_value(reinterpret_cast<uint64_t>(_val));
}
else if constexpr(concepts::can_stringify<value_type>::value)
{
auto _ss = std::stringstream{};
_ss << std::forward<Tp>(_val);
_get_dbg()->set_string_value(_ss.str());
}
else
{
static_assert(std::is_empty<value_type>::value, "Error! unsupported data type");
}
}
@@ -30,7 +30,9 @@
#include <rocprofiler-sdk/internal_threading.h>
#include <rocprofiler-sdk/rocprofiler.h>
#include <cereal/archives/binary.hpp>
#include <cereal/archives/json.hpp>
#include <cereal/archives/portable_binary.hpp>
#include <cereal/cereal.hpp>
#include <cereal/types/array.hpp>
#include <cereal/types/atomic.hpp>
@@ -286,6 +288,16 @@ save(ArchiveT& ar, rocprofiler_buffer_tracing_memory_copy_record_t data)
SAVE_DATA_FIELD(src_agent_id);
}
template <typename ArchiveT>
void
save(ArchiveT& ar, rocprofiler_buffer_tracing_correlation_id_retirement_record_t data)
{
SAVE_DATA_FIELD(size);
SAVE_DATA_FIELD(kind);
SAVE_DATA_FIELD(timestamp);
SAVE_DATA_FIELD(internal_correlation_id);
}
template <typename ArchiveT>
void
save(ArchiveT& ar, HsaCacheType data)