[SDK] Expose counter dims in rocprofiler_counter_info_v1_t and only show counters being profiled in metadata. (#325)
* expose dimensional info in rocprofiler_counter_info_v1_t.
* add counter_id in dim info.
* address review comments
* format.
* address comments.
* use array of pointers for dimensions_instaces.
* format and comments.
* address comments.
* new line.
* Update counter_defs.yaml
* Update counter_defs.yaml
* Update counter_defs.yaml
* counter_defs.
* format counter defs.
* format counter defs.
* format counter defs.
* show only counters being profiled in metadata.
* Format.
* use config for counters and fix warnings.
* add version for rocprofiler_counter_dimension_info_v1_t struct.
* rename rocprofiler_counter_record_dimension_instance_v1_info_t.
* account device id from pmc for counters metadata.
* move dim structs to counters.h.
* address comments to compare value.
* fix tests.
* Address comments. use pointer of arrays for ABI.
* rebase.
* fix build error.
* use separate metadata::init() for rocprofv3.
* also print not found counters.
* precompute all the perf counters needed to be in metadata.
* Misc.
* format
* Format.
* rocprofiler::sdk::container::c_array
* Address comments.
* source/lib/output/metadata.cpp
* lint.
* add unit test for c_array.
* add unit test and serialization support for c_array container.
* Misc.
* Clean files.
* Format.
* clang-tidy.
* add more checks to c_array.
* misc. typo
* Addr comments.
---------
Co-authored-by: Venkateshwar Reddy Kandula <vkandula@amd.com>
Co-authored-by: Jonathan R. Madsen <Jonathan.Madsen@amd.com>
[ROCm/rocprofiler-sdk commit: bf0fad1d54]
This commit is contained in:
committato da
GitHub
parent
b88018d24d
commit
0ff0ffffa2
@@ -50,24 +50,83 @@ typedef struct ROCPROFILER_SDK_EXPERIMENTAL rocprofiler_counter_info_v0_t
|
||||
uint8_t is_derived : 1; ///< If this counter is a derived counter
|
||||
} rocprofiler_counter_info_v0_t;
|
||||
|
||||
/**
|
||||
* @brief (experimental) Represents metadata about a single dimension of a counter instance.
|
||||
*
|
||||
* This structure provides the name of the dimension (e.g., "XCC", "SE", etc.)
|
||||
* and the index indicating the position of a specific counter instance within that dimension.
|
||||
*/
|
||||
typedef struct ROCPROFILER_SDK_EXPERIMENTAL rocprofiler_counter_dimension_info_t
|
||||
{
|
||||
uint64_t size; ///< Size of this structure. Used for versioning and validation.
|
||||
const char* dimension_name;
|
||||
size_t index;
|
||||
|
||||
/**
|
||||
* @var dimension_name
|
||||
* @brief Name of the dimension this instance belongs to.
|
||||
|
||||
* @var index
|
||||
* @brief Position (zero-based) of the instance within the specified dimension.
|
||||
*/
|
||||
|
||||
} rocprofiler_counter_dimension_info_t;
|
||||
|
||||
/**
|
||||
* @brief (experimental) Describes a specific counter instance and its position across multiple
|
||||
* dimensions.
|
||||
*
|
||||
* This structure provides the unique instance ID, associated counter ID, number of dimensions for
|
||||
* the instance, and a pointer to an array of metadata describing each dimension's name and index.
|
||||
*/
|
||||
typedef struct ROCPROFILER_SDK_EXPERIMENTAL rocprofiler_counter_record_dimension_instance_info_t
|
||||
{
|
||||
uint64_t size; ///< Size of this structure. Used for versioning and validation.
|
||||
rocprofiler_counter_instance_id_t instance_id;
|
||||
uint64_t counter_id;
|
||||
uint64_t dimensions_count;
|
||||
const rocprofiler_counter_dimension_info_t** dimensions;
|
||||
|
||||
/**
|
||||
* @var instance_id
|
||||
* @brief Encoded identifier for the instance, which includes the counter ID and all dimension
|
||||
positions.
|
||||
|
||||
* @var counter_id
|
||||
* @brief Identifier of the counter associated with this instance.
|
||||
|
||||
* @var dimensions_count
|
||||
* @brief Number of dimensions associated with this instance.
|
||||
|
||||
* @var dimensions
|
||||
* @brief Array of pointers to dimension info structures, each representing one dimension
|
||||
* and the position of this instance within that dimension.
|
||||
*
|
||||
* The array has `dimensions_count` elements, and each element is a pointer to a
|
||||
* `rocprofiler_counter_dimension_info_t` structure.
|
||||
*/
|
||||
|
||||
} rocprofiler_counter_record_dimension_instance_info_t;
|
||||
|
||||
/**
|
||||
* @brief (experimental) Counter info struct version 1. Combines information from
|
||||
* ::rocprofiler_counter_info_v0_t with the dimension information.
|
||||
*/
|
||||
typedef struct ROCPROFILER_SDK_EXPERIMENTAL rocprofiler_counter_info_v1_t
|
||||
{
|
||||
rocprofiler_counter_id_t id; ///< Id of this counter
|
||||
const char* name; ///< Name of the counter
|
||||
uint64_t size; ///< Size of this structure. Used for versioning and validation.
|
||||
rocprofiler_counter_id_t id; ///< Id of this counter
|
||||
const char* name; ///< Name of the counter
|
||||
const char* description; ///< Description of the counter
|
||||
const char* block; ///< Block of the counter (non-derived only)
|
||||
const char* expression; ///< Counter expression (derived counters only)
|
||||
uint8_t is_constant : 1; ///< If this counter is HW constant
|
||||
uint8_t is_derived : 1; ///< If this counter is a derived counter
|
||||
|
||||
uint64_t dimensions_count;
|
||||
const rocprofiler_counter_record_dimension_info_t* dimensions;
|
||||
uint64_t instance_ids_count;
|
||||
const rocprofiler_counter_instance_id_t* instance_ids;
|
||||
uint64_t dimensions_count;
|
||||
const rocprofiler_counter_record_dimension_info_t** dimensions;
|
||||
uint64_t dimensions_instances_count;
|
||||
const rocprofiler_counter_record_dimension_instance_info_t** dimensions_instances;
|
||||
|
||||
/// @var dimensions_count
|
||||
/// @brief Number of dimensions for the counter
|
||||
@@ -75,11 +134,12 @@ typedef struct ROCPROFILER_SDK_EXPERIMENTAL rocprofiler_counter_info_v1_t
|
||||
/// @var dimensions
|
||||
/// @brief Dimension information of the counter
|
||||
///
|
||||
/// @var instance_ids_count
|
||||
/// @brief Number of instance ids for the counter
|
||||
/// @var dimensions_instances_count
|
||||
/// @brief Number of unique instances for this counter, across all dimension combinations.
|
||||
///
|
||||
/// @var instance_ids
|
||||
/// @brief Instance ids that can be generated by the counter
|
||||
/// @var dimensions_instances
|
||||
/// @brief Array of pointers to instance info structs, each describing a unique instance
|
||||
/// and its specific dimension mapping.
|
||||
} rocprofiler_counter_info_v1_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,3 +14,4 @@ install(
|
||||
add_subdirectory(codeobj)
|
||||
add_subdirectory(details)
|
||||
add_subdirectory(serialization)
|
||||
add_subdirectory(container)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#
|
||||
#
|
||||
# Installation of public C++ headers (implementations)
|
||||
#
|
||||
#
|
||||
set(ROCPROFILER_CXX_CONTAINERS_HEADER_FILES c_array.hpp)
|
||||
|
||||
install(
|
||||
FILES ${ROCPROFILER_CXX_CONTAINERS_HEADER_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/rocprofiler-sdk/cxx/container
|
||||
COMPONENT development)
|
||||
@@ -0,0 +1,136 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2025 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 <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace rocprofiler
|
||||
{
|
||||
namespace sdk
|
||||
{
|
||||
namespace container
|
||||
{
|
||||
template <typename Tp>
|
||||
struct c_array
|
||||
{
|
||||
// Construct an array wrapper from a base pointer and array size
|
||||
c_array(Tp* _base, size_t _size)
|
||||
: m_base{_base}
|
||||
, m_size{_size}
|
||||
{}
|
||||
|
||||
~c_array() = default;
|
||||
c_array(const c_array&) = default;
|
||||
c_array(c_array&&) noexcept = default;
|
||||
c_array& operator=(const c_array&) = default;
|
||||
c_array& operator=(c_array&&) noexcept = default;
|
||||
|
||||
// Get the size of the wrapped array
|
||||
size_t size() const { return m_size; }
|
||||
|
||||
// Access an element by index
|
||||
Tp& operator[](size_t i) { return m_base[i]; }
|
||||
|
||||
// Access an element by index
|
||||
const Tp& operator[](size_t i) const { return m_base[i]; }
|
||||
|
||||
// Access an element by index with bounds check
|
||||
Tp& at(size_t i)
|
||||
{
|
||||
if(i < m_size) return m_base[i];
|
||||
throw std::out_of_range(std::string{typeid(*this).name()} + std::to_string(i) +
|
||||
" exceeds size " + std::to_string(m_size));
|
||||
}
|
||||
|
||||
// Access an element by index with bounds check
|
||||
const Tp& at(size_t i) const
|
||||
{
|
||||
if(i < m_size) return m_base[i];
|
||||
throw std::out_of_range(std::string{typeid(*this).name()} + std::to_string(i) +
|
||||
" exceeds size " + std::to_string(m_size));
|
||||
}
|
||||
|
||||
// Get a slice of this array, from a start index (inclusive) to end index (exclusive)
|
||||
c_array<Tp> slice(size_t start, size_t end) { return c_array<Tp>(&m_base[start], end - start); }
|
||||
|
||||
void pop_front()
|
||||
{
|
||||
++m_base;
|
||||
--m_size;
|
||||
}
|
||||
|
||||
void pop_back() { --m_size; }
|
||||
|
||||
operator Tp*() const { return m_base; }
|
||||
|
||||
// Iterator class for convenient range-based for loop support
|
||||
template <typename Up>
|
||||
struct iterator
|
||||
{
|
||||
// Start the iterator at a given pointer
|
||||
iterator(Tp* p)
|
||||
: m_ptr{p}
|
||||
{}
|
||||
|
||||
// Advance to the next element
|
||||
void operator++() { ++m_ptr; }
|
||||
void operator++(int) { m_ptr++; }
|
||||
|
||||
// Get the current element
|
||||
Up& operator*() const { return *m_ptr; }
|
||||
|
||||
// Compare iterators
|
||||
bool operator==(const iterator& rhs) const { return m_ptr == rhs.m_ptr; }
|
||||
bool operator!=(const iterator& rhs) const { return m_ptr != rhs.m_ptr; }
|
||||
|
||||
private:
|
||||
Tp* m_ptr = nullptr;
|
||||
};
|
||||
|
||||
// Get an iterator positioned at the beginning of the wrapped array
|
||||
iterator<Tp> begin() { return iterator<Tp>{m_base}; }
|
||||
iterator<const Tp> begin() const { return iterator<const Tp>{m_base}; }
|
||||
|
||||
// Get an iterator positioned at the end of the wrapped array
|
||||
iterator<Tp> end() { return iterator<Tp>{&m_base[m_size]}; }
|
||||
iterator<const Tp> end() const { return iterator<const Tp>{&m_base[m_size]}; }
|
||||
|
||||
private:
|
||||
Tp* m_base = nullptr;
|
||||
size_t m_size = 0;
|
||||
};
|
||||
|
||||
// Function for automatic template argument deduction
|
||||
template <typename Tp>
|
||||
c_array<Tp>
|
||||
make_c_array(Tp* base, size_t size)
|
||||
{
|
||||
return c_array<Tp>(base, size);
|
||||
}
|
||||
} // namespace container
|
||||
} // namespace sdk
|
||||
} // namespace rocprofiler
|
||||
@@ -24,11 +24,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <rocprofiler-sdk/agent.h>
|
||||
#include <rocprofiler-sdk/counters.h>
|
||||
#include <rocprofiler-sdk/defines.h>
|
||||
#include <rocprofiler-sdk/fwd.h>
|
||||
#include <rocprofiler-sdk/hsa.h>
|
||||
#include <rocprofiler-sdk/internal_threading.h>
|
||||
|
||||
#include "rocprofiler-sdk/cxx/details/mpl.hpp"
|
||||
|
||||
#include <string_view>
|
||||
#include <tuple>
|
||||
|
||||
#define ROCPROFILER_CXX_DECLARE_OPERATORS(TYPE) \
|
||||
@@ -88,6 +92,37 @@ less(Tp lhs, Tp rhs)
|
||||
static_assert(sizeof(Tp) == sizeof(uint64_t), "error! only for opaque handle types");
|
||||
return lhs.handle < rhs.handle;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template <typename Tp>
|
||||
struct sv_trait
|
||||
{
|
||||
static constexpr auto is_string_type() noexcept
|
||||
{
|
||||
return mpl::is_string_type<mpl::unqualified_identity_t<Tp>>::value;
|
||||
}
|
||||
|
||||
using type = std::conditional_t<is_string_type(), std::string_view, Tp&>;
|
||||
|
||||
constexpr type operator()(Tp& v) noexcept
|
||||
{
|
||||
if constexpr(is_string_type())
|
||||
return std::string_view{v};
|
||||
else
|
||||
return v;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
// tie_sv(): deduce each Tp from your lvalues, then build tuple<...> out of
|
||||
// either Tp& or std::string_view, calling operator() on each.
|
||||
template <typename... Tp>
|
||||
constexpr auto
|
||||
tie_sv(Tp&... vs) noexcept
|
||||
{
|
||||
return std::make_tuple(detail::sv_trait<Tp>{}(vs)...);
|
||||
}
|
||||
} // namespace operators
|
||||
} // namespace sdk
|
||||
} // namespace rocprofiler
|
||||
@@ -110,6 +145,8 @@ ROCPROFILER_CXX_DECLARE_OPERATORS(rocprofiler_dim3_t)
|
||||
ROCPROFILER_CXX_DECLARE_OPERATORS(hsa_region_t)
|
||||
ROCPROFILER_CXX_DECLARE_OPERATORS(hsa_amd_memory_pool_t)
|
||||
ROCPROFILER_CXX_DECLARE_OPERATORS(const rocprofiler_counter_record_dimension_info_t&)
|
||||
ROCPROFILER_CXX_DECLARE_OPERATORS(const rocprofiler_counter_record_dimension_instance_info_t&)
|
||||
ROCPROFILER_CXX_DECLARE_OPERATORS(const rocprofiler_counter_dimension_info_t&)
|
||||
ROCPROFILER_CXX_DECLARE_OPERATORS(rocprofiler_version_triplet_t)
|
||||
|
||||
// definitions of operator==
|
||||
@@ -141,11 +178,43 @@ operator==(rocprofiler_dim3_t lhs, rocprofiler_dim3_t rhs)
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(rocprofiler_counter_record_dimension_info_t lhs,
|
||||
rocprofiler_counter_record_dimension_info_t rhs)
|
||||
operator==(const rocprofiler_counter_record_dimension_info_t& lhs,
|
||||
const rocprofiler_counter_record_dimension_info_t& rhs)
|
||||
{
|
||||
return std::tie(lhs.id, lhs.instance_size, lhs.name) ==
|
||||
std::tie(rhs.id, rhs.instance_size, rhs.name);
|
||||
namespace op = ::rocprofiler::sdk::operators;
|
||||
return op::tie_sv(lhs.id, lhs.instance_size, lhs.name) ==
|
||||
op::tie_sv(rhs.id, rhs.instance_size, rhs.name);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const rocprofiler_counter_dimension_info_t& lhs,
|
||||
const rocprofiler_counter_dimension_info_t& rhs)
|
||||
{
|
||||
namespace op = ::rocprofiler::sdk::operators;
|
||||
return op::tie_sv(lhs.dimension_name, lhs.index, lhs.size) ==
|
||||
op::tie_sv(rhs.dimension_name, rhs.index, rhs.size);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator==(const rocprofiler_counter_record_dimension_instance_info_t& lhs,
|
||||
const rocprofiler_counter_record_dimension_instance_info_t& rhs)
|
||||
{
|
||||
if(std::tie(lhs.instance_id, lhs.counter_id, lhs.dimensions_count) !=
|
||||
std::tie(rhs.instance_id, rhs.counter_id, rhs.dimensions_count))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for(uint64_t i = 0; i < lhs.dimensions_count; ++i)
|
||||
{
|
||||
if(lhs.dimensions[i] == nullptr && rhs.dimensions[i] == nullptr) continue;
|
||||
if(!lhs.dimensions[i] || !rhs.dimensions[i] || *lhs.dimensions[i] != *rhs.dimensions[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
@@ -193,8 +262,35 @@ inline bool
|
||||
operator<(const rocprofiler_counter_record_dimension_info_t& lhs,
|
||||
const rocprofiler_counter_record_dimension_info_t& rhs)
|
||||
{
|
||||
return std::tie(lhs.id, lhs.instance_size, lhs.name) <
|
||||
std::tie(rhs.id, rhs.instance_size, rhs.name);
|
||||
namespace op = ::rocprofiler::sdk::operators;
|
||||
return op::tie_sv(lhs.id, lhs.instance_size, lhs.name) <
|
||||
op::tie_sv(rhs.id, rhs.instance_size, rhs.name);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator<(const rocprofiler_counter_dimension_info_t& lhs,
|
||||
const rocprofiler_counter_dimension_info_t& rhs)
|
||||
{
|
||||
namespace op = ::rocprofiler::sdk::operators;
|
||||
return op::tie_sv(lhs.dimension_name, lhs.index, lhs.size) <
|
||||
op::tie_sv(rhs.dimension_name, rhs.index, rhs.size);
|
||||
}
|
||||
|
||||
inline bool
|
||||
operator<(const rocprofiler_counter_record_dimension_instance_info_t& lhs,
|
||||
const rocprofiler_counter_record_dimension_instance_info_t& rhs)
|
||||
{
|
||||
if(lhs.instance_id != rhs.instance_id) return lhs.instance_id < rhs.instance_id;
|
||||
if(lhs.counter_id != rhs.counter_id) return lhs.counter_id < rhs.counter_id;
|
||||
if(lhs.dimensions_count != rhs.dimensions_count)
|
||||
return lhs.dimensions_count < rhs.dimensions_count;
|
||||
|
||||
for(uint64_t i = 0; i < lhs.dimensions_count; ++i)
|
||||
{
|
||||
if(!lhs.dimensions[i] || !rhs.dimensions[i]) return *lhs.dimensions[i] < *rhs.dimensions[i];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <rocprofiler-sdk/internal_threading.h>
|
||||
#include <rocprofiler-sdk/marker.h>
|
||||
#include <rocprofiler-sdk/pc_sampling.h>
|
||||
#include <rocprofiler-sdk/cxx/container/c_array.hpp>
|
||||
#include <rocprofiler-sdk/cxx/name_info.hpp>
|
||||
#include <rocprofiler-sdk/cxx/utility.hpp>
|
||||
|
||||
@@ -1236,16 +1237,33 @@ save(ArchiveT& ar, rocprofiler_counter_info_v1_t data)
|
||||
ROCP_SDK_SAVE_DATA_CSTR(block);
|
||||
ROCP_SDK_SAVE_DATA_CSTR(expression);
|
||||
|
||||
auto convert = [](const auto* val, uint64_t sz) {
|
||||
using data_type = std::remove_cv_t<std::remove_pointer_t<decltype(val)>>;
|
||||
auto retval = std::vector<data_type>{};
|
||||
for(uint64_t i = 0; i < sz; ++i)
|
||||
retval.emplace_back(val[i]);
|
||||
return retval;
|
||||
};
|
||||
ROCP_SDK_SAVE_VALUE(
|
||||
"dimensions",
|
||||
rocprofiler::sdk::container::make_c_array(data.dimensions, data.dimensions_count));
|
||||
|
||||
ROCP_SDK_SAVE_VALUE("dims", convert(data.dimensions, data.dimensions_count));
|
||||
ROCP_SDK_SAVE_VALUE("instances", convert(data.instance_ids, data.instance_ids_count));
|
||||
ROCP_SDK_SAVE_VALUE("instances",
|
||||
rocprofiler::sdk::container::make_c_array(data.dimensions_instances,
|
||||
data.dimensions_instances_count));
|
||||
}
|
||||
|
||||
template <typename ArchiveT>
|
||||
void
|
||||
save(ArchiveT& ar, rocprofiler_counter_dimension_info_t data)
|
||||
{
|
||||
ROCP_SDK_SAVE_DATA_CSTR(dimension_name);
|
||||
ROCP_SDK_SAVE_DATA_FIELD(index);
|
||||
}
|
||||
|
||||
template <typename ArchiveT>
|
||||
void
|
||||
save(ArchiveT& ar, rocprofiler_counter_record_dimension_instance_info_t data)
|
||||
{
|
||||
ROCP_SDK_SAVE_DATA_FIELD(instance_id);
|
||||
ROCP_SDK_SAVE_DATA_FIELD(counter_id);
|
||||
|
||||
ROCP_SDK_SAVE_VALUE(
|
||||
"dimensions",
|
||||
rocprofiler::sdk::container::make_c_array(data.dimensions, data.dimensions_count));
|
||||
}
|
||||
|
||||
template <typename ArchiveT>
|
||||
@@ -1303,6 +1321,28 @@ save(ArchiveT& ar, const rocprofiler::sdk::utility::name_info_impl<EnumT, ValueT
|
||||
ar(cereal::make_nvp("operations", _ops));
|
||||
}
|
||||
|
||||
template <typename ArchiveT, typename Tp>
|
||||
void
|
||||
save(ArchiveT& ar, const rocprofiler::sdk::container::c_array<Tp>& data)
|
||||
{
|
||||
ar(make_size_tag(data.size()));
|
||||
for(auto itr : data)
|
||||
ar(itr);
|
||||
}
|
||||
|
||||
template <typename ArchiveT, typename Tp>
|
||||
void
|
||||
save(ArchiveT& ar, const rocprofiler::sdk::container::c_array<Tp*>& data)
|
||||
{
|
||||
size_type _sz = 0;
|
||||
for(auto* itr : data)
|
||||
if(itr) ++_sz;
|
||||
|
||||
ar(make_size_tag(_sz));
|
||||
for(auto* itr : data)
|
||||
ar(*itr);
|
||||
}
|
||||
|
||||
ROCPROFILER_SDK_CEREAL_NAMESPACE_END
|
||||
|
||||
#undef ROCP_SDK_SAVE_DATA_FIELD
|
||||
|
||||
Fai riferimento in un nuovo problema
Block a user