ROCpd support [Part 1] (#279)
- Add rocpd support for - cpu_frequency - amd_smi - sampling
This commit is contained in:
committed by
GitHub
parent
4b4a846b58
commit
26ae543012
@@ -6,31 +6,38 @@ configure_file(
|
||||
)
|
||||
|
||||
set(core_sources
|
||||
${CMAKE_CURRENT_LIST_DIR}/agent_manager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/amd_smi.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/argparse.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/categories.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/config.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/constraint.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/cpu.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/debug.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/dynamic_library.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/exception.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/gpu.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mproc.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/node_info.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/perf.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/perfetto.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/rocprofiler-sdk.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/amd_smi.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/state.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/timemory.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/utility.cpp
|
||||
)
|
||||
|
||||
set(core_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/agent.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/agent_manager.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/amd_smi.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/argparse.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/categories.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/common.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/concepts.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/config.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/constraint.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/cpu.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/debug.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/dynamic_library.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/exception.hpp
|
||||
@@ -38,11 +45,11 @@ set(core_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/locking.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mpi.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/mproc.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/node_info.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/perf.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/perfetto.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/redirect.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/rocprofiler-sdk.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/amd_smi.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/state.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/timemory.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/utility.hpp
|
||||
@@ -61,6 +68,7 @@ target_sources(
|
||||
add_subdirectory(binary)
|
||||
add_subdirectory(components)
|
||||
add_subdirectory(containers)
|
||||
add_subdirectory(rocpd)
|
||||
|
||||
target_include_directories(
|
||||
rocprofiler-systems-core-library
|
||||
@@ -95,6 +103,22 @@ target_link_libraries(
|
||||
$<BUILD_INTERFACE:$<IF:$<BOOL:${ROCPROFSYS_BUILD_LTO}>,rocprofiler-systems::rocprofiler-systems-lto,>>
|
||||
)
|
||||
|
||||
file(GLOB ROCPD_SCHEMA_FILES "${CMAKE_CURRENT_LIST_DIR}/rocpd/data_storage/schema/*.sql")
|
||||
|
||||
foreach(_SRC ${ROCPD_SCHEMA_FILES})
|
||||
cmake_path(GET _SRC FILENAME _BASE)
|
||||
configure_file(
|
||||
${_SRC}
|
||||
${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/${_BASE}
|
||||
COPYONLY
|
||||
)
|
||||
install(
|
||||
FILES ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/${_BASE}
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}
|
||||
COMPONENT core
|
||||
)
|
||||
endforeach()
|
||||
|
||||
set_target_properties(
|
||||
rocprofiler-systems-core-library
|
||||
PROPERTIES OUTPUT_NAME ${BINARY_NAME_PREFIX}-core
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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 <string>
|
||||
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
# include <amd_smi/amdsmi.h>
|
||||
# include <rocprofiler-sdk/agent.h>
|
||||
#endif
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
|
||||
enum class agent_type : uint8_t
|
||||
{
|
||||
CPU, ///< Agent type is a CPU
|
||||
GPU ///< Agent type is a GPU
|
||||
};
|
||||
|
||||
struct agent
|
||||
{
|
||||
agent_type type;
|
||||
uint64_t id;
|
||||
uint32_t node_id;
|
||||
int32_t logical_node_id;
|
||||
int32_t logical_node_type_id;
|
||||
std::string name;
|
||||
std::string model_name;
|
||||
std::string vendor_name;
|
||||
std::string product_name;
|
||||
|
||||
size_t device_id{ 0 };
|
||||
size_t base_id{ 0 };
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
amdsmi_processor_handle smi_handle = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,137 @@
|
||||
// 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.
|
||||
|
||||
#include "agent_manager.hpp"
|
||||
#include "debug.hpp"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
|
||||
agent_manager&
|
||||
agent_manager::get_instance()
|
||||
{
|
||||
static agent_manager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void
|
||||
agent_manager::insert_agent(agent& _agent)
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(
|
||||
3, "Inserting agent with device handle: %lu, and agent id: %ld, device type: %s",
|
||||
_agent.device_id,
|
||||
(_agent.type == agent_type::GPU ? _gpu_agents_cnt : _cpu_agents_cnt),
|
||||
(_agent.type == agent_type::GPU ? "GPU" : "CPU"));
|
||||
|
||||
_agent.device_id =
|
||||
(_agent.type == agent_type::GPU ? _gpu_agents_cnt++ : _cpu_agents_cnt++);
|
||||
_agents.emplace_back(std::make_shared<agent>(_agent));
|
||||
}
|
||||
|
||||
const agent&
|
||||
agent_manager::get_agent_by_id(size_t device_id, agent_type type) const
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(3, "Getting agent for device id: %ld, type %s\n", device_id,
|
||||
(type == agent_type::GPU) ? "GPU" : "CPU");
|
||||
auto _agent =
|
||||
std::find_if(_agents.begin(), _agents.end(), [&](const auto& agent_ptr) {
|
||||
return agent_ptr->type == type && agent_ptr->device_id == device_id;
|
||||
});
|
||||
if(_agent == _agents.end())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Agent not found for device id: " << device_id
|
||||
<< ", type: " << (type == agent_type::GPU ? "GPU" : "CPU");
|
||||
throw std::out_of_range(oss.str());
|
||||
}
|
||||
return **_agent;
|
||||
}
|
||||
|
||||
const agent&
|
||||
agent_manager::get_agent_by_handle(uint64_t device_handle, agent_type type) const
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(3, "Getting agent for device handle: %ld, type %s\n",
|
||||
device_handle, (type == agent_type::GPU ? "GPU" : "CPU"));
|
||||
auto _agent =
|
||||
std::find_if(_agents.begin(), _agents.end(), [&](const auto& agent_ptr) {
|
||||
return agent_ptr->type == type && agent_ptr->id == device_handle;
|
||||
});
|
||||
if(_agent == _agents.end())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Agent not found for device handle: " << device_handle
|
||||
<< ", type: " << (type == agent_type::GPU ? "GPU" : "CPU");
|
||||
throw std::out_of_range(oss.str());
|
||||
}
|
||||
return **_agent;
|
||||
}
|
||||
|
||||
const agent&
|
||||
agent_manager::get_agent_by_handle(size_t device_handle) const
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(3, "Getting agent for device handle: %ld\n", device_handle);
|
||||
auto _agent =
|
||||
std::find_if(_agents.begin(), _agents.end(), [&](const auto& agent_ptr) {
|
||||
return agent_ptr->id == device_handle;
|
||||
});
|
||||
if(_agent == _agents.end())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Agent not found for device handle: " << device_handle;
|
||||
throw std::out_of_range(oss.str());
|
||||
}
|
||||
return **_agent;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<agent>>
|
||||
agent_manager::get_agents_by_type(agent_type type) const
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(3, "Getting agent for device type: %s\n",
|
||||
type == agent_type::GPU ? "GPU" : "CPU");
|
||||
|
||||
std::vector<std::shared_ptr<agent>> agents;
|
||||
std::copy_if(std::begin(_agents), std::end(_agents), std::back_inserter(agents),
|
||||
[&type](const auto& agent_ptr) { return agent_ptr->type == type; });
|
||||
return agents;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<agent>>
|
||||
agent_manager::get_agents() const
|
||||
{
|
||||
return _agents;
|
||||
}
|
||||
|
||||
size_t
|
||||
agent_manager::get_gpu_agents_count() const
|
||||
{
|
||||
return _gpu_agents_cnt;
|
||||
}
|
||||
|
||||
size_t
|
||||
agent_manager::get_cpu_agents_count() const
|
||||
{
|
||||
return _cpu_agents_cnt;
|
||||
}
|
||||
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,62 @@
|
||||
// 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 <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "agent.hpp"
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
|
||||
struct agent_manager
|
||||
{
|
||||
static agent_manager& get_instance();
|
||||
|
||||
agent_manager(const agent_manager&) = delete;
|
||||
agent_manager& operator=(const agent_manager&) = delete;
|
||||
agent_manager(agent_manager&&) = delete;
|
||||
agent_manager& operator=(agent_manager&&) = delete;
|
||||
~agent_manager() = default;
|
||||
|
||||
void insert_agent(agent& agent);
|
||||
const agent& get_agent_by_id(size_t device_id, agent_type type) const;
|
||||
const agent& get_agent_by_handle(size_t device_id, agent_type type) const;
|
||||
const agent& get_agent_by_handle(size_t device_handle) const;
|
||||
|
||||
std::vector<std::shared_ptr<agent>> get_agents_by_type(agent_type type) const;
|
||||
|
||||
std::vector<std::shared_ptr<agent>> get_agents() const;
|
||||
|
||||
size_t get_gpu_agents_count() const;
|
||||
size_t get_cpu_agents_count() const;
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<agent>> _agents;
|
||||
size_t _gpu_agents_cnt{ 0 };
|
||||
size_t _cpu_agents_cnt{ 0 };
|
||||
agent_manager() = default;
|
||||
};
|
||||
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,353 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022-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 <algorithm>
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <unistd.h>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "core/benchmark/category.hpp"
|
||||
#include "core/debug.hpp"
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace benchmark
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <bool enabled, typename category_enum, category_enum... enabled_categories>
|
||||
struct benchmark_impl
|
||||
{
|
||||
template <category_enum... categories>
|
||||
struct scope
|
||||
{
|
||||
scope(const scope&) = delete;
|
||||
scope& operator=(const scope&) = delete;
|
||||
~scope() = default;
|
||||
|
||||
protected:
|
||||
scope() = default;
|
||||
scope(scope&&) = default;
|
||||
scope& operator=(scope&&) = default;
|
||||
};
|
||||
|
||||
template <category_enum... categories>
|
||||
static void start()
|
||||
{}
|
||||
|
||||
template <category_enum... categories>
|
||||
static void end()
|
||||
{}
|
||||
|
||||
template <category_enum... categories>
|
||||
[[nodiscard]] static scope<categories...> scoped_trace()
|
||||
{
|
||||
return scope<categories...>{};
|
||||
}
|
||||
|
||||
static void init_from_env(const char* = nullptr) {}
|
||||
static void show_results() {}
|
||||
};
|
||||
|
||||
using tid_t = __pid_t;
|
||||
struct indexed_category
|
||||
{
|
||||
size_t category;
|
||||
tid_t thread_id;
|
||||
|
||||
friend bool operator==(const indexed_category& lhs, const indexed_category& rhs)
|
||||
{
|
||||
return lhs.category == rhs.category && lhs.thread_id == rhs.thread_id;
|
||||
}
|
||||
};
|
||||
|
||||
struct indexed_category_hash
|
||||
{
|
||||
size_t operator()(const indexed_category& p) const noexcept
|
||||
{
|
||||
std::size_t hash1 = std::hash<size_t>{}(p.category);
|
||||
std::size_t hash2 = std::hash<size_t>{}(p.thread_id);
|
||||
return hash1 ^ (hash2 << 1);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename category_enum, category_enum... enabled_categories>
|
||||
struct benchmark_impl<true, category_enum, enabled_categories...>
|
||||
{
|
||||
static_assert(std::is_enum_v<category_enum>, "category_enum must be an enum");
|
||||
|
||||
public:
|
||||
using clock = std::chrono::high_resolution_clock;
|
||||
using time_point = clock::time_point;
|
||||
static constexpr size_t _max_categories = static_cast<size_t>(category_enum::count);
|
||||
|
||||
template <category_enum... categories>
|
||||
struct scope
|
||||
{
|
||||
friend benchmark_impl;
|
||||
|
||||
public:
|
||||
scope(const scope&) = delete;
|
||||
scope& operator=(const scope&) = delete;
|
||||
~scope() { end<categories...>(); }
|
||||
|
||||
protected:
|
||||
scope() { start<categories...>(); }
|
||||
|
||||
scope(scope&&) = default;
|
||||
scope& operator=(scope&&) = default;
|
||||
};
|
||||
|
||||
template <category_enum... categories>
|
||||
static void start()
|
||||
{
|
||||
static const thread_local auto _thread_id = gettid();
|
||||
const auto now = clock::now();
|
||||
std::lock_guard lock(m_mutex);
|
||||
(..., (is_category_defined<categories>([&] {
|
||||
if(m_enabled.test(to_index(categories)))
|
||||
m_started[{ to_index(categories), _thread_id }] = now;
|
||||
})));
|
||||
}
|
||||
|
||||
template <category_enum... categories>
|
||||
static void end()
|
||||
{
|
||||
static const thread_local auto _thread_id = getpid();
|
||||
const auto _end_time = clock::now();
|
||||
std::lock_guard lock(m_mutex);
|
||||
(..., (is_category_defined<categories>([&] {
|
||||
if(m_enabled.test(to_index(categories)))
|
||||
end_category(_end_time, categories, _thread_id);
|
||||
})));
|
||||
}
|
||||
|
||||
template <category_enum... categories>
|
||||
[[nodiscard]] static scope<categories...> scoped_trace()
|
||||
{
|
||||
return scope<categories...>{};
|
||||
}
|
||||
|
||||
static void init_from_env(const char* envVar = "ROCPROFSYS_BENCHMARK_CATEGORIES")
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
const auto* env = std::getenv(envVar);
|
||||
if(env == nullptr || std::string(env).empty())
|
||||
{
|
||||
ROCPROFSYS_WARNING(1, "No BENCHMARK categories specified in environment "
|
||||
"variable ROCPROFSYS_BENCHMARK_CATEGORIES.\n");
|
||||
return;
|
||||
}
|
||||
std::string _str(env);
|
||||
std::istringstream ss(_str);
|
||||
std::string token;
|
||||
|
||||
while(std::getline(ss, token, ','))
|
||||
{
|
||||
token.erase(0, token.find_first_not_of(" \t"));
|
||||
token.erase(token.find_last_not_of(" \t") + 1);
|
||||
for(category_enum cat : compiledCategories)
|
||||
{
|
||||
if(to_string(cat) == token)
|
||||
{
|
||||
m_enabled.set(to_index(cat));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void show_results()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
std::vector<std::pair<category_enum, result_data>> sorted;
|
||||
|
||||
for(category_enum cat : compiledCategories)
|
||||
{
|
||||
const auto& data = m_results[to_index(cat)];
|
||||
if(data.count > 0)
|
||||
{
|
||||
sorted.emplace_back(cat, data);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(sorted.begin(), sorted.end(), [](const auto& a, const auto& b) {
|
||||
return a.second.total_time > b.second.total_time;
|
||||
});
|
||||
|
||||
constexpr uint32_t _category = 30;
|
||||
constexpr uint32_t _calls = 8;
|
||||
constexpr uint32_t _total = 12;
|
||||
constexpr uint32_t _avg = 10;
|
||||
constexpr uint32_t _min = 10;
|
||||
constexpr uint32_t _max = 10;
|
||||
|
||||
std::cout << "\033[32m"
|
||||
<< std::string(_category + _calls + _total + _avg + _min + _max, '=')
|
||||
<< "\n";
|
||||
std::cout << "Benchmark Results (Sorted by Total Time):\n";
|
||||
std::cout << std::string(_category + _calls + _total + _avg + _min + _max, '-')
|
||||
<< "\n";
|
||||
std::cout << std::left << std::setw(_category) << "Category" << std::right
|
||||
<< std::setw(_calls) << "Calls" << std::setw(_total) << "Total(ms)"
|
||||
<< std::setw(_avg) << "Avg(us)" << std::setw(_min) << "Min(us)"
|
||||
<< std::setw(_max) << "Max(us)" << "\n";
|
||||
|
||||
std::cout << std::string(_category + _calls + _total + _avg + _min + _max, '-')
|
||||
<< "\n";
|
||||
|
||||
for(const auto& [cat, data] : sorted)
|
||||
{
|
||||
double totalMs = static_cast<double>(data.total_time) / 1000.0;
|
||||
double avgUs = static_cast<double>(data.total_time) / data.count;
|
||||
|
||||
std::cout << std::left << std::setw(_category) << to_string(cat) << std::right
|
||||
<< std::setw(_calls) << data.count << std::setw(_total)
|
||||
<< std::fixed << std::setprecision(3) << totalMs << std::setw(_avg)
|
||||
<< std::fixed << std::setprecision(1) << avgUs << std::setw(_min)
|
||||
<< data.min_time << std::setw(_max) << data.max_time << "\n";
|
||||
}
|
||||
|
||||
std::cout << std::string(_category + _calls + _total + _avg + _min + _max, '=')
|
||||
<< "\033[0m" << "\n\n";
|
||||
}
|
||||
|
||||
private:
|
||||
struct result_data
|
||||
{
|
||||
uint64_t total_time = 0;
|
||||
size_t count = 0;
|
||||
uint64_t min_time = std::numeric_limits<uint64_t>::max();
|
||||
uint64_t max_time = std::numeric_limits<uint64_t>::min();
|
||||
|
||||
void update(uint64_t duration)
|
||||
{
|
||||
total_time += duration;
|
||||
count += 1;
|
||||
if(duration < min_time) min_time = duration;
|
||||
if(duration > max_time) max_time = duration;
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr size_t to_index(category_enum cat)
|
||||
{
|
||||
return static_cast<size_t>(cat);
|
||||
}
|
||||
|
||||
static void end_category(const time_point& end_time, category_enum cat,
|
||||
const tid_t thread_id)
|
||||
{
|
||||
const size_t _idx = to_index(cat);
|
||||
auto _it = m_started.find({ _idx, thread_id });
|
||||
if(_it == m_started.end())
|
||||
{
|
||||
ROCPROFSYS_WARNING(1, "Benchmark error: missing start time for category!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
auto duration =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(end_time - _it->second)
|
||||
.count();
|
||||
m_started.erase(_it);
|
||||
m_results[_idx].update(duration);
|
||||
}
|
||||
|
||||
template <category_enum Cat, typename Func>
|
||||
static constexpr void is_category_defined(Func&& f)
|
||||
{
|
||||
if constexpr(((Cat == enabled_categories) || ...))
|
||||
{
|
||||
f();
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr std::array<category_enum, sizeof...(enabled_categories)>
|
||||
compiledCategories = { enabled_categories... };
|
||||
|
||||
static inline std::unordered_map<indexed_category, time_point, indexed_category_hash>
|
||||
m_started;
|
||||
static inline std::array<result_data, _max_categories> m_results{};
|
||||
static inline std::bitset<_max_categories> m_enabled;
|
||||
static inline std::mutex m_mutex;
|
||||
};
|
||||
|
||||
#ifdef ROCPROFSYS_ENABLE_BENCHMARK
|
||||
using _benchmark_impl = benchmark::benchmark_impl<
|
||||
static_cast<bool>(ROCPROFSYS_ENABLE_BENCHMARK), benchmark::category,
|
||||
benchmark::category::kernel_dispatch, benchmark::category::memory_copy,
|
||||
benchmark::category::memory_allocate, benchmark::category::db_entry_kernel_dispatch,
|
||||
benchmark::category::db_entry_memory_copy,
|
||||
benchmark::category::db_entry_memory_allocate,
|
||||
benchmark::category::perfetto_kernel_dispatch,
|
||||
benchmark::category::sdk_tool_buffered_tracing>;
|
||||
#else
|
||||
using _benchmark_impl = benchmark::benchmark_impl<false, benchmark::category>;
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
template <category... categories>
|
||||
void
|
||||
start()
|
||||
{
|
||||
_benchmark_impl::template start<categories...>();
|
||||
}
|
||||
|
||||
template <category... categories>
|
||||
void
|
||||
end()
|
||||
{
|
||||
_benchmark_impl::template end<categories...>();
|
||||
}
|
||||
|
||||
template <category... categories>
|
||||
[[nodiscard]] auto
|
||||
scoped_trace()
|
||||
{
|
||||
return _benchmark_impl::template scoped_trace<categories...>();
|
||||
}
|
||||
|
||||
inline void
|
||||
init_from_env(const char* envVar = "BENCHMARK_CATEGORIES")
|
||||
{
|
||||
_benchmark_impl::init_from_env(envVar);
|
||||
}
|
||||
|
||||
inline void
|
||||
show_results()
|
||||
{
|
||||
_benchmark_impl::show_results();
|
||||
}
|
||||
|
||||
} // namespace benchmark
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2018-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
|
||||
// with 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:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimers.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimers in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the names of Advanced Micro Devices, Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this Software without specific prior written permission.
|
||||
//
|
||||
// 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
|
||||
// CONTRIBUTORS 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 WITH
|
||||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace benchmark
|
||||
{
|
||||
enum class category
|
||||
{
|
||||
kernel_dispatch,
|
||||
db_entry_kernel_dispatch,
|
||||
memory_copy,
|
||||
db_entry_memory_copy,
|
||||
memory_allocate,
|
||||
db_entry_memory_allocate,
|
||||
perfetto_kernel_dispatch,
|
||||
sdk_tool_buffered_tracing,
|
||||
count
|
||||
};
|
||||
|
||||
constexpr std::string_view
|
||||
to_string(category cat)
|
||||
{
|
||||
switch(cat)
|
||||
{
|
||||
case category::kernel_dispatch: return "kernel_dispatch";
|
||||
case category::db_entry_kernel_dispatch: return "db_entry_kernel_dispatch";
|
||||
case category::memory_copy: return "memory_copy";
|
||||
case category::memory_allocate: return "memory_allocate";
|
||||
case category::db_entry_memory_copy: return "db_entry_memory_copy";
|
||||
case category::db_entry_memory_allocate: return "db_entry_memory_allocate";
|
||||
case category::perfetto_kernel_dispatch: return "perfetto_kernel_dispatch";
|
||||
case category::sdk_tool_buffered_tracing: return "sdk_tool_buffered_tracing";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace benchmark
|
||||
} // namespace rocprofsys
|
||||
@@ -312,6 +312,9 @@ configure_settings(bool _init)
|
||||
"Enable causal profiling analysis", false, "backend",
|
||||
"causal", "analysis");
|
||||
|
||||
ROCPROFSYS_CONFIG_SETTING(bool, "ROCPROFSYS_USE_ROCPD", "Enable rocpd backend", false,
|
||||
"backend", "rocpd");
|
||||
|
||||
ROCPROFSYS_CONFIG_SETTING(bool, "ROCPROFSYS_USE_ROCM",
|
||||
"Enable ROCm API and kernel tracing", true, "backend",
|
||||
"rocm");
|
||||
@@ -1246,10 +1249,17 @@ configure_signal_handler(const std::shared_ptr<settings>& _config)
|
||||
static auto _dyninst_trampoline_signal =
|
||||
getenv("DYNINST_SIGNAL_TRAMPOLINE_SIGILL") ? SIGILL : SIGTRAP;
|
||||
|
||||
static auto root_pid =
|
||||
get_env<pid_t>("ROCPROFSYS_ROOT_PROCESS", process::get_id(), false);
|
||||
if(_config->get_enable_signal_handler())
|
||||
{
|
||||
tim::signals::disable_signal_detection();
|
||||
signal_settings::enable(sys_signal::Interrupt);
|
||||
auto is_child_process = root_pid != getpid();
|
||||
if(is_child_process)
|
||||
{
|
||||
signal_settings::enable(sys_signal::Terminate);
|
||||
}
|
||||
signal_settings::set_exit_action(rocprofsys_exit_action);
|
||||
signal_settings::check_environment();
|
||||
auto default_signals = signal_settings::get_default();
|
||||
@@ -2347,6 +2357,40 @@ get_tmpdir()
|
||||
return static_cast<tim::tsettings<std::string>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
std::string
|
||||
get_database_absolute_path(std::string_view database_name)
|
||||
{
|
||||
const auto* _existing_path = std::getenv("ROCPROFSYS_DATABASE_DIR");
|
||||
auto _dir = _existing_path ? std::string{ _existing_path } : std::string{};
|
||||
auto _ext = std::string{ "db" };
|
||||
|
||||
auto _cfg = settings::compose_filename_config{ settings::use_output_suffix(),
|
||||
settings::default_process_suffix(),
|
||||
false, _dir };
|
||||
|
||||
const auto get_path = [](const std::string& path) {
|
||||
size_t last_slash = path.find_last_of("/\\");
|
||||
return (last_slash != std::string::npos) ? path.substr(0, last_slash + 1)
|
||||
: std::string{};
|
||||
};
|
||||
|
||||
auto _val = settings::compose_output_filename(std::string(database_name), _ext, _cfg);
|
||||
_dir = get_path(_val);
|
||||
|
||||
setenv("ROCPROFSYS_DATABASE_DIR", _dir.c_str(), 1);
|
||||
|
||||
if(!_val.empty() && _val.at(0) != '/')
|
||||
return settings::format(JOIN('/', "%env{PWD}%", _val), get_config()->get_tag());
|
||||
return _val;
|
||||
}
|
||||
|
||||
bool&
|
||||
get_use_rocpd()
|
||||
{
|
||||
static auto _v = get_config()->at("ROCPROFSYS_USE_ROCPD");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v).get();
|
||||
}
|
||||
|
||||
tmp_file::tmp_file(std::string _v)
|
||||
: filename{ std::move(_v) }
|
||||
{}
|
||||
|
||||
@@ -358,6 +358,12 @@ get_use_tmp_files();
|
||||
std::string
|
||||
get_tmpdir();
|
||||
|
||||
std::string
|
||||
get_database_absolute_path(std::string_view database_name);
|
||||
|
||||
bool&
|
||||
get_use_rocpd() ROCPROFSYS_HOT;
|
||||
|
||||
struct tmp_file
|
||||
{
|
||||
tmp_file(std::string);
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
#include "cpu.hpp"
|
||||
#include "agent_manager.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace cpu
|
||||
{
|
||||
std::vector<cpu_info>
|
||||
process_cpu_info_data()
|
||||
{
|
||||
std::vector<cpu_info> cpu_data;
|
||||
std::ifstream cpuinfo_file("/proc/cpuinfo");
|
||||
|
||||
if(!cpuinfo_file.is_open())
|
||||
{
|
||||
return cpu_data;
|
||||
}
|
||||
|
||||
std::string line;
|
||||
cpu_info current_cpu;
|
||||
bool has_processor_entry = false;
|
||||
|
||||
auto parse_long = [](const std::string& value) -> long {
|
||||
try
|
||||
{
|
||||
return std::stol(value);
|
||||
} catch(const std::exception&)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
auto trim_whitespace = [](const std::string& str) -> std::string {
|
||||
size_t start = str.find_first_not_of(" \t");
|
||||
if(start == std::string::npos) return "";
|
||||
size_t end = str.find_last_not_of(" \t");
|
||||
return str.substr(start, end - start + 1);
|
||||
};
|
||||
|
||||
static const std::unordered_map<std::string,
|
||||
std::function<void(cpu_info&, const std::string&)>>
|
||||
field_parsers = {
|
||||
{ "processor",
|
||||
[&parse_long](cpu_info& cpu, const std::string& val) {
|
||||
cpu.processor = parse_long(val);
|
||||
} },
|
||||
{ "cpu family",
|
||||
[&parse_long](cpu_info& cpu, const std::string& val) {
|
||||
cpu.family = parse_long(val);
|
||||
} },
|
||||
{ "model",
|
||||
[&parse_long](cpu_info& cpu, const std::string& val) {
|
||||
cpu.model = parse_long(val);
|
||||
} },
|
||||
{ "physical id",
|
||||
[&parse_long](cpu_info& cpu, const std::string& val) {
|
||||
cpu.physical_id = parse_long(val);
|
||||
} },
|
||||
{ "core id",
|
||||
[&parse_long](cpu_info& cpu, const std::string& val) {
|
||||
cpu.core_id = parse_long(val);
|
||||
} },
|
||||
{ "apicid",
|
||||
[&parse_long](cpu_info& cpu, const std::string& val) {
|
||||
cpu.apicid = parse_long(val);
|
||||
} },
|
||||
{ "vendor_id",
|
||||
[](cpu_info& cpu, const std::string& val) { cpu.vendor_id = val; } },
|
||||
{ "model name",
|
||||
[](cpu_info& cpu, const std::string& val) { cpu.model_name = val; } }
|
||||
};
|
||||
|
||||
while(std::getline(cpuinfo_file, line))
|
||||
{
|
||||
if(line.empty())
|
||||
{
|
||||
if(has_processor_entry)
|
||||
{
|
||||
cpu_data.push_back(current_cpu);
|
||||
return cpu_data; // Return immediately after first core
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t colon_pos = line.find(':');
|
||||
if(colon_pos == std::string::npos)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string key = trim_whitespace(line.substr(0, colon_pos));
|
||||
std::string value = trim_whitespace(line.substr(colon_pos + 1));
|
||||
|
||||
std::transform(key.begin(), key.end(), key.begin(), ::tolower);
|
||||
|
||||
auto it = field_parsers.find(key);
|
||||
if(it != field_parsers.end())
|
||||
{
|
||||
it->second(current_cpu, value);
|
||||
if(key == "processor")
|
||||
{
|
||||
has_processor_entry = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(has_processor_entry)
|
||||
{
|
||||
cpu_data.push_back(current_cpu);
|
||||
}
|
||||
|
||||
return cpu_data;
|
||||
}
|
||||
|
||||
std::vector<cpu_info>
|
||||
get_cpu_info()
|
||||
{
|
||||
static auto _v = process_cpu_info_data();
|
||||
return _v;
|
||||
}
|
||||
|
||||
size_t
|
||||
device_count()
|
||||
{
|
||||
auto cpu_data = get_cpu_info();
|
||||
return cpu_data.size();
|
||||
}
|
||||
|
||||
void
|
||||
query_cpu_agents()
|
||||
{
|
||||
int32_t id_count = 0;
|
||||
uint32_t node_count = 0;
|
||||
uint32_t cpu_count = 0;
|
||||
|
||||
if(device_count() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
auto cpu_data = get_cpu_info();
|
||||
|
||||
for(auto& cpu : cpu_data)
|
||||
{
|
||||
auto node_id = node_count++;
|
||||
auto logical_id = id_count++;
|
||||
auto id = cpu_count++;
|
||||
auto cur_agent = agent{ agent_type::CPU,
|
||||
id,
|
||||
node_id,
|
||||
logical_id,
|
||||
static_cast<int32_t>(id),
|
||||
cpu.model_name,
|
||||
cpu.model_name,
|
||||
cpu.vendor_id,
|
||||
"" };
|
||||
_agent_manager.insert_agent(cur_agent);
|
||||
}
|
||||
}
|
||||
} // namespace cpu
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,57 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022-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 <string>
|
||||
#include <vector>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace cpu
|
||||
{
|
||||
|
||||
struct cpu_info
|
||||
{
|
||||
long processor = -1;
|
||||
long family = -1;
|
||||
long model = -1;
|
||||
long physical_id = -1;
|
||||
long core_id = -1;
|
||||
long apicid = -1;
|
||||
std::string vendor_id = {};
|
||||
std::string model_name = {};
|
||||
};
|
||||
|
||||
std::vector<cpu_info>
|
||||
process_cpu_info_data();
|
||||
|
||||
std::vector<cpu_info>
|
||||
get_cpu_info();
|
||||
|
||||
size_t
|
||||
device_count();
|
||||
|
||||
void
|
||||
query_cpu_agents();
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace rocprofsys
|
||||
+50
-21
@@ -20,6 +20,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "agent.hpp"
|
||||
#define ROCPROFILER_SDK_CEREAL_NAMESPACE_BEGIN \
|
||||
namespace tim \
|
||||
{ \
|
||||
@@ -41,6 +42,10 @@
|
||||
|
||||
#include <timemory/manager.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "core/agent_manager.hpp"
|
||||
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
# include <amd_smi/amdsmi.h>
|
||||
# include <rocprofiler-sdk/agent.h>
|
||||
@@ -108,18 +113,31 @@ amdsmi_init()
|
||||
}
|
||||
#endif // ROCPROFSYS_USE_ROCM > 0
|
||||
|
||||
int32_t
|
||||
query_rocm_gpu_agents()
|
||||
size_t
|
||||
query_rocm_agents()
|
||||
{
|
||||
int32_t _dev_cnt = 0;
|
||||
size_t _dev_cnt = 0;
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
auto iterator = [](rocprofiler_agent_version_t /*version*/, const void** agents,
|
||||
size_t num_agents, void* user_data) -> rocprofiler_status_t {
|
||||
auto* _cnt = static_cast<int32_t*>(user_data);
|
||||
auto iterator = []([[maybe_unused]] rocprofiler_agent_version_t version,
|
||||
const void** agents, size_t num_agents,
|
||||
[[maybe_unused]] void* user_data) -> rocprofiler_status_t {
|
||||
auto& _agent_manager = agent_manager::get_instance();
|
||||
for(size_t i = 0; i < num_agents; ++i)
|
||||
{
|
||||
const auto* _agent = static_cast<const rocprofiler_agent_v0_t*>(agents[i]);
|
||||
if(_agent && _agent->type == ROCPROFILER_AGENT_TYPE_GPU) *_cnt += 1;
|
||||
const auto* _agent = static_cast<const rocprofiler_agent_v0_t*>(agents[i]);
|
||||
auto cur_agent = agent{
|
||||
(_agent->type == ROCPROFILER_AGENT_TYPE_GPU ? agent_type::GPU
|
||||
: agent_type::CPU),
|
||||
_agent->device_id,
|
||||
_agent->node_id,
|
||||
_agent->logical_node_id,
|
||||
_agent->logical_node_type_id,
|
||||
std::string(_agent->name),
|
||||
std::string(_agent->vendor_name),
|
||||
std::string(_agent->product_name),
|
||||
std::string(_agent->model_name),
|
||||
};
|
||||
_agent_manager.insert_agent(cur_agent);
|
||||
}
|
||||
return ROCPROFILER_STATUS_SUCCESS;
|
||||
};
|
||||
@@ -127,15 +145,14 @@ query_rocm_gpu_agents()
|
||||
try
|
||||
{
|
||||
rocprofiler_query_available_agents(ROCPROFILER_AGENT_INFO_VERSION_0, iterator,
|
||||
sizeof(rocprofiler_agent_v0_t), &_dev_cnt);
|
||||
sizeof(rocprofiler_agent_v0_t), nullptr);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
ROCPROFSYS_BASIC_VERBOSE(
|
||||
1, "Exception thrown getting the rocm agents: %s. _dev_cnt=%d\n", _e.what(),
|
||||
1, "Exception thrown getting the rocm agents: %s. _dev_cnt=%ld\n", _e.what(),
|
||||
_dev_cnt);
|
||||
}
|
||||
// rocprofiler_query_available_agents(ROCPROFILER_AGENT_INFO_VERSION_0, iterator,
|
||||
// sizeof(rocprofiler_agent_v0_t), &_dev_cnt);
|
||||
_dev_cnt = agent_manager::get_instance().get_gpu_agents_count();
|
||||
#endif
|
||||
return _dev_cnt;
|
||||
}
|
||||
@@ -145,7 +162,7 @@ int
|
||||
device_count()
|
||||
{
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
static int _num_devices = query_rocm_gpu_agents();
|
||||
static int _num_devices = query_rocm_agents();
|
||||
return _num_devices;
|
||||
#else
|
||||
return 0;
|
||||
@@ -174,20 +191,31 @@ add_device_metadata(ArchiveT& ar)
|
||||
#if ROCPROFSYS_USE_ROCM > 0
|
||||
using agent_vec_t = std::vector<rocprofiler_agent_v0_t>;
|
||||
|
||||
auto _agents_vec = agent_vec_t{};
|
||||
auto iterator = [](rocprofiler_agent_version_t /*version*/, const void** agents,
|
||||
size_t num_agents, void* user_data) -> rocprofiler_status_t {
|
||||
auto* _agents_vec_v = static_cast<agent_vec_t*>(user_data);
|
||||
_agents_vec_v->reserve(num_agents);
|
||||
auto iterator_cb = []([[maybe_unused]] rocprofiler_agent_version_t version,
|
||||
const void** agents, size_t num_agents,
|
||||
[[maybe_unused]] void* user_data) -> rocprofiler_status_t {
|
||||
auto* agents_vec = static_cast<agent_vec_t*>(user_data);
|
||||
for(size_t i = 0; i < num_agents; ++i)
|
||||
{
|
||||
const auto* _agent = static_cast<const rocprofiler_agent_v0_t*>(agents[i]);
|
||||
if(_agent) _agents_vec_v->emplace_back(*_agent);
|
||||
if(_agent->type == ROCPROFILER_AGENT_TYPE_GPU)
|
||||
{
|
||||
agents_vec->push_back(*_agent);
|
||||
}
|
||||
}
|
||||
return ROCPROFILER_STATUS_SUCCESS;
|
||||
};
|
||||
rocprofiler_query_available_agents(ROCPROFILER_AGENT_INFO_VERSION_0, iterator,
|
||||
sizeof(rocprofiler_agent_v0_t), &_agents_vec);
|
||||
|
||||
auto _agents_vec = agent_vec_t{};
|
||||
try
|
||||
{
|
||||
rocprofiler_query_available_agents(ROCPROFILER_AGENT_INFO_VERSION_0, iterator_cb,
|
||||
sizeof(rocprofiler_agent_v0_t), &_agents_vec);
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
ROCPROFSYS_BASIC_VERBOSE(1, "Exception thrown getting the rocm agents: %s.\n",
|
||||
_e.what());
|
||||
}
|
||||
|
||||
ar(make_nvp("rocm_agents", _agents_vec));
|
||||
#else
|
||||
@@ -228,6 +256,7 @@ get_processor_handles()
|
||||
{
|
||||
uint32_t socket_count;
|
||||
uint32_t processor_count;
|
||||
processors::processors_list.clear();
|
||||
|
||||
// Passing nullptr will return us the number of sockets available for read in this
|
||||
// system
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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.
|
||||
|
||||
#include "node_info.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
|
||||
node_info::node_info()
|
||||
{
|
||||
auto ifs = std::ifstream{ "/etc/machine-id" };
|
||||
if(!ifs.is_open())
|
||||
{
|
||||
ROCPROFSYS_WARNING(0, "Error: Unable to open /etc/machine-id!");
|
||||
return;
|
||||
}
|
||||
if(!(ifs >> machine_id) || machine_id.empty())
|
||||
{
|
||||
ROCPROFSYS_WARNING(0, "Error: Unable to read machine ID from /etc/machine-id!");
|
||||
}
|
||||
|
||||
hash = std::hash<std::string>{}(machine_id) % std::numeric_limits<int64_t>::max();
|
||||
id = hash % std::numeric_limits<size_t>::max();
|
||||
|
||||
struct utsname _sys_info;
|
||||
if(uname(&_sys_info))
|
||||
{
|
||||
ROCPROFSYS_WARNING(0, "Error: Unable to get system information!");
|
||||
return;
|
||||
}
|
||||
|
||||
system_name = _sys_info.sysname;
|
||||
node_name = _sys_info.nodename;
|
||||
release = _sys_info.release;
|
||||
version = _sys_info.version;
|
||||
machine = _sys_info.machine;
|
||||
domain_name = _sys_info.domainname;
|
||||
}
|
||||
|
||||
node_info&
|
||||
node_info::get_instance()
|
||||
{
|
||||
static node_info instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,58 @@
|
||||
// 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 <cstdint>
|
||||
#include <string>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
|
||||
struct node_info
|
||||
{
|
||||
private:
|
||||
node_info();
|
||||
|
||||
public:
|
||||
~node_info() = default;
|
||||
node_info(const node_info&) = default;
|
||||
node_info(node_info&&) noexcept = default;
|
||||
node_info& operator=(const node_info&) = default;
|
||||
node_info& operator=(node_info&&) noexcept = default;
|
||||
|
||||
static node_info& get_instance();
|
||||
|
||||
uint64_t id = 0;
|
||||
uint64_t hash = 0;
|
||||
std::string machine_id = {};
|
||||
std::string system_name = {};
|
||||
std::string node_name = {};
|
||||
std::string release = {};
|
||||
std::string version = {};
|
||||
std::string machine = {};
|
||||
std::string domain_name = {};
|
||||
};
|
||||
|
||||
const node_info&
|
||||
get_node_info();
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,13 @@
|
||||
set(rocpd_sources
|
||||
${CMAKE_CURRENT_LIST_DIR}/data_processor.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/json.cpp
|
||||
)
|
||||
|
||||
set(rocpd_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/data_processor.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/json.hpp
|
||||
)
|
||||
|
||||
target_sources(rocprofiler-systems-core-library PRIVATE ${rocpd_sources} ${rocpd_headers})
|
||||
|
||||
add_subdirectory(data_storage)
|
||||
@@ -0,0 +1,674 @@
|
||||
// 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.
|
||||
|
||||
#include "data_processor.hpp"
|
||||
#include "core/rocpd/data_storage/database.hpp"
|
||||
#include "core/rocpd/data_storage/table_insert_query.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace rocpd
|
||||
{
|
||||
data_processor::data_processor()
|
||||
{
|
||||
data_storage::database::get_instance().initialize_schema();
|
||||
_upid = data_storage::database::get_instance().get_upid();
|
||||
|
||||
// Initialize event statement
|
||||
initialize_event_stmt();
|
||||
initialize_pmc_event_stmt();
|
||||
initialize_sample_stmt();
|
||||
initialize_region_stmt();
|
||||
initialize_kernel_dispatch_stmt();
|
||||
initialize_memory_copy_stmt();
|
||||
initialize_code_object_stmt();
|
||||
initialize_kernel_symbol_stmt();
|
||||
initialize_metadata();
|
||||
initialize_args_stmt();
|
||||
initialize_memory_alloc_stmt();
|
||||
}
|
||||
|
||||
data_processor&
|
||||
data_processor::get_instance()
|
||||
{
|
||||
static data_processor _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_metadata()
|
||||
{
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_metadata_" + _upid)
|
||||
.set_columns("tag", "value")
|
||||
.set_values("upid", _upid)
|
||||
.get_query_string());
|
||||
}
|
||||
|
||||
size_t
|
||||
data_processor::insert_string(const char* str)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
auto it = _string_map.find(str);
|
||||
if(it != _string_map.end()) return _string_map.at(str);
|
||||
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_string_" + _upid)
|
||||
.set_columns("guid", "string")
|
||||
.set_values(_upid, str)
|
||||
.get_query_string());
|
||||
|
||||
const auto string_id = data_storage::database::get_instance().get_last_insert_id();
|
||||
_string_map.emplace(str, string_id);
|
||||
return string_id;
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_node_info(size_t node_id, size_t hash, const char* machine_id,
|
||||
const char* system_name, const char* hostname,
|
||||
const char* release, const char* version,
|
||||
const char* hardware_name, const char* domain_name)
|
||||
{
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_info_node_" + _upid)
|
||||
.set_columns("id", "guid", "hash", "machine_id", "system_name", "hostname",
|
||||
"release", "version", "hardware_name", "domain_name")
|
||||
.set_values(node_id, _upid, hash, machine_id, system_name, hostname, release,
|
||||
version, hardware_name, domain_name)
|
||||
.get_query_string());
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_process_info(size_t nid, size_t ppid, size_t pid, size_t init,
|
||||
size_t fini, size_t start, size_t end,
|
||||
const char* command, const char* environment,
|
||||
const char* extdata)
|
||||
{
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_info_process_" + _upid)
|
||||
.set_columns("id", "guid", "nid", "ppid", "pid", "init", "fini", "start",
|
||||
"end", "command", "environment", "extdata")
|
||||
.set_values(pid, _upid, nid, ppid, pid, init, fini, start, end, command,
|
||||
environment, extdata)
|
||||
.get_query_string());
|
||||
}
|
||||
|
||||
size_t
|
||||
data_processor::insert_agent(size_t node_id, size_t pid, const char* agent_type,
|
||||
size_t absolute_index, size_t logical_index,
|
||||
size_t type_index, uint64_t uuid, const char* name,
|
||||
const char* model_name, const char* vendor_name,
|
||||
const char* product_name, const char* user_name,
|
||||
const char* extdata)
|
||||
{
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_info_agent_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "type", "absolute_index", "logical_index",
|
||||
"type_index", "uuid", "name", "model_name", "vendor_name",
|
||||
"product_name", "user_name", "extdata")
|
||||
.set_values(_upid, node_id, pid, agent_type, absolute_index, logical_index,
|
||||
type_index, uuid, name, model_name, vendor_name, product_name,
|
||||
user_name, extdata)
|
||||
.get_query_string());
|
||||
|
||||
return data_storage::database::get_instance().get_last_insert_id();
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_track(const char* track_name, size_t node_id, size_t process_id,
|
||||
std::optional<size_t> thread_id, const char* extdata)
|
||||
{
|
||||
if(_tracks.find(track_name) != _tracks.end())
|
||||
{
|
||||
ROCPROFSYS_WARNING(2, "Fail to add track %s, already exist!\n", track_name);
|
||||
return;
|
||||
}
|
||||
|
||||
auto name_id = insert_string(track_name);
|
||||
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_track_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "tid", "name_id", "extdata")
|
||||
.set_values(_upid, node_id, process_id, thread_id, name_id, extdata)
|
||||
.get_query_string());
|
||||
|
||||
auto track_id = data_storage::database::get_instance().get_last_insert_id();
|
||||
_tracks[track_name] = track_name_map{ track_id, name_id };
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_pmc_description(
|
||||
size_t node_id, size_t process_id, size_t agent_id, const char* target_arch,
|
||||
size_t event_code, size_t instance_id, const char* name, const char* symbol,
|
||||
const char* description, const char* long_description, const char* component,
|
||||
const char* units, const char* value_type, const char* block, const char* expression,
|
||||
uint32_t is_constant, uint32_t is_derived, const char* extdata)
|
||||
{
|
||||
auto it = _pmc_descriptor_map.find({ agent_id, name });
|
||||
if(it != _pmc_descriptor_map.end())
|
||||
{
|
||||
ROCPROFSYS_WARNING(0,
|
||||
"Insert PMC description failed! Error: PMC descriptor "
|
||||
"(name:%s) (ID:%lu) already exist!\n",
|
||||
name, agent_id);
|
||||
return;
|
||||
}
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
|
||||
auto query =
|
||||
query_builder.set_table_name("rocpd_info_pmc_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "agent_id", "target_arch", "event_code",
|
||||
"instance_id", "name", "symbol", "description",
|
||||
"long_description", "component", "units", "value_type", "block",
|
||||
"expression", "is_constant", "is_derived", "extdata")
|
||||
.set_values(_upid, node_id, process_id, agent_id, target_arch, event_code,
|
||||
instance_id, name, symbol, description, long_description,
|
||||
component, units, value_type, block, expression, is_constant,
|
||||
is_derived, extdata)
|
||||
.get_query_string();
|
||||
data_storage::database::get_instance().execute_query(query);
|
||||
|
||||
auto pmc_id = data_storage::database::get_instance().get_last_insert_id();
|
||||
_pmc_descriptor_map.emplace(
|
||||
std::pair<pmc_identifier, size_t>{ { agent_id, name }, pmc_id });
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_pmc_event(size_t event_id, size_t agent_id, const char* pmc_name,
|
||||
double value, const char* extdata)
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(2,
|
||||
"Insert PMC event: id %ld, agent id: %ld, pmc name: %s, value: "
|
||||
"%lf, extdata: %s\n",
|
||||
event_id, agent_id, pmc_name, value, extdata);
|
||||
auto it = _pmc_descriptor_map.find({ agent_id, pmc_name });
|
||||
if(it == _pmc_descriptor_map.end())
|
||||
{
|
||||
ROCPROFSYS_WARNING(0,
|
||||
"Insert PMC event failed! Error: non-existing PMC description "
|
||||
"agent id: %ld, pmc name: %s !\n",
|
||||
agent_id, pmc_name);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto pmc_description_id = it->second;
|
||||
_insert_pmc_event_statement(_upid.c_str(), event_id, pmc_description_id, value,
|
||||
extdata);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_sample(const char* track, uint64_t timestamp, size_t event_id,
|
||||
const char* extdata)
|
||||
{
|
||||
ROCPROFSYS_VERBOSE(
|
||||
3, "Insert sample: track: %s, timestamp: %lu, event id: %ld, extdata: %s\n",
|
||||
track, timestamp, event_id, extdata);
|
||||
auto it = _tracks.find(track);
|
||||
if(it == _tracks.end())
|
||||
{
|
||||
ROCPROFSYS_WARNING(0, "Insert sample failed! Error: Unexisting track %s!\n",
|
||||
track);
|
||||
return;
|
||||
}
|
||||
auto track_info = it->second;
|
||||
_insert_sample_statement(_upid.c_str(), track_info.track_id, timestamp, event_id,
|
||||
extdata);
|
||||
}
|
||||
|
||||
size_t
|
||||
data_processor::insert_event(size_t category_id, size_t stack_id, size_t parent_stack_id,
|
||||
size_t correlation_id, const char* call_stack,
|
||||
const char* line_info, const char* extdata)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
auto it = _category_map.find(category_id);
|
||||
if(it == _category_map.end())
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Insert event failed! Error: Unknown category id: " << category_id
|
||||
<< " for UPID: " << _upid;
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
|
||||
ROCPROFSYS_VERBOSE(3, "Insert event category id: %ld, string id: %ld\n", category_id,
|
||||
it->second);
|
||||
|
||||
_insert_event_statement(_upid.c_str(), it->second, stack_id, parent_stack_id,
|
||||
correlation_id, call_stack, line_info, extdata);
|
||||
return data_storage::database::get_instance().get_last_insert_id();
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_event_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_event_" + _upid)
|
||||
.set_columns("guid", "category_id", "stack_id", "parent_stack_id",
|
||||
"correlation_id", "call_stack", "line_info", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_event_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, size_t, size_t, size_t,
|
||||
const char*, const char*, const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_pmc_event_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_pmc_event_" + _upid)
|
||||
.set_columns("guid", "event_id", "pmc_id", "value", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_pmc_event_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, size_t, double, const char*>(
|
||||
query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_sample_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_sample_" + _upid)
|
||||
.set_columns("guid", "track_id", "timestamp", "event_id", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_sample_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, uint64_t, size_t,
|
||||
const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_region_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_region_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "tid", "start", "end", "name_id",
|
||||
"event_id", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_region_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, size_t, size_t, uint64_t,
|
||||
uint64_t, size_t, size_t, const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_kernel_dispatch_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_kernel_dispatch_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "tid", "agent_id", "kernel_id",
|
||||
"dispatch_id", "queue_id", "stream_id", "start", "end",
|
||||
"private_segment_size", "group_segment_size",
|
||||
"workgroup_size_x", "workgroup_size_y",
|
||||
"workgroup_size_z", "grid_size_x", "grid_size_y",
|
||||
"grid_size_z", "region_name_id", "event_id", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
|
||||
'?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_kernel_dispatch_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, size_t, size_t, size_t,
|
||||
size_t, size_t, size_t, size_t, uint64_t, uint64_t,
|
||||
size_t, size_t, size_t, size_t, size_t, size_t,
|
||||
size_t, size_t, size_t, size_t, const char*>(
|
||||
query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_memory_copy_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_memory_copy_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "tid", "start", "end", "name_id",
|
||||
"dst_agent_id", "dst_address", "src_agent_id",
|
||||
"src_address", "size", "queue_id", "stream_id",
|
||||
"region_name_id", "event_id", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
|
||||
'?', '?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_memory_copy_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, size_t, size_t, uint64_t,
|
||||
uint64_t, size_t, size_t, size_t, size_t, size_t,
|
||||
size_t, size_t, size_t, size_t, size_t,
|
||||
const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_kernel_symbol_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query =
|
||||
query_builder.set_table_name("rocpd_info_kernel_symbol_" + _upid)
|
||||
.set_columns("id", "guid", "nid", "pid", "code_object_id", "kernel_name",
|
||||
"display_name", "kernel_object", "kernarg_segment_size",
|
||||
"kernarg_segment_alignment", "group_segment_size",
|
||||
"private_segment_size", "sgpr_count", "arch_vgpr_count",
|
||||
"accum_vgpr_count", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
|
||||
'?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_kernel_symbol_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<size_t, const char*, size_t, size_t, uint64_t,
|
||||
const char*, const char*, uint64_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_code_object_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query =
|
||||
query_builder.set_table_name("rocpd_info_code_object_" + _upid)
|
||||
.set_columns("id", "guid", "nid", "pid", "agent_id", "uri", "load_base",
|
||||
"load_size", "load_delta", "storage_type", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_code_object_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<size_t, const char*, size_t, size_t, size_t,
|
||||
const char*, uint64_t, uint64_t, uint64_t,
|
||||
const char*, const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_args_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_arg_" + _upid)
|
||||
.set_columns("guid", "event_id", "position", "type", "name", "value",
|
||||
"extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_args_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, size_t, const char*,
|
||||
const char*, const char*, const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::initialize_memory_alloc_stmt()
|
||||
{
|
||||
data_storage::queries::table_insert_query query_builder;
|
||||
auto query = query_builder.set_table_name("rocpd_memory_allocate_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "tid", "agent_id", "type",
|
||||
"level", "start", "end", "address", "size", "queue_id",
|
||||
"stream_id", "event_id", "extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
|
||||
'?', '?', '?', '?')
|
||||
.get_query_string();
|
||||
_insert_memory_alloc_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<
|
||||
const char*, size_t, size_t, size_t, size_t, const char*, const char*,
|
||||
uint64_t, uint64_t, size_t, size_t, size_t, size_t, size_t, const char*>(
|
||||
query);
|
||||
|
||||
// Statement without agent_id
|
||||
query = query_builder.set_table_name("rocpd_memory_allocate_" + _upid)
|
||||
.set_columns("guid", "nid", "pid", "tid", "type", "level", "start", "end",
|
||||
"address", "size", "queue_id", "stream_id", "event_id",
|
||||
"extdata")
|
||||
.set_values('?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?',
|
||||
'?', '?')
|
||||
.get_query_string();
|
||||
_insert_memory_alloc_no_agent_statement =
|
||||
data_storage::database::get_instance()
|
||||
.create_statement_executor<const char*, size_t, size_t, size_t, const char*,
|
||||
const char*, uint64_t, uint64_t, size_t, size_t,
|
||||
size_t, size_t, size_t, const char*>(query);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_args(size_t event_id, size_t position, const char* type,
|
||||
const char* name, const char* value, const char* extdata)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
_insert_args_statement(_upid.c_str(), event_id, position, type, name, value, extdata);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_stream_info(size_t stream_id, size_t node_id, size_t process_id,
|
||||
const char* name, const char* extdata)
|
||||
{
|
||||
if(_stream_ids.count(stream_id) > 0)
|
||||
{
|
||||
// ROCPROFSYS_WARNING(
|
||||
// 1, "Insert stream info failed! Error: Stream ID %ld already exists!\n",
|
||||
// stream_id);
|
||||
return;
|
||||
}
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_info_stream_" + _upid)
|
||||
.set_columns("id", "guid", "nid", "pid", "name", "extdata")
|
||||
.set_values(stream_id, _upid, node_id, process_id, name, extdata)
|
||||
.get_query_string());
|
||||
_stream_ids.insert(stream_id);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_queue_info(size_t queue_id, size_t node_id, size_t process_id,
|
||||
const char* name, const char* extdata)
|
||||
{
|
||||
if(_queue_ids.count(queue_id) > 0)
|
||||
{
|
||||
// ROCPROFSYS_WARNING(
|
||||
// 1, "Insert queue info failed! Error: Queue ID %ld already exists!\n",
|
||||
// queue_id);
|
||||
return;
|
||||
}
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_info_queue_" + _upid)
|
||||
.set_columns("id", "guid", "nid", "pid", "name", "extdata")
|
||||
.set_values(queue_id, _upid, node_id, process_id, name, extdata)
|
||||
.get_query_string());
|
||||
_queue_ids.insert(queue_id);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_code_object(size_t id, size_t node_id, size_t process_id,
|
||||
size_t agent_id, const char* uri, uint64_t ld_base,
|
||||
uint64_t ld_size, uint64_t ld_delta,
|
||||
const char* storage_type, const char* extdata)
|
||||
{
|
||||
if(_code_object_ids.count(id) > 0)
|
||||
{
|
||||
// ROCPROFSYS_WARNING(
|
||||
// 1,
|
||||
// "Insert code object info failed! Error: Code object ID %ld already
|
||||
// exists!\n", id);
|
||||
return;
|
||||
}
|
||||
ROCPROFSYS_VERBOSE(2, "Insert code object with ID: %ld\n", id);
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
_insert_code_object_statement(id, _upid.c_str(), node_id, process_id, agent_id, uri,
|
||||
ld_base, ld_size, ld_delta, storage_type, extdata);
|
||||
|
||||
_code_object_ids.insert(id);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_kernel_symbol(
|
||||
size_t id, size_t node_id, size_t process_id, uint64_t code_obj_id, const char* name,
|
||||
const char* display_name, uint32_t kernel_obj, uint32_t kernarg_segmnt_size,
|
||||
uint32_t kernarg_segment_alignment, uint32_t group_segment_size,
|
||||
uint32_t private_segment_size, uint32_t sgrp_count, uint32_t arch_vgrp_count,
|
||||
uint32_t accum_vgrp_count, const char* extdata)
|
||||
{
|
||||
if(_kernel_sym_ids.count(id) > 0)
|
||||
{
|
||||
// ROCPROFSYS_WARNING(
|
||||
// 1,
|
||||
// "Insert kernel symbol failed! Error: Kernel symbol ID %ld already
|
||||
// exists!\n", id);
|
||||
return;
|
||||
}
|
||||
|
||||
ROCPROFSYS_VERBOSE(2, "Insert kernel symbol: %s with ID: %ld\n", name, id);
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
_insert_kernel_symbol_statement(
|
||||
id, _upid.c_str(), node_id, process_id, code_obj_id, name, display_name,
|
||||
kernel_obj, kernarg_segmnt_size, kernarg_segment_alignment, group_segment_size,
|
||||
private_segment_size, sgrp_count, arch_vgrp_count, accum_vgrp_count, extdata);
|
||||
|
||||
_kernel_sym_ids.insert(id);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_category(size_t category_id, const char* name)
|
||||
{
|
||||
auto it = _category_map.find(category_id);
|
||||
if(it != _category_map.end())
|
||||
{
|
||||
// ROCPROFSYS_WARNING(
|
||||
// 1, "Insert category failed! Error: Category %s already exist!\n", name);
|
||||
return;
|
||||
}
|
||||
auto name_id = insert_string(name);
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
ROCPROFSYS_VERBOSE(2, "Insert category: name: %s, id: %ld, name id: %ld\n", name,
|
||||
category_id, name_id);
|
||||
_category_map.emplace(category_id, name_id);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_region(size_t node_id, size_t process_id, size_t thread_id,
|
||||
uint64_t start, uint64_t end, size_t name_id,
|
||||
size_t event_id, const char* extdata)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
ROCPROFSYS_VERBOSE(2, "Insert region for event id: %ld\n", event_id);
|
||||
|
||||
_insert_region_statement(_upid.c_str(), node_id, process_id, thread_id, start, end,
|
||||
name_id, event_id, extdata);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_kernel_dispatch(
|
||||
size_t node_id, size_t process_id, size_t thread_id, size_t agent_id,
|
||||
size_t kernel_id, size_t dispatch_id, size_t queue_id, size_t stream_id,
|
||||
uint64_t start, uint64_t end, size_t private_segment_size, size_t group_segment_size,
|
||||
size_t workgroup_size_x, size_t workgroup_size_y, size_t workgroup_size_z,
|
||||
size_t grid_size_x, size_t grid_size_y, size_t grid_size_z, size_t region_name_id,
|
||||
size_t event_id, const char* extdata)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
|
||||
ROCPROFSYS_VERBOSE(2, "Insert kernel dispatch for event id: %ld\n", event_id);
|
||||
|
||||
_insert_kernel_dispatch_statement(
|
||||
_upid.c_str(), node_id, process_id, thread_id, agent_id, kernel_id, dispatch_id,
|
||||
queue_id, stream_id, start, end, private_segment_size, group_segment_size,
|
||||
workgroup_size_x, workgroup_size_y, workgroup_size_z, grid_size_x, grid_size_y,
|
||||
grid_size_z, region_name_id, event_id, extdata);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_memory_copy(size_t node_id, size_t process_id, size_t thread_id,
|
||||
uint64_t start, uint64_t end, size_t name_id,
|
||||
size_t dst_agent_id, size_t dst_addr,
|
||||
size_t src_agent_id, size_t src_addr, size_t size,
|
||||
size_t queue_id, size_t stream_id,
|
||||
size_t region_name_id, size_t event_id,
|
||||
const char* extdata)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_data_mutex);
|
||||
|
||||
_insert_memory_copy_statement(_upid.c_str(), node_id, process_id, thread_id, start,
|
||||
end, name_id, dst_agent_id, dst_addr, src_agent_id,
|
||||
src_addr, size, queue_id, stream_id, region_name_id,
|
||||
event_id, extdata);
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::insert_memory_alloc(size_t node_id, size_t process_id, size_t thread_id,
|
||||
std::optional<size_t> agent_id, const char* type,
|
||||
const char* level, uint64_t start, uint64_t end,
|
||||
size_t address, size_t size, size_t queue_id,
|
||||
size_t stream_id, size_t event_id,
|
||||
const char* extdata)
|
||||
{
|
||||
if(agent_id.has_value())
|
||||
{
|
||||
_insert_memory_alloc_statement(_upid.c_str(), node_id, process_id, thread_id,
|
||||
agent_id.value(), type, level, start, end, address,
|
||||
size, queue_id, stream_id, event_id, extdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
_insert_memory_alloc_no_agent_statement(
|
||||
_upid.c_str(), node_id, process_id, thread_id, type, level, start, end,
|
||||
address, size, queue_id, stream_id, event_id, extdata);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
data_processor::insert_thread_info(size_t node_id, size_t parent_process_id,
|
||||
size_t process_id, size_t thread_id, const char* name,
|
||||
uint64_t start, uint64_t end, const char* extdata)
|
||||
{
|
||||
auto it = _thread_id_map.find(thread_id);
|
||||
|
||||
if(it != _thread_id_map.end())
|
||||
{
|
||||
return _thread_id_map.at(thread_id);
|
||||
}
|
||||
|
||||
data_storage::queries::table_insert_query query;
|
||||
data_storage::database::get_instance().execute_query(
|
||||
query.set_table_name("rocpd_info_thread_" + _upid)
|
||||
.set_columns("guid", "nid", "ppid", "pid", "tid", "name", "start", "end",
|
||||
"extdata")
|
||||
.set_values(_upid.c_str(), node_id, parent_process_id, process_id, thread_id,
|
||||
name, start, end, extdata)
|
||||
.get_query_string());
|
||||
|
||||
auto thread_idx = data_storage::database::get_instance().get_last_insert_id();
|
||||
_thread_id_map.emplace(thread_id, thread_idx);
|
||||
return thread_idx;
|
||||
}
|
||||
|
||||
void
|
||||
data_processor::flush()
|
||||
{
|
||||
// Flush all pending data to the database
|
||||
data_storage::database::get_instance().flush();
|
||||
}
|
||||
|
||||
} // namespace rocpd
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,252 @@
|
||||
// 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 <cstdint>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace rocpd
|
||||
{
|
||||
struct data_processor
|
||||
{
|
||||
using insert_event_stmt =
|
||||
std::function<void(const char*, size_t, size_t, size_t, size_t, const char*,
|
||||
const char*, const char*)>;
|
||||
using insert_pmc_event_stms =
|
||||
std::function<void(const char*, size_t, size_t, double, const char*)>;
|
||||
using insert_sample_stmt =
|
||||
std::function<void(const char*, size_t, uint64_t, size_t, const char*)>;
|
||||
using insert_region_stmt =
|
||||
std::function<void(const char*, size_t, size_t, size_t, uint64_t, uint64_t,
|
||||
size_t, size_t, const char*)>;
|
||||
using insert_kernel_dispatch_stmt = std::function<void(
|
||||
const char*, size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
|
||||
uint64_t, uint64_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t,
|
||||
size_t, size_t, size_t, const char*)>;
|
||||
using insert_memory_copy_stmt = std::function<void(
|
||||
const char*, size_t, size_t, size_t, uint64_t, uint64_t, size_t, size_t, size_t,
|
||||
size_t, size_t, size_t, size_t, size_t, size_t, size_t, const char*)>;
|
||||
using insert_memory_alloc_stmt = std::function<void(
|
||||
const char*, size_t, size_t, size_t, size_t, const char*, const char*, uint64_t,
|
||||
uint64_t, size_t, size_t, size_t, size_t, size_t, const char*)>;
|
||||
using insert_memory_alloc_no_agent_stmt = std::function<void(
|
||||
const char*, size_t, size_t, size_t, const char*, const char*, uint64_t, uint64_t,
|
||||
size_t, size_t, size_t, size_t, size_t, const char*)>;
|
||||
using insert_kernel_symbol_stmt =
|
||||
std::function<void(size_t, const char*, size_t, size_t, uint64_t, const char*,
|
||||
const char*, uint64_t, uint32_t, uint32_t, uint32_t, uint32_t,
|
||||
uint32_t, uint32_t, uint32_t, const char*)>;
|
||||
using insert_code_object_stmt =
|
||||
std::function<void(size_t, const char*, size_t, size_t, size_t, const char*,
|
||||
uint64_t, uint64_t, uint64_t, const char*, const char*)>;
|
||||
using insert_args_stmt = std::function<void(const char*, size_t, size_t, const char*,
|
||||
const char*, const char*, const char*)>;
|
||||
|
||||
private:
|
||||
struct track_name_map
|
||||
{
|
||||
size_t track_id;
|
||||
size_t name_id;
|
||||
};
|
||||
|
||||
struct pmc_identifier
|
||||
{
|
||||
size_t agent_id;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct pmc_identifier_hash
|
||||
{
|
||||
std::size_t operator()(const pmc_identifier& pmc) const noexcept
|
||||
{
|
||||
std::size_t h1 = std::hash<size_t>{}(pmc.agent_id);
|
||||
std::size_t h2 = std::hash<std::string>{}(pmc.name);
|
||||
return h1 ^ (h2 << 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct pmc_identifier_equal
|
||||
{
|
||||
bool operator()(const pmc_identifier& lhs,
|
||||
const pmc_identifier& rhs) const noexcept
|
||||
{
|
||||
return lhs.agent_id == rhs.agent_id && lhs.name == rhs.name;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
static data_processor& get_instance();
|
||||
|
||||
size_t insert_string(const char* str);
|
||||
|
||||
void insert_node_info(size_t node_id, size_t hash, const char* machine_id,
|
||||
const char* system_name, const char* hostname,
|
||||
const char* release, const char* version,
|
||||
const char* hardware_name, const char* domain_name);
|
||||
|
||||
void insert_process_info(size_t node_id, size_t ppid, size_t pid, size_t init,
|
||||
size_t fini, size_t start, size_t end, const char* command,
|
||||
const char* environment = "{}", const char* extdata = "{}");
|
||||
|
||||
size_t insert_agent(size_t node_id, size_t pid, const char* agent_type,
|
||||
size_t absolute_index, size_t logical_index, size_t type_index,
|
||||
uint64_t uuid, const char* name, const char* model_name,
|
||||
const char* vendor_name, const char* product_name,
|
||||
const char* user_name, const char* extdata = "{}");
|
||||
|
||||
void insert_track(const char* track_name, size_t node_id, size_t process_id,
|
||||
std::optional<size_t> thread_id, const char* extdata = "{}");
|
||||
|
||||
size_t insert_event(size_t category_id, size_t stack_id, size_t parent_stack_id,
|
||||
size_t correlation_id, const char* call_stack = "{}",
|
||||
const char* line_info = "{}", const char* extdata = "{}");
|
||||
|
||||
void insert_pmc_event(size_t event_id, size_t agent_id, const char* pmc_descriptor,
|
||||
double value, const char* extdata = "{}");
|
||||
|
||||
void insert_pmc_description(size_t node_id, size_t process_id, size_t agent_id,
|
||||
const char* target_arch, size_t event_code,
|
||||
size_t instance_id, const char* name, const char* symbol,
|
||||
const char* description, const char* long_description,
|
||||
const char* component, const char* units,
|
||||
const char* value_type, const char* block,
|
||||
const char* expression, uint32_t is_constant,
|
||||
uint32_t is_derived, const char* extdata = "{}");
|
||||
|
||||
void insert_sample(const char* track, uint64_t timestamp, size_t event_id,
|
||||
const char* extdata = "{}");
|
||||
|
||||
void insert_category(size_t category_id, const char* name);
|
||||
|
||||
void insert_region(size_t node_id, size_t process_id, size_t thread_id,
|
||||
uint64_t start, uint64_t end, size_t name_id, size_t event_id,
|
||||
const char* extdata = "{}");
|
||||
|
||||
size_t insert_thread_info(size_t node_id, size_t parent_process_id, size_t process_id,
|
||||
size_t thread_id, const char* name, uint64_t start = 0,
|
||||
uint64_t end = 0, const char* extdata = "{}");
|
||||
|
||||
void insert_stream_info(size_t stream_id, size_t node_id, size_t process_id,
|
||||
const char* name, const char* extdata = "{}");
|
||||
void insert_queue_info(size_t queue_id, size_t node_id, size_t process_id,
|
||||
const char* name, const char* extdata = "{}");
|
||||
|
||||
void insert_kernel_dispatch(size_t node_id, size_t process_id, size_t thread_id,
|
||||
size_t agent_id, size_t kernel_id, size_t dispatch_id,
|
||||
size_t queue_id, size_t stream_id, uint64_t start,
|
||||
uint64_t end, size_t private_segment_size,
|
||||
size_t group_segment_size, size_t workgroup_size_x,
|
||||
size_t workgroup_size_y, size_t workgroup_size_z,
|
||||
size_t grid_size_x, size_t grid_size_y,
|
||||
size_t grid_size_z, size_t region_name_id,
|
||||
size_t event_id, const char* extdata = "{}");
|
||||
|
||||
void insert_memory_copy(size_t node_id, size_t process_id, size_t thread_id,
|
||||
uint64_t start, uint64_t end, size_t name_id,
|
||||
size_t dst_agent_id, size_t dst_addr, size_t src_agent_id,
|
||||
size_t src_addr, size_t size, size_t queue_id,
|
||||
size_t stream_id, size_t region_name_id, size_t event_id,
|
||||
const char* extdata = "{}");
|
||||
|
||||
void insert_kernel_symbol(size_t id, size_t node_id, size_t process_id,
|
||||
uint64_t code_obj_id, const char* name,
|
||||
const char* display_name, uint32_t kernel_obj,
|
||||
uint32_t kernarg_segmnt_size,
|
||||
uint32_t kernarg_segment_alignment,
|
||||
uint32_t group_segment_size, uint32_t private_segment_size,
|
||||
uint32_t sgrp_count, uint32_t arch_vgrp_count,
|
||||
uint32_t accum_vgrp_count, const char* extdata = "{}");
|
||||
|
||||
void insert_code_object(size_t id, size_t node_id, size_t process_id, size_t agent_id,
|
||||
const char* uri, uint64_t ld_base, uint64_t ld_size,
|
||||
uint64_t ld_delta, const char* storage_type,
|
||||
const char* extdata = "{}");
|
||||
|
||||
void insert_args(size_t event_id, size_t position, const char* type, const char* name,
|
||||
const char* value, const char* extdata = "{}");
|
||||
|
||||
void insert_memory_alloc(size_t node_id, size_t process_id, size_t thread_id,
|
||||
std::optional<size_t> agent_id, const char* type,
|
||||
const char* level, uint64_t start, uint64_t end,
|
||||
size_t address, size_t size, size_t queue_id,
|
||||
size_t stream_id, size_t event_id,
|
||||
const char* extdata = "{}");
|
||||
|
||||
void flush();
|
||||
|
||||
private:
|
||||
data_processor();
|
||||
data_processor(data_processor&) = delete;
|
||||
data_processor& operator=(const data_processor&) = delete;
|
||||
|
||||
void initialize_pmc_event_stmt();
|
||||
void initialize_event_stmt();
|
||||
void initialize_sample_stmt();
|
||||
void initialize_region_stmt();
|
||||
void initialize_kernel_dispatch_stmt();
|
||||
void initialize_memory_copy_stmt();
|
||||
void initialize_kernel_symbol_stmt();
|
||||
void initialize_code_object_stmt();
|
||||
void initialize_metadata();
|
||||
void initialize_args_stmt();
|
||||
void initialize_memory_alloc_stmt();
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, track_name_map> _tracks;
|
||||
std::unordered_map<pmc_identifier, size_t, pmc_identifier_hash, pmc_identifier_equal>
|
||||
_pmc_descriptor_map;
|
||||
std::unordered_map<size_t, size_t> _thread_id_map;
|
||||
std::unordered_map<size_t, size_t> _category_map;
|
||||
std::unordered_map<std::string, size_t> _string_map;
|
||||
|
||||
std::set<uint64_t> _code_object_ids;
|
||||
std::set<uint64_t> _kernel_sym_ids;
|
||||
std::set<uint64_t> _stream_ids;
|
||||
std::set<uint64_t> _queue_ids;
|
||||
|
||||
insert_event_stmt _insert_event_statement;
|
||||
insert_pmc_event_stms _insert_pmc_event_statement;
|
||||
insert_sample_stmt _insert_sample_statement;
|
||||
insert_region_stmt _insert_region_statement;
|
||||
insert_kernel_dispatch_stmt _insert_kernel_dispatch_statement;
|
||||
insert_memory_copy_stmt _insert_memory_copy_statement;
|
||||
insert_kernel_symbol_stmt _insert_kernel_symbol_statement;
|
||||
insert_code_object_stmt _insert_code_object_statement;
|
||||
insert_args_stmt _insert_args_statement;
|
||||
insert_memory_alloc_stmt _insert_memory_alloc_statement;
|
||||
insert_memory_alloc_no_agent_stmt _insert_memory_alloc_no_agent_statement;
|
||||
|
||||
std::string _upid{};
|
||||
|
||||
std::mutex _data_mutex;
|
||||
};
|
||||
|
||||
} // namespace rocpd
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,14 @@
|
||||
set(data_storage_sources ${CMAKE_CURRENT_LIST_DIR}/database.cpp)
|
||||
|
||||
set(data_storage_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/database.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/insert_query_builders.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/table_insert_query.hpp
|
||||
)
|
||||
|
||||
target_sources(rocprofiler-systems-core-library PRIVATE ${data_storage_sources})
|
||||
|
||||
target_link_libraries(
|
||||
rocprofiler-systems-core-library
|
||||
PRIVATE $<BUILD_INTERFACE:rocprofiler-systems::rocprofiler-systems-sqlite3>
|
||||
)
|
||||
@@ -0,0 +1,170 @@
|
||||
// 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.
|
||||
|
||||
#include "database.hpp"
|
||||
#include "common/md5sum.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "node_info.hpp"
|
||||
|
||||
#include <config.hpp>
|
||||
#include <fstream>
|
||||
#include <regex>
|
||||
#include <timemory/environment/types.hpp>
|
||||
#include <timemory/utility/filepath.hpp>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
void
|
||||
create_directory_for_database_file(const std::string& db_file)
|
||||
{
|
||||
auto _db_dirname = tim::filepath::dirname(db_file);
|
||||
if(!tim::filepath::direxists(_db_dirname))
|
||||
{
|
||||
tim::filepath::makedir(_db_dirname);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace rocpd
|
||||
{
|
||||
namespace data_storage
|
||||
{
|
||||
database&
|
||||
database::get_instance()
|
||||
{
|
||||
static database _instance;
|
||||
return _instance;
|
||||
}
|
||||
|
||||
database::database()
|
||||
{
|
||||
auto db_name = std::string_view{ "rocpd.db" };
|
||||
auto abs_db_path = rocprofsys::get_database_absolute_path(db_name);
|
||||
create_directory_for_database_file(abs_db_path);
|
||||
ROCPROFSYS_VERBOSE(0, "Database: %s\r\n", abs_db_path.c_str());
|
||||
|
||||
validate_sqlite3_result(sqlite3_open(":memory:", &_sqlite3_db_temp), "",
|
||||
"database open failed!");
|
||||
validate_sqlite3_result(sqlite3_open(abs_db_path.c_str(), &_sqlite3_db), "",
|
||||
"database open failed!");
|
||||
}
|
||||
|
||||
database::~database()
|
||||
{
|
||||
sqlite3_close(_sqlite3_db_temp);
|
||||
sqlite3_close(_sqlite3_db);
|
||||
}
|
||||
|
||||
void
|
||||
database::initialize_schema()
|
||||
{
|
||||
auto get_file_path = [](const std::string_view filename) {
|
||||
auto _rocprofsys_root = tim::get_env<std::string>(
|
||||
"rocprofiler_systems_ROOT", tim::get_env<std::string>("ROCPROFSYS_ROOT", ""));
|
||||
if(!_rocprofsys_root.empty() &&
|
||||
tim::filepath::direxists(std::string(_rocprofsys_root)))
|
||||
{
|
||||
auto new_file_path = std::string(_rocprofsys_root)
|
||||
.append("/share/rocprofiler-systems/")
|
||||
.append(filename);
|
||||
if(tim::filepath::exists(new_file_path))
|
||||
{
|
||||
return new_file_path;
|
||||
}
|
||||
}
|
||||
return std::string(
|
||||
"rocprofiler-systems/source/lib/core/rocpd/data_storage/schema/")
|
||||
.append(filename);
|
||||
};
|
||||
|
||||
std::vector<std::string_view> schema_files = { "rocpd_tables.sql", "rocpd_views.sql",
|
||||
"data_views.sql", "marker_views.sql",
|
||||
"summary_views.sql" };
|
||||
|
||||
// Process each schema file
|
||||
for(const auto& schema_file : schema_files)
|
||||
{
|
||||
auto file_path = get_file_path(schema_file);
|
||||
std::ifstream file(file_path);
|
||||
if(!file.is_open())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("Failed to open schema file ").append(file_path));
|
||||
}
|
||||
|
||||
std::stringstream ss_query;
|
||||
ss_query << file.rdbuf();
|
||||
std::string query = ss_query.str();
|
||||
|
||||
std::regex upid_pattern("\\{\\{uuid\\}\\}");
|
||||
std::regex view_upid_pattern("\\{\\{view_upid\\}\\}");
|
||||
|
||||
query = std::regex_replace(query, upid_pattern, "_" + get_upid());
|
||||
query = std::regex_replace(query, view_upid_pattern, "");
|
||||
|
||||
validate_sqlite3_result(
|
||||
sqlite3_exec(_sqlite3_db_temp, query.c_str(), 0, 0, 0), query.c_str(),
|
||||
std::string("Invalid schema file, init database failed!").append(file_path));
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
database::execute_query(const std::string& query)
|
||||
{
|
||||
validate_sqlite3_result(sqlite3_exec(_sqlite3_db_temp, query.c_str(), 0, 0, 0),
|
||||
"Failed to execute query - ", query);
|
||||
}
|
||||
|
||||
std::string
|
||||
database::get_upid()
|
||||
{
|
||||
static std::string _upid = []() {
|
||||
auto n_info = node_info::get_instance();
|
||||
auto guid = common::md5sum{ n_info.id, getpid(), getppid() };
|
||||
return guid.hexdigest();
|
||||
}();
|
||||
return _upid;
|
||||
}
|
||||
|
||||
size_t
|
||||
database::get_last_insert_id() const
|
||||
{
|
||||
return sqlite3_last_insert_rowid(_sqlite3_db_temp);
|
||||
}
|
||||
|
||||
void
|
||||
database::flush()
|
||||
{
|
||||
auto* backup = sqlite3_backup_init(_sqlite3_db, "main", _sqlite3_db_temp, "main");
|
||||
if(backup)
|
||||
{
|
||||
sqlite3_backup_step(backup, -1); // Copy all pages
|
||||
sqlite3_backup_finish(backup);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace data_storage
|
||||
} // namespace rocpd
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,204 @@
|
||||
// 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 "common/traits.hpp"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sqlite3.h>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace rocpd
|
||||
{
|
||||
namespace data_storage
|
||||
{
|
||||
static std::mutex _mutex;
|
||||
class database
|
||||
{
|
||||
public:
|
||||
static database& get_instance();
|
||||
|
||||
database(database&) = delete;
|
||||
database& operator=(database&) = delete;
|
||||
|
||||
void flush();
|
||||
|
||||
~database();
|
||||
|
||||
private:
|
||||
database();
|
||||
|
||||
template <typename... Args>
|
||||
inline void validate_sqlite3_result(int sqlite3_error_code, const char* query,
|
||||
Args&&... args)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "\n===========================================================\n";
|
||||
ss << "Database Error\n";
|
||||
((ss << args << " "), ...);
|
||||
ss << "\nQuery: " << query << "\n";
|
||||
switch(sqlite3_error_code)
|
||||
{
|
||||
case SQLITE_OK:
|
||||
case SQLITE_DONE: return;
|
||||
case SQLITE_CONSTRAINT:
|
||||
{
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
ss << "Constraint violation(s): " << "\n";
|
||||
|
||||
sqlite3_exec(_sqlite3_db_temp, "PRAGMA foreign_keys = OFF;", nullptr,
|
||||
nullptr, nullptr);
|
||||
sqlite3_exec(_sqlite3_db_temp, query, nullptr, nullptr, nullptr);
|
||||
sqlite3_exec(_sqlite3_db_temp, "PRAGMA foreign_keys = ON;", nullptr,
|
||||
nullptr, nullptr);
|
||||
sqlite3_prepare_v2(_sqlite3_db_temp, "PRAGMA foreign_key_check", -1,
|
||||
&stmt, nullptr);
|
||||
int rc = 0;
|
||||
while((rc = sqlite3_step(stmt)) == SQLITE_ROW)
|
||||
{
|
||||
const char* table = (const char*) sqlite3_column_text(stmt, 0);
|
||||
int rowid = sqlite3_column_int(stmt, 1);
|
||||
const char* parent = (const char*) sqlite3_column_text(stmt, 2);
|
||||
int fkid = sqlite3_column_int(stmt, 3);
|
||||
|
||||
ss << " - " << "FK Violation - Table: " << (table ? table : "NULL")
|
||||
<< ", RowID: " << rowid
|
||||
<< ", Parent: " << (parent ? parent : "NULL") << ", FKID: " << fkid
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
}
|
||||
break;
|
||||
}
|
||||
ss << " [Sqlite3 error: " << sqlite3_errstr(sqlite3_error_code);
|
||||
ss << " (Extended error message: " << sqlite3_errmsg(_sqlite3_db_temp) << ")]";
|
||||
throw std::runtime_error(ss.str());
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<!(common::traits::is_string_literal<T>() ||
|
||||
std::is_floating_point_v<std::decay_t<T>> ||
|
||||
std::is_same_v<std::decay_t<T>, int64_t> ||
|
||||
std::is_same_v<std::decay_t<T>, uint64_t> ||
|
||||
std::is_same_v<std::decay_t<T>, int32_t> ||
|
||||
std::is_same_v<std::decay_t<T>, uint32_t>),
|
||||
int> = 0>
|
||||
inline void bind_value([[maybe_unused]] sqlite3_stmt* stmt,
|
||||
[[maybe_unused]] int position, [[maybe_unused]] T& _value,
|
||||
[[maybe_unused]] const std::string& query)
|
||||
{
|
||||
throw std::runtime_error("Unsupported type for binding!");
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
std::enable_if_t<common::traits::is_string_literal<T>(), int> = 0>
|
||||
inline void bind_value(sqlite3_stmt* stmt, int position, T&& _value,
|
||||
const std::string& query)
|
||||
{
|
||||
validate_sqlite3_result(
|
||||
sqlite3_bind_text(stmt, position, _value, -1, SQLITE_STATIC), query.c_str(),
|
||||
"Failed to bind text! Position: ", position, ", Value: ", _value);
|
||||
}
|
||||
|
||||
template <typename T,
|
||||
std::enable_if_t<std::is_floating_point_v<std::decay_t<T>>, int> = 0>
|
||||
inline void bind_value(sqlite3_stmt* stmt, int position, T&& _value,
|
||||
const std::string& query)
|
||||
{
|
||||
validate_sqlite3_result(
|
||||
sqlite3_bind_double(stmt, position, _value), query.c_str(),
|
||||
"Failed to bind double! Position: ", position, ", Value: ", _value);
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_same_v<std::decay_t<T>, int64_t> ||
|
||||
std::is_same_v<std::decay_t<T>, uint64_t>,
|
||||
int> = 0>
|
||||
inline void bind_value(sqlite3_stmt* stmt, int position, T&& _value,
|
||||
const std::string& query)
|
||||
{
|
||||
validate_sqlite3_result(sqlite3_bind_int64(stmt, position, _value), query.c_str(),
|
||||
"Failed to bind int64_t/uint64_t! Position: ", position,
|
||||
", Value: ", _value);
|
||||
}
|
||||
|
||||
template <typename T, std::enable_if_t<std::is_same_v<std::decay_t<T>, int32_t> ||
|
||||
std::is_same_v<std::decay_t<T>, uint32_t>,
|
||||
int> = 0>
|
||||
inline void bind_value(sqlite3_stmt* stmt, int position, T&& _value,
|
||||
const std::string& query)
|
||||
{
|
||||
validate_sqlite3_result(sqlite3_bind_int(stmt, position, _value), query.c_str(),
|
||||
"Failed to bind int32_t/uint32_t! Position: ", position,
|
||||
", Value: ", _value);
|
||||
}
|
||||
|
||||
public:
|
||||
void initialize_schema();
|
||||
|
||||
void execute_query(const std::string& query);
|
||||
|
||||
size_t get_last_insert_id() const;
|
||||
|
||||
/**
|
||||
* This function prepares an SQLite statement based on the provided SQL query and
|
||||
* returns a lambda that can execute the prepared statement, binding the provided
|
||||
* values to the respective placeholders in the query.
|
||||
*/
|
||||
template <typename... Values>
|
||||
auto create_statement_executor(const std::string& query)
|
||||
{
|
||||
sqlite3_stmt* p_stmt;
|
||||
validate_sqlite3_result(
|
||||
sqlite3_prepare_v2(_sqlite3_db_temp, query.c_str(), -1, &p_stmt, nullptr),
|
||||
query.c_str(), "Failed to create statement!");
|
||||
std::shared_ptr<sqlite3_stmt> stmt{ p_stmt, sqlite3_finalize };
|
||||
|
||||
return [stmt, query, this](Values... value) {
|
||||
std::lock_guard lock{ _mutex };
|
||||
int position = 1;
|
||||
|
||||
((bind_value(stmt.get(), position++, value, query)), ...);
|
||||
|
||||
validate_sqlite3_result(sqlite3_step(stmt.get()), query.c_str(),
|
||||
"Failed to execute step!\n", "Values: ", value...);
|
||||
sqlite3_reset(stmt.get());
|
||||
};
|
||||
}
|
||||
|
||||
static std::string get_upid();
|
||||
|
||||
private:
|
||||
sqlite3* _sqlite3_db{ nullptr };
|
||||
sqlite3* _sqlite3_db_temp{ nullptr };
|
||||
};
|
||||
|
||||
} // namespace data_storage
|
||||
} // namespace rocpd
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,126 @@
|
||||
// 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 "common/traits.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace rocpd
|
||||
{
|
||||
namespace data_storage
|
||||
{
|
||||
namespace queries
|
||||
{
|
||||
|
||||
namespace query_builders
|
||||
{
|
||||
|
||||
struct query_value_builder
|
||||
{
|
||||
query_value_builder(std::stringstream& ss)
|
||||
: _ss{ ss }
|
||||
{}
|
||||
|
||||
template <typename... Values>
|
||||
query_value_builder& set_values(Values&&... values)
|
||||
{
|
||||
auto i = sizeof...(values);
|
||||
_ss << "( ";
|
||||
((process_value(values) << (i-- > 1 ? ", " : " ")), ...);
|
||||
_ss << ")";
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string get_query_string() { return _ss.str(); }
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
std::enable_if_t<common::traits::is_string_literal<T>(), std::stringstream&>
|
||||
process_value(T& value)
|
||||
{
|
||||
_ss << "\"" << value << "\"";
|
||||
return _ss;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<common::traits::is_optional_v<std::decay_t<T>>, std::stringstream&>
|
||||
process_value(T& value)
|
||||
{
|
||||
if(value.has_value())
|
||||
{
|
||||
_ss << value.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
_ss << "NULL";
|
||||
}
|
||||
return _ss;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<!common::traits::is_string_literal<T>() &&
|
||||
!common::traits::is_optional_v<std::decay_t<T>>,
|
||||
std::stringstream&>
|
||||
process_value(T& value)
|
||||
{
|
||||
_ss << value;
|
||||
return _ss;
|
||||
}
|
||||
|
||||
private:
|
||||
std::stringstream& _ss;
|
||||
};
|
||||
|
||||
struct query_columns_builder
|
||||
{
|
||||
query_columns_builder(std::stringstream& ss)
|
||||
: _ss{ ss }
|
||||
, _query_value_builder{ _ss }
|
||||
{}
|
||||
|
||||
template <typename... Columns,
|
||||
typename =
|
||||
std::enable_if_t<(common::traits::is_string_literal<Columns>() && ...)>>
|
||||
query_value_builder& set_columns(Columns&... columns)
|
||||
{
|
||||
auto i = sizeof...(columns);
|
||||
_ss << "( ";
|
||||
((_ss << columns << (i-- > 1 ? ", " : " ")), ...) << ") VALUES ";
|
||||
return _query_value_builder;
|
||||
}
|
||||
|
||||
private:
|
||||
std::stringstream& _ss;
|
||||
query_value_builder _query_value_builder;
|
||||
};
|
||||
|
||||
} // namespace query_builders
|
||||
} // namespace queries
|
||||
} // namespace data_storage
|
||||
} // namespace rocpd
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,722 @@
|
||||
--
|
||||
-- Useful views
|
||||
--
|
||||
-- Code objects
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`code_objects` AS
|
||||
SELECT
|
||||
CO.id,
|
||||
CO.guid,
|
||||
CO.nid,
|
||||
P.pid,
|
||||
A.absolute_index AS agent_abs_index,
|
||||
CO.uri,
|
||||
CO.load_base,
|
||||
CO.load_size,
|
||||
CO.load_delta,
|
||||
CO.storage_type AS storage_type_str,
|
||||
JSON_EXTRACT(CO.extdata, '$.size') AS code_object_size,
|
||||
JSON_EXTRACT(CO.extdata, '$.storage_type') AS storage_type,
|
||||
JSON_EXTRACT(CO.extdata, '$.memory_base') AS memory_base,
|
||||
JSON_EXTRACT(CO.extdata, '$.memory_size') AS memory_size
|
||||
FROM
|
||||
`rocpd_info_code_object` CO
|
||||
INNER JOIN `rocpd_info_agent` A ON CO.agent_id = A.id
|
||||
AND CO.guid = A.guid
|
||||
INNER JOIN `rocpd_info_process` P ON CO.pid = P.id
|
||||
AND CO.guid = P.guid;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`kernel_symbols` AS
|
||||
SELECT
|
||||
KS.id,
|
||||
KS.guid,
|
||||
KS.nid,
|
||||
P.pid,
|
||||
KS.code_object_id,
|
||||
KS.kernel_name,
|
||||
KS.display_name,
|
||||
KS.kernel_object,
|
||||
KS.kernarg_segment_size,
|
||||
KS.kernarg_segment_alignment,
|
||||
KS.group_segment_size,
|
||||
KS.private_segment_size,
|
||||
KS.sgpr_count,
|
||||
KS.arch_vgpr_count,
|
||||
KS.accum_vgpr_count,
|
||||
JSON_EXTRACT(KS.extdata, '$.size') AS kernel_symbol_size,
|
||||
JSON_EXTRACT(KS.extdata, '$.kernel_id') AS kernel_id,
|
||||
JSON_EXTRACT(KS.extdata, '$.kernel_code_entry_byte_offset') AS kernel_code_entry_byte_offset,
|
||||
JSON_EXTRACT(KS.extdata, '$.formatted_kernel_name') AS formatted_kernel_name,
|
||||
JSON_EXTRACT(KS.extdata, '$.demangled_kernel_name') AS demangled_kernel_name,
|
||||
JSON_EXTRACT(KS.extdata, '$.truncated_kernel_name') AS truncated_kernel_name,
|
||||
JSON_EXTRACT(KS.extdata, '$.kernel_address.handle') AS kernel_address
|
||||
FROM
|
||||
`rocpd_info_kernel_symbol` KS
|
||||
INNER JOIN `rocpd_info_process` P ON KS.pid = P.id
|
||||
AND KS.guid = P.guid;
|
||||
|
||||
-- Processes
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`processes` AS
|
||||
SELECT
|
||||
N.id AS nid,
|
||||
N.machine_id,
|
||||
N.system_name,
|
||||
N.hostname,
|
||||
N.release AS system_release,
|
||||
N.version AS system_version,
|
||||
P.guid,
|
||||
P.ppid,
|
||||
P.pid,
|
||||
P.init,
|
||||
P.start,
|
||||
P.end,
|
||||
P.fini,
|
||||
P.command
|
||||
FROM
|
||||
`rocpd_info_process` P
|
||||
INNER JOIN `rocpd_info_node` N ON N.id = P.nid
|
||||
AND N.guid = P.guid;
|
||||
|
||||
-- Threads
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`threads` AS
|
||||
SELECT
|
||||
N.id AS nid,
|
||||
N.machine_id,
|
||||
N.system_name,
|
||||
N.hostname,
|
||||
N.release AS system_release,
|
||||
N.version AS system_version,
|
||||
P.guid,
|
||||
P.ppid,
|
||||
P.pid,
|
||||
T.tid,
|
||||
T.start,
|
||||
T.end,
|
||||
T.name
|
||||
FROM
|
||||
`rocpd_info_thread` T
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = T.pid
|
||||
AND N.guid = T.guid
|
||||
INNER JOIN `rocpd_info_node` N ON N.id = T.nid
|
||||
AND N.guid = T.guid;
|
||||
|
||||
-- CPU regions
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`regions` AS
|
||||
SELECT
|
||||
R.id,
|
||||
R.guid,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
S.string AS name,
|
||||
R.nid,
|
||||
P.pid,
|
||||
T.tid,
|
||||
R.start,
|
||||
R.end,
|
||||
(R.end - R.start) AS duration,
|
||||
R.event_id,
|
||||
E.stack_id,
|
||||
E.parent_stack_id,
|
||||
E.correlation_id AS corr_id,
|
||||
E.extdata,
|
||||
E.call_stack,
|
||||
E.line_info
|
||||
FROM
|
||||
`rocpd_region` R
|
||||
INNER JOIN `rocpd_event` E ON E.id = R.event_id
|
||||
AND E.guid = R.guid
|
||||
INNER JOIN `rocpd_string` S ON S.id = R.name_id
|
||||
AND S.guid = R.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = R.pid
|
||||
AND P.guid = R.guid
|
||||
INNER JOIN `rocpd_info_thread` T ON T.id = R.tid
|
||||
AND T.guid = R.guid;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`region_args` AS
|
||||
SELECT
|
||||
R.id,
|
||||
R.guid,
|
||||
R.nid,
|
||||
P.pid,
|
||||
A.type,
|
||||
A.name,
|
||||
A.value
|
||||
FROM
|
||||
`rocpd_region` R
|
||||
INNER JOIN `rocpd_event` E ON E.id = R.event_id
|
||||
AND E.guid = R.guid
|
||||
INNER JOIN `rocpd_arg` A ON A.event_id = E.id
|
||||
AND A.guid = R.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = R.pid
|
||||
AND P.guid = R.guid;
|
||||
|
||||
--
|
||||
-- Samples
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`samples` AS
|
||||
SELECT
|
||||
R.id,
|
||||
R.guid,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = T.name_id
|
||||
AND RS.guid = T.guid
|
||||
) AS name,
|
||||
T.nid,
|
||||
P.pid,
|
||||
TH.tid,
|
||||
R.timestamp,
|
||||
R.event_id,
|
||||
E.stack_id AS stack_id,
|
||||
E.parent_stack_id AS parent_stack_id,
|
||||
E.correlation_id AS corr_id,
|
||||
E.extdata AS extdata,
|
||||
E.call_stack AS call_stack,
|
||||
E.line_info AS line_info
|
||||
FROM
|
||||
`rocpd_sample` R
|
||||
INNER JOIN `rocpd_track` T ON T.id = R.track_id
|
||||
AND T.guid = R.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = R.event_id
|
||||
AND E.guid = R.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = T.pid
|
||||
AND P.guid = T.guid
|
||||
INNER JOIN `rocpd_info_thread` TH ON TH.id = T.tid
|
||||
AND TH.guid = T.guid;
|
||||
|
||||
--
|
||||
-- Provides samples view with the same columns as regions view
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`sample_regions` AS
|
||||
SELECT
|
||||
R.id,
|
||||
R.guid,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = T.name_id
|
||||
AND RS.guid = T.guid
|
||||
) AS name,
|
||||
T.nid,
|
||||
P.pid,
|
||||
TH.tid,
|
||||
R.timestamp AS start,
|
||||
R.timestamp AS END,
|
||||
(R.timestamp - R.timestamp) AS duration,
|
||||
R.event_id,
|
||||
E.stack_id AS stack_id,
|
||||
E.parent_stack_id AS parent_stack_id,
|
||||
E.correlation_id AS corr_id,
|
||||
E.extdata AS extdata,
|
||||
E.call_stack AS call_stack,
|
||||
E.line_info AS line_info
|
||||
FROM
|
||||
`rocpd_sample` R
|
||||
INNER JOIN `rocpd_track` T ON T.id = R.track_id
|
||||
AND T.guid = R.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = R.event_id
|
||||
AND E.guid = R.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = T.pid
|
||||
AND P.guid = T.guid
|
||||
INNER JOIN `rocpd_info_thread` TH ON TH.id = T.tid
|
||||
AND TH.guid = T.guid;
|
||||
|
||||
--
|
||||
-- Provides a unified view of the regions and samples
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`regions_and_samples` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`regions`
|
||||
UNION ALL
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`sample_regions`;
|
||||
|
||||
--
|
||||
-- Kernel information
|
||||
CREATE VIEW
|
||||
`kernels` AS
|
||||
SELECT
|
||||
K.id,
|
||||
K.guid,
|
||||
T.tid,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
R.string AS region,
|
||||
S.display_name AS name,
|
||||
K.nid,
|
||||
P.pid,
|
||||
A.absolute_index AS agent_abs_index,
|
||||
A.logical_index AS agent_log_index,
|
||||
A.type_index AS agent_type_index,
|
||||
A.type AS agent_type,
|
||||
S.code_object_id AS code_object_id,
|
||||
K.kernel_id,
|
||||
K.dispatch_id,
|
||||
K.stream_id,
|
||||
K.queue_id,
|
||||
Q.name AS queue,
|
||||
ST.name AS stream,
|
||||
K.start,
|
||||
K.end,
|
||||
(K.end - K.start) AS duration,
|
||||
K.grid_size_x AS grid_x,
|
||||
K.grid_size_y AS grid_y,
|
||||
K.grid_size_z AS grid_z,
|
||||
K.workgroup_size_x AS workgroup_x,
|
||||
K.workgroup_size_y AS workgroup_y,
|
||||
K.workgroup_size_z AS workgroup_z,
|
||||
K.group_segment_size AS lds_size,
|
||||
K.private_segment_size AS scratch_size,
|
||||
S.group_segment_size AS static_lds_size,
|
||||
S.private_segment_size AS static_scratch_size,
|
||||
E.stack_id,
|
||||
E.parent_stack_id,
|
||||
E.correlation_id AS corr_id
|
||||
FROM
|
||||
`rocpd_kernel_dispatch` K
|
||||
INNER JOIN `rocpd_info_agent` A ON A.id = K.agent_id
|
||||
AND A.guid = K.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = K.event_id
|
||||
AND E.guid = K.guid
|
||||
INNER JOIN `rocpd_string` R ON R.id = K.region_name_id
|
||||
AND R.guid = K.guid
|
||||
INNER JOIN `rocpd_info_kernel_symbol` S ON S.id = K.kernel_id
|
||||
AND S.guid = K.guid
|
||||
LEFT JOIN `rocpd_info_stream` ST ON ST.id = K.stream_id
|
||||
AND ST.guid = K.guid
|
||||
LEFT JOIN `rocpd_info_queue` Q ON Q.id = K.queue_id
|
||||
AND Q.guid = K.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = Q.pid
|
||||
AND P.guid = Q.guid
|
||||
INNER JOIN `rocpd_info_thread` T ON T.id = K.tid
|
||||
AND T.guid = K.guid;
|
||||
|
||||
--
|
||||
-- Performance Monitoring Counters (PMC)
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`pmc_info` AS
|
||||
SELECT
|
||||
PMC_I.id,
|
||||
PMC_I.guid,
|
||||
PMC_I.nid,
|
||||
P.pid,
|
||||
A.absolute_index AS agent_abs_index,
|
||||
PMC_I.is_constant,
|
||||
PMC_I.is_derived,
|
||||
PMC_I.name,
|
||||
PMC_I.description,
|
||||
PMC_I.block,
|
||||
PMC_I.expression
|
||||
FROM
|
||||
`rocpd_info_pmc` PMC_I
|
||||
INNER JOIN `rocpd_info_agent` A ON PMC_I.agent_id = A.id
|
||||
AND PMC_I.guid = A.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = PMC_I.pid
|
||||
AND PMC_I.guid = P.guid;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`pmc_events` AS
|
||||
SELECT
|
||||
PMC_E.id,
|
||||
PMC_E.guid,
|
||||
PMC_E.pmc_id,
|
||||
E.id AS event_id,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
(
|
||||
SELECT
|
||||
display_name
|
||||
FROM
|
||||
`rocpd_info_kernel_symbol` KS
|
||||
WHERE
|
||||
KS.id = K.kernel_id
|
||||
AND KS.guid = K.guid
|
||||
) AS name,
|
||||
K.nid,
|
||||
P.pid,
|
||||
K.dispatch_id,
|
||||
K.start,
|
||||
K.end,
|
||||
(K.end - K.start) AS duration,
|
||||
PMC_I.name AS counter_name,
|
||||
PMC_E.value AS counter_value
|
||||
FROM
|
||||
`rocpd_pmc_event` PMC_E
|
||||
INNER JOIN `rocpd_info_pmc` PMC_I ON PMC_I.id = PMC_E.pmc_id
|
||||
AND PMC_I.guid = PMC_E.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = PMC_E.event_id
|
||||
AND E.guid = PMC_E.guid
|
||||
INNER JOIN `rocpd_kernel_dispatch` K ON K.event_id = PMC_E.event_id
|
||||
AND K.guid = PMC_E.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = K.pid
|
||||
AND P.guid = K.guid;
|
||||
|
||||
-- events with arguments ---
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`events_args` AS
|
||||
SELECT
|
||||
E.id AS event_id,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
E.stack_id,
|
||||
E.parent_stack_id,
|
||||
E.correlation_id,
|
||||
A.position AS arg_position,
|
||||
A.type AS arg_type,
|
||||
A.name AS arg_name,
|
||||
A.value AS arg_value,
|
||||
E.call_stack,
|
||||
E.line_info,
|
||||
A.extdata
|
||||
FROM
|
||||
`rocpd_event` E
|
||||
INNER JOIN `rocpd_arg` A ON A.event_id = E.id
|
||||
AND A.guid = E.guid;
|
||||
|
||||
-- list of astream arguments enriched by the corresponding stream descriptions
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`stream_args` AS
|
||||
SELECT
|
||||
A.id AS argument_id,
|
||||
A.event_id AS event_id,
|
||||
A.position AS arg_position,
|
||||
A.type AS arg_type,
|
||||
A.value AS arg_value,
|
||||
JSON_EXTRACT(A.extdata, '$.stream_id') AS stream_id,
|
||||
S.nid,
|
||||
P.pid,
|
||||
S.name AS stream_name,
|
||||
S.extdata AS extdata
|
||||
FROM
|
||||
`rocpd_arg` A
|
||||
INNER JOIN `rocpd_info_stream` S ON JSON_EXTRACT(A.extdata, '$.stream_id') = S.id
|
||||
AND A.guid = S.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = S.pid
|
||||
AND P.guid = S.guid
|
||||
WHERE
|
||||
A.name = 'stream';
|
||||
|
||||
--
|
||||
--
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`memory_copies` AS
|
||||
SELECT
|
||||
M.id,
|
||||
M.guid,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
M.nid,
|
||||
P.pid,
|
||||
T.tid,
|
||||
M.start,
|
||||
M.end,
|
||||
(M.end - M.start) AS duration,
|
||||
S.string AS name,
|
||||
R.string AS region_name,
|
||||
M.stream_id,
|
||||
M.queue_id,
|
||||
ST.name AS stream_name,
|
||||
Q.name AS queue_name,
|
||||
M.size,
|
||||
dst_agent.name AS dst_device,
|
||||
dst_agent.absolute_index AS dst_agent_abs_index,
|
||||
dst_agent.logical_index AS dst_agent_log_index,
|
||||
dst_agent.type_index AS dst_agent_type_index,
|
||||
dst_agent.type AS dst_agent_type,
|
||||
M.dst_address,
|
||||
src_agent.name AS src_device,
|
||||
src_agent.absolute_index AS src_agent_abs_index,
|
||||
src_agent.logical_index AS src_agent_log_index,
|
||||
src_agent.type_index AS src_agent_type_index,
|
||||
src_agent.type AS src_agent_type,
|
||||
M.src_address,
|
||||
E.stack_id,
|
||||
E.parent_stack_id,
|
||||
E.correlation_id AS corr_id
|
||||
FROM
|
||||
`rocpd_memory_copy` M
|
||||
INNER JOIN `rocpd_string` S ON S.id = M.name_id
|
||||
AND S.guid = M.guid
|
||||
LEFT JOIN `rocpd_string` R ON R.id = M.region_name_id
|
||||
AND R.guid = M.guid
|
||||
INNER JOIN `rocpd_info_agent` dst_agent ON dst_agent.id = M.dst_agent_id
|
||||
AND dst_agent.guid = M.guid
|
||||
INNER JOIN `rocpd_info_agent` src_agent ON src_agent.id = M.src_agent_id
|
||||
AND src_agent.guid = M.guid
|
||||
LEFT JOIN `rocpd_info_queue` Q ON Q.id = M.queue_id
|
||||
AND Q.guid = M.guid
|
||||
LEFT JOIN `rocpd_info_stream` ST ON ST.id = M.stream_id
|
||||
AND ST.guid = M.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = M.event_id
|
||||
AND E.guid = M.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = M.pid
|
||||
AND P.guid = M.guid
|
||||
INNER JOIN `rocpd_info_thread` T ON T.id = M.tid
|
||||
AND T.guid = M.guid;
|
||||
|
||||
--
|
||||
--
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`memory_allocations` AS
|
||||
SELECT
|
||||
M.id,
|
||||
M.guid,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
M.nid,
|
||||
P.pid,
|
||||
T.tid,
|
||||
M.start,
|
||||
M.end,
|
||||
(M.end - M.start) AS duration,
|
||||
M.type,
|
||||
M.level,
|
||||
A.name AS agent_name,
|
||||
A.absolute_index AS agent_abs_index,
|
||||
A.logical_index AS agent_log_index,
|
||||
A.type_index AS agent_type_index,
|
||||
A.type AS agent_type,
|
||||
M.address,
|
||||
M.size,
|
||||
M.queue_id,
|
||||
Q.name AS queue_name,
|
||||
M.stream_id,
|
||||
ST.name AS stream_name,
|
||||
E.stack_id,
|
||||
E.parent_stack_id,
|
||||
E.correlation_id AS corr_id
|
||||
FROM
|
||||
`rocpd_memory_allocate` M
|
||||
LEFT JOIN `rocpd_info_agent` A ON M.agent_id = A.id
|
||||
AND M.guid = A.guid
|
||||
LEFT JOIN `rocpd_info_queue` Q ON Q.id = M.queue_id
|
||||
AND Q.guid = M.guid
|
||||
LEFT JOIN `rocpd_info_stream` ST ON ST.id = M.stream_id
|
||||
AND ST.guid = M.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = M.event_id
|
||||
AND E.guid = M.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = M.pid
|
||||
AND P.guid = M.guid
|
||||
INNER JOIN `rocpd_info_thread` T ON T.id = M.tid
|
||||
AND P.guid = M.guid;
|
||||
|
||||
--
|
||||
--
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`scratch_memory` AS
|
||||
SELECT
|
||||
M.id,
|
||||
M.guid,
|
||||
M.nid,
|
||||
P.pid,
|
||||
M.type AS operation,
|
||||
A.name AS agent_name,
|
||||
A.absolute_index AS agent_abs_index,
|
||||
A.logical_index AS agent_log_index,
|
||||
A.type_index AS agent_type_index,
|
||||
A.type AS agent_type,
|
||||
M.queue_id,
|
||||
T.tid,
|
||||
JSON_EXTRACT(M.extdata, '$.flags') AS alloc_flags,
|
||||
M.start,
|
||||
M.end,
|
||||
M.size,
|
||||
M.address,
|
||||
E.correlation_id,
|
||||
E.stack_id,
|
||||
E.parent_stack_id,
|
||||
E.correlation_id AS corr_id,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
E.extdata AS event_extdata
|
||||
FROM
|
||||
`rocpd_memory_allocate` M
|
||||
LEFT JOIN `rocpd_info_agent` A ON M.agent_id = A.id
|
||||
AND M.guid = A.guid
|
||||
LEFT JOIN `rocpd_info_queue` Q ON Q.id = M.queue_id
|
||||
AND Q.guid = M.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = M.event_id
|
||||
AND E.guid = M.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = M.pid
|
||||
AND P.guid = M.guid
|
||||
INNER JOIN `rocpd_info_thread` T ON T.id = M.tid
|
||||
AND T.guid = M.guid
|
||||
WHERE
|
||||
M.level = 'SCRATCH'
|
||||
ORDER BY
|
||||
M.start ASC;
|
||||
|
||||
--
|
||||
--
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`counters_collection` AS
|
||||
SELECT
|
||||
MIN(PMC_E.id) AS id,
|
||||
PMC_E.guid,
|
||||
K.dispatch_id,
|
||||
K.kernel_id,
|
||||
E.id AS event_id,
|
||||
E.correlation_id,
|
||||
E.stack_id,
|
||||
E.parent_stack_id,
|
||||
P.pid,
|
||||
T.tid,
|
||||
K.agent_id,
|
||||
A.absolute_index AS agent_abs_index,
|
||||
A.logical_index AS agent_log_index,
|
||||
A.type_index AS agent_type_index,
|
||||
A.type AS agent_type,
|
||||
K.queue_id,
|
||||
k.grid_size_x AS grid_size_x,
|
||||
k.grid_size_y AS grid_size_y,
|
||||
k.grid_size_z AS grid_size_z,
|
||||
(K.grid_size_x * K.grid_size_y * K.grid_size_z) AS grid_size,
|
||||
S.display_name AS kernel_name,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = K.region_name_id
|
||||
AND RS.guid = K.guid
|
||||
) AS kernel_region,
|
||||
K.workgroup_size_x AS workgroup_size_x,
|
||||
K.workgroup_size_y AS workgroup_size_y,
|
||||
K.workgroup_size_z AS workgroup_size_z,
|
||||
(K.workgroup_size_x * K.workgroup_size_y * K.workgroup_size_z) AS workgroup_size,
|
||||
K.group_segment_size AS lds_block_size,
|
||||
K.private_segment_size AS scratch_size,
|
||||
S.arch_vgpr_count AS vgpr_count,
|
||||
S.accum_vgpr_count,
|
||||
S.sgpr_count,
|
||||
PMC_I.name AS counter_name,
|
||||
PMC_I.symbol AS counter_symbol,
|
||||
PMC_I.component,
|
||||
PMC_I.description,
|
||||
PMC_I.block,
|
||||
PMC_I.expression,
|
||||
PMC_I.value_type,
|
||||
PMC_I.id AS counter_id,
|
||||
SUM(PMC_E.value) AS value,
|
||||
K.start,
|
||||
K.end,
|
||||
PMC_I.is_constant,
|
||||
PMC_I.is_derived,
|
||||
(K.end - K.start) AS duration,
|
||||
(
|
||||
SELECT
|
||||
string
|
||||
FROM
|
||||
`rocpd_string` RS
|
||||
WHERE
|
||||
RS.id = E.category_id
|
||||
AND RS.guid = E.guid
|
||||
) AS category,
|
||||
K.nid,
|
||||
E.extdata,
|
||||
S.code_object_id
|
||||
FROM
|
||||
`rocpd_pmc_event` PMC_E
|
||||
INNER JOIN `rocpd_info_pmc` PMC_I ON PMC_I.id = PMC_E.pmc_id
|
||||
AND PMC_I.guid = PMC_E.guid
|
||||
INNER JOIN `rocpd_event` E ON E.id = PMC_E.event_id
|
||||
AND E.guid = PMC_E.guid
|
||||
INNER JOIN `rocpd_kernel_dispatch` K ON K.event_id = PMC_E.event_id
|
||||
AND K.guid = PMC_E.guid
|
||||
INNER JOIN `rocpd_info_agent` A ON A.id = K.agent_id
|
||||
AND A.guid = K.guid
|
||||
INNER JOIN `rocpd_info_kernel_symbol` S ON S.id = K.kernel_id
|
||||
AND S.guid = K.guid
|
||||
INNER JOIN `rocpd_info_process` P ON P.id = K.pid
|
||||
AND P.guid = K.guid
|
||||
INNER JOIN `rocpd_info_thread` T ON T.id = K.tid
|
||||
AND T.guid = K.guid
|
||||
GROUP BY
|
||||
PMC_E.guid,
|
||||
K.dispatch_id,
|
||||
PMC_I.name,
|
||||
K.agent_id;
|
||||
@@ -0,0 +1,3 @@
|
||||
--
|
||||
-- Views related to markers
|
||||
--
|
||||
@@ -0,0 +1,45 @@
|
||||
--
|
||||
-- Indexes for the various fields
|
||||
--
|
||||
|
||||
-- string field
|
||||
-- CREATE INDEX `rocpd_string{{uuid}}_string_idx` ON `rocpd_string{{uuid}}` ("string");
|
||||
|
||||
-- guid field
|
||||
-- CREATE INDEX `rocpd_string{{uuid}}_guid_idx` ON `rocpd_string{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_node{{uuid}}_guid_idx` ON `rocpd_info_node{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_process{{uuid}}_guid_idx` ON `rocpd_info_process{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_thread{{uuid}}_guid_idx` ON `rocpd_info_thread{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_agent{{uuid}}_guid_idx` ON `rocpd_info_agent{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_queue{{uuid}}_guid_idx` ON `rocpd_info_queue{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_stream{{uuid}}_guid_idx` ON `rocpd_info_stream{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_pmc{{uuid}}_guid_idx` ON `rocpd_info_pmc{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_code_object{{uuid}}_guid_idx` ON `rocpd_info_code_object{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_info_kernel_symbol{{uuid}}_guid_idx` ON `rocpd_info_kernel_symbol{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_track{{uuid}}_guid_idx` ON `rocpd_track{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_event{{uuid}}_guid_idx` ON `rocpd_event{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_arg{{uuid}}_guid_idx` ON `rocpd_arg{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_pmc_event{{uuid}}_guid_idx` ON `rocpd_pmc_event{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_guid_idx` ON `rocpd_region{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_sample{{uuid}}_guid_idx` ON `rocpd_sample{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_kernel_dispatch{{uuid}}_guid_idx` ON `rocpd_kernel_dispatch{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_memory_copy{{uuid}}_guid_idx` ON `rocpd_memory_copy{{uuid}}` ("id", "guid");
|
||||
-- CREATE INDEX `rocpd_memory_allocate{{uuid}}_guid_idx` ON `rocpd_memory_allocate{{uuid}}` ("id", "guid");
|
||||
|
||||
-- CREATE INDEX `rocpd_event{{uuid}}_category_idx` ON `rocpd_event{{uuid}}` ("id", "guid", "category_id");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_event_idx` ON `rocpd_region{{uuid}}` ("id", "guid", "event_id");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_name_idx` ON `rocpd_region{{uuid}}` ("id", "guid", "name_id");
|
||||
-- CREATE INDEX `rocpd_sample{{uuid}}_event_idx` ON `rocpd_sample{{uuid}}` ("id", "guid", "event_id");
|
||||
-- CREATE INDEX `rocpd_sample{{uuid}}_track_idx` ON `rocpd_sample{{uuid}}` ("id", "guid", "track_id");
|
||||
-- CREATE INDEX `rocpd_track{{uuid}}_name_idx` ON `rocpd_track{{uuid}}` ("id", "guid", "name_id");
|
||||
|
||||
-- CREATE INDEX `rocpd_memory_copy{{uuid}}_guid_nid_pid_idx` ON `rocpd_memory_copy{{uuid}}` ("guid", "nid", "pid");
|
||||
-- CREATE INDEX `rocpd_kernel_dispatch{{uuid}}_guid_nid_pid_idx` ON `rocpd_kernel_dispatch{{uuid}}` ("guid", "nid", "pid");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_guid_idx` ON `rocpd_region{{uuid}}` ("guid", "nid", "pid");
|
||||
-- CREATE INDEX `rocpd_sample{{uuid}}_guid_nid_pid_idx` ON `rocpd_sample{{uuid}}` ("guid", "nid", "pid");
|
||||
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_guid_idx` ON `rocpd_region{{uuid}}` ("guid");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_nid_idx` ON `rocpd_region{{uuid}}` ("nid");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_pid_idx` ON `rocpd_region{{uuid}}` ("pid");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_start_idx` ON `rocpd_region{{uuid}}` ("start");
|
||||
-- CREATE INDEX `rocpd_region{{uuid}}_end_idx` ON `rocpd_region{{uuid}}` ("end");
|
||||
@@ -0,0 +1,373 @@
|
||||
-- Enable foreign key support for cascading
|
||||
PRAGMA foreign_keys = ON;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
"rocpd_metadata{{uuid}}" (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"tag" TEXT NOT NULL,
|
||||
"value" TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_string{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"string" TEXT NOT NULL UNIQUE ON CONFLICT ABORT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_node{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"hash" BIGINT NOT NULL UNIQUE,
|
||||
"machine_id" TEXT NOT NULL UNIQUE,
|
||||
"system_name" TEXT,
|
||||
"hostname" TEXT,
|
||||
"release" TEXT,
|
||||
"version" TEXT,
|
||||
"hardware_name" TEXT,
|
||||
"domain_name" TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_process{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"ppid" INTEGER,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"init" BIGINT,
|
||||
"fini" BIGINT,
|
||||
"start" BIGINT,
|
||||
"end" BIGINT,
|
||||
"command" TEXT,
|
||||
"environment" JSONB DEFAULT "{}" NOT NULL,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_thread{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"ppid" INTEGER,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"tid" INTEGER NOT NULL,
|
||||
"name" TEXT,
|
||||
"start" BIGINT,
|
||||
"end" BIGINT,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_agent{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"type" TEXT CHECK ("type" IN ('CPU', 'GPU')),
|
||||
"absolute_index" INTEGER,
|
||||
"logical_index" INTEGER,
|
||||
"type_index" INTEGER,
|
||||
"uuid" INTEGER,
|
||||
"name" TEXT,
|
||||
"model_name" TEXT,
|
||||
"vendor_name" TEXT,
|
||||
"product_name" TEXT,
|
||||
"user_name" TEXT,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_queue{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"name" TEXT,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_stream{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"name" TEXT,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- 2993533, 2269219937, 2993533
|
||||
-- 2993533, 2269219937, 2993533
|
||||
-- Performance monitoring counters (PMC) descriptions
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_pmc{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"agent_id" INTEGER,
|
||||
"target_arch" TEXT CHECK ("target_arch" IN ('CPU', 'GPU')),
|
||||
"event_code" INT,
|
||||
"instance_id" INTEGER,
|
||||
"name" TEXT NOT NULL,
|
||||
"symbol" TEXT NOT NULL,
|
||||
"description" TEXT,
|
||||
"long_description" TEXT DEFAULT "",
|
||||
"component" TEXT,
|
||||
"units" TEXT DEFAULT "",
|
||||
"value_type" TEXT CHECK ("value_type" IN ('ABS', 'ACCUM', 'RELATIVE')),
|
||||
"block" TEXT,
|
||||
"expression" TEXT,
|
||||
"is_constant" INTEGER,
|
||||
"is_derived" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (agent_id) REFERENCES `rocpd_info_agent{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_code_object{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"agent_id" INTEGER,
|
||||
"uri" TEXT,
|
||||
"load_base" BIGINT,
|
||||
"load_size" BIGINT,
|
||||
"load_delta" BIGINT,
|
||||
"storage_type" TEXT CHECK ("storage_type" IN ('FILE', 'MEMORY')),
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (agent_id) REFERENCES `rocpd_info_agent{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_info_kernel_symbol{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"code_object_id" INTEGER NOT NULL,
|
||||
"kernel_name" TEXT,
|
||||
"display_name" TEXT,
|
||||
"kernel_object" INTEGER,
|
||||
"kernarg_segment_size" INTEGER,
|
||||
"kernarg_segment_alignment" INTEGER,
|
||||
"group_segment_size" INTEGER,
|
||||
"private_segment_size" INTEGER,
|
||||
"sgpr_count" INTEGER,
|
||||
"arch_vgpr_count" INTEGER,
|
||||
"accum_vgpr_count" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (code_object_id) REFERENCES `rocpd_info_code_object{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Stores repetitive info for samples
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_track{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER,
|
||||
"tid" INTEGER,
|
||||
"name_id" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (tid) REFERENCES `rocpd_info_thread{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (name_id) REFERENCES `rocpd_string{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Storage for a region, instant, and counter
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_event{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"category_id" INTEGER,
|
||||
"stack_id" INTEGER,
|
||||
"parent_stack_id" INTEGER,
|
||||
"correlation_id" INTEGER,
|
||||
"call_stack" JSONB DEFAULT "{}" NOT NULL,
|
||||
"line_info" JSONB DEFAULT "{}" NOT NULL,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (category_id) REFERENCES `rocpd_string{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- stores arguments for events
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_arg{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"event_id" INTEGER NOT NULL,
|
||||
"position" INTEGER NOT NULL,
|
||||
"type" TEXT NOT NULL,
|
||||
"name" TEXT NOT NULL,
|
||||
"value" TEXT, -- TODO: discuss make it value_id and integer, refer to string table --
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (event_id) REFERENCES `rocpd_event{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Region with a start/stop on the same thread (CPU)
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_pmc_event{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"event_id" INTEGER,
|
||||
"pmc_id" INTEGER NOT NULL,
|
||||
"value" REAL DEFAULT 0.0,
|
||||
"extdata" JSONB DEFAULT "{}",
|
||||
FOREIGN KEY (pmc_id) REFERENCES `rocpd_info_pmc{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (event_id) REFERENCES `rocpd_event{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Region with a start/stop on the same thread (CPU)
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_region{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"tid" INTEGER NOT NULL,
|
||||
"start" BIGINT NOT NULL,
|
||||
"end" BIGINT NOT NULL,
|
||||
"name_id" INTEGER NOT NULL,
|
||||
"event_id" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (tid) REFERENCES `rocpd_info_thread{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (name_id) REFERENCES `rocpd_string{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (event_id) REFERENCES `rocpd_event{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Instantaneous sample
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_sample{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"track_id" INTEGER NOT NULL,
|
||||
"timestamp" BIGINT NOT NULL,
|
||||
"event_id" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (track_id) REFERENCES `rocpd_track{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (event_id) REFERENCES `rocpd_event{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_kernel_dispatch{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"tid" INTEGER,
|
||||
"agent_id" INTEGER NOT NULL,
|
||||
"kernel_id" INTEGER NOT NULL,
|
||||
"dispatch_id" INTEGER NOT NULL,
|
||||
"queue_id" INTEGER NOT NULL,
|
||||
"stream_id" INTEGER NOT NULL,
|
||||
"start" BIGINT NOT NULL,
|
||||
"end" BIGINT NOT NULL,
|
||||
"private_segment_size" INTEGER,
|
||||
"group_segment_size" INTEGER,
|
||||
"workgroup_size_x" INTEGER NOT NULL,
|
||||
"workgroup_size_y" INTEGER NOT NULL,
|
||||
"workgroup_size_z" INTEGER NOT NULL,
|
||||
"grid_size_x" INTEGER NOT NULL,
|
||||
"grid_size_y" INTEGER NOT NULL,
|
||||
"grid_size_z" INTEGER NOT NULL,
|
||||
"region_name_id" INTEGER,
|
||||
"event_id" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (tid) REFERENCES `rocpd_info_thread{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (agent_id) REFERENCES `rocpd_info_agent{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (kernel_id) REFERENCES `rocpd_info_kernel_symbol{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (queue_id) REFERENCES `rocpd_info_queue{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (stream_id) REFERENCES `rocpd_info_stream{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (region_name_id) REFERENCES `rocpd_string{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (event_id) REFERENCES `rocpd_event{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_memory_copy{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"tid" INTEGER,
|
||||
"start" BIGINT NOT NULL,
|
||||
"end" BIGINT NOT NULL,
|
||||
"name_id" INTEGER NOT NULL,
|
||||
"dst_agent_id" INTEGER,
|
||||
"dst_address" INTEGER,
|
||||
"src_agent_id" INTEGER,
|
||||
"src_address" INTEGER,
|
||||
"size" INTEGER NOT NULL,
|
||||
"queue_id" INTEGER,
|
||||
"stream_id" INTEGER,
|
||||
"region_name_id" INTEGER,
|
||||
"event_id" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (tid) REFERENCES `rocpd_info_thread{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (name_id) REFERENCES `rocpd_string{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (dst_agent_id) REFERENCES `rocpd_info_agent{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (src_agent_id) REFERENCES `rocpd_info_agent{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (stream_id) REFERENCES `rocpd_info_stream{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (queue_id) REFERENCES `rocpd_info_queue{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (region_name_id) REFERENCES `rocpd_string{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (event_id) REFERENCES `rocpd_event{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
-- Memory allocations (real memory, virtual memory, and scratch memory)
|
||||
CREATE TABLE IF NOT EXISTS
|
||||
`rocpd_memory_allocate{{uuid}}` (
|
||||
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
"guid" TEXT DEFAULT "{{guid}}" NOT NULL,
|
||||
"nid" INTEGER NOT NULL,
|
||||
"pid" INTEGER NOT NULL,
|
||||
"tid" INTEGER,
|
||||
"agent_id" INTEGER,
|
||||
"type" TEXT CHECK ("type" IN ('ALLOC', 'FREE', 'REALLOC', 'RECLAIM')),
|
||||
"level" TEXT CHECK ("level" IN ('REAL', 'VIRTUAL', 'SCRATCH')),
|
||||
"start" BIGINT NOT NULL,
|
||||
"end" BIGINT NOT NULL,
|
||||
"address" INTEGER,
|
||||
"size" INTEGER NOT NULL,
|
||||
"queue_id" INTEGER,
|
||||
"stream_id" INTEGER,
|
||||
"event_id" INTEGER,
|
||||
"extdata" JSONB DEFAULT "{}" NOT NULL,
|
||||
FOREIGN KEY (nid) REFERENCES `rocpd_info_node{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (pid) REFERENCES `rocpd_info_process{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (tid) REFERENCES `rocpd_info_thread{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (agent_id) REFERENCES `rocpd_info_agent{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (stream_id) REFERENCES `rocpd_info_stream{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (queue_id) REFERENCES `rocpd_info_queue{{uuid}}` (id) ON UPDATE CASCADE,
|
||||
FOREIGN KEY (event_id) REFERENCES `rocpd_event{{uuid}}` (id) ON UPDATE CASCADE
|
||||
);
|
||||
|
||||
INSERT INTO
|
||||
`rocpd_metadata{{uuid}}` ("tag", "value")
|
||||
VALUES
|
||||
("schema_version", "3"),
|
||||
("uuid", "{{uuid}}"),
|
||||
("guid", "{{guid}}");
|
||||
@@ -0,0 +1,139 @@
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_metadata` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_metadata{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_string` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_string{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_node` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_node{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_process` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_process{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_thread` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_thread{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_agent` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_agent{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_queue` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_queue{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_stream` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_stream{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_pmc` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_pmc{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_code_object` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_code_object{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_info_kernel_symbol` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_info_kernel_symbol{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_track` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_track{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_event` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_event{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_arg` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_arg{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_pmc_event` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_pmc_event{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_region` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_region{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_sample` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_sample{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_kernel_dispatch` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_kernel_dispatch{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_memory_copy` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_memory_copy{{uuid}}`;
|
||||
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`rocpd_memory_allocate` AS
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
`rocpd_memory_allocate{{uuid}}`;
|
||||
@@ -0,0 +1,376 @@
|
||||
--
|
||||
-- Useful summary views
|
||||
--
|
||||
--
|
||||
-- Sorted list of kernels which consume the most overall time
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`top_kernels` AS
|
||||
SELECT
|
||||
S.display_name AS name,
|
||||
COUNT(K.kernel_id) AS total_calls,
|
||||
SUM(K.end - K.start) / 1000.0 AS total_duration,
|
||||
(SUM(K.end - K.start) / COUNT(K.kernel_id)) / 1000.0 AS average,
|
||||
SUM(K.end - K.start) * 100.0 / (
|
||||
SELECT
|
||||
SUM(A.end - A.start)
|
||||
FROM
|
||||
`rocpd_kernel_dispatch` A
|
||||
) AS percentage
|
||||
FROM
|
||||
`rocpd_kernel_dispatch` K
|
||||
INNER JOIN `rocpd_info_kernel_symbol` S ON S.id = K.kernel_id
|
||||
AND S.guid = K.guid
|
||||
GROUP BY
|
||||
name
|
||||
ORDER BY
|
||||
total_duration DESC;
|
||||
|
||||
--
|
||||
-- GPU utilization metrics including kernels and memory copy operations
|
||||
CREATE VIEW IF NOT EXISTS
|
||||
`busy` AS
|
||||
SELECT
|
||||
A.agent_id,
|
||||
AG.type,
|
||||
GpuTime,
|
||||
WallTime,
|
||||
GpuTime * 1.0 / WallTime AS Busy
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
agent_id,
|
||||
guid,
|
||||
SUM(END - start) AS GpuTime
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
agent_id,
|
||||
guid,
|
||||
END,
|
||||
start
|
||||
FROM
|
||||
`rocpd_kernel_dispatch`
|
||||
UNION ALL
|
||||
SELECT
|
||||
dst_agent_id AS agent_id,
|
||||
guid,
|
||||
END,
|
||||
start
|
||||
FROM
|
||||
`rocpd_memory_copy`
|
||||
)
|
||||
GROUP BY
|
||||
agent_id,
|
||||
guid
|
||||
) A
|
||||
INNER JOIN (
|
||||
SELECT
|
||||
MAX(END) - MIN(start) AS WallTime
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
END,
|
||||
start
|
||||
FROM
|
||||
`rocpd_kernel_dispatch`
|
||||
UNION ALL
|
||||
SELECT
|
||||
END,
|
||||
start
|
||||
FROM
|
||||
`rocpd_memory_copy`
|
||||
)
|
||||
) W ON 1 = 1
|
||||
INNER JOIN `rocpd_info_agent` AG ON AG.id = A.agent_id
|
||||
AND AG.guid = A.guid;
|
||||
|
||||
--
|
||||
-- Overall performance summary including kernels and memory copy operations
|
||||
CREATE VIEW
|
||||
`top` AS
|
||||
SELECT
|
||||
name,
|
||||
COUNT(*) AS total_calls,
|
||||
SUM(duration) / 1000.0 AS total_duration,
|
||||
(SUM(duration) / COUNT(*)) / 1000.0 AS average,
|
||||
SUM(duration) * 100.0 / total_time AS percentage
|
||||
FROM
|
||||
(
|
||||
-- Kernel operations
|
||||
SELECT
|
||||
ks.display_name AS name,
|
||||
(kd.end - kd.start) AS duration
|
||||
FROM
|
||||
`rocpd_kernel_dispatch` kd
|
||||
INNER JOIN `rocpd_info_kernel_symbol` ks ON kd.kernel_id = ks.id
|
||||
AND kd.guid = ks.guid
|
||||
UNION ALL
|
||||
-- Memory operations
|
||||
SELECT
|
||||
rs.string AS name,
|
||||
(END - start) AS duration
|
||||
FROM
|
||||
`rocpd_memory_copy` mc
|
||||
INNER JOIN `rocpd_string` rs ON rs.id = mc.name_id
|
||||
AND rs.guid = mc.guid
|
||||
UNION ALL
|
||||
-- Regions
|
||||
SELECT
|
||||
rs.string AS name,
|
||||
(END - start) AS duration
|
||||
FROM
|
||||
`rocpd_region` rr
|
||||
INNER JOIN `rocpd_string` rs ON rs.id = rr.name_id
|
||||
AND rs.guid = rr.guid
|
||||
) operations
|
||||
CROSS JOIN (
|
||||
SELECT
|
||||
SUM(END - start) AS total_time
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
END,
|
||||
start
|
||||
FROM
|
||||
`rocpd_kernel_dispatch`
|
||||
UNION ALL
|
||||
SELECT
|
||||
END,
|
||||
start
|
||||
FROM
|
||||
`rocpd_memory_copy`
|
||||
UNION ALL
|
||||
SELECT
|
||||
END,
|
||||
start
|
||||
FROM
|
||||
`rocpd_region`
|
||||
)
|
||||
) TOTAL
|
||||
GROUP BY
|
||||
name
|
||||
ORDER BY
|
||||
total_duration DESC;
|
||||
|
||||
-- Kernel summary by name
|
||||
CREATE VIEW
|
||||
`kernel_summary` AS
|
||||
WITH
|
||||
avg_data AS (
|
||||
SELECT
|
||||
name,
|
||||
AVG(duration) AS avg_duration
|
||||
FROM
|
||||
`kernels`
|
||||
GROUP BY
|
||||
name
|
||||
),
|
||||
aggregated_data AS (
|
||||
SELECT
|
||||
K.name,
|
||||
COUNT(*) AS calls,
|
||||
SUM(K.duration) AS total_duration,
|
||||
SUM(CAST(K.duration AS REAL) * CAST(K.duration AS REAL)) AS sqr_duration,
|
||||
A.avg_duration AS average_duration,
|
||||
MIN(K.duration) AS min_duration,
|
||||
MAX(K.duration) AS max_duration,
|
||||
SUM(CAST((K.duration - A.avg_duration) AS REAL) * CAST((K.duration - A.avg_duration) AS REAL)) / (COUNT(*) - 1) AS variance_duration,
|
||||
SQRT(
|
||||
SUM(CAST((K.duration - A.avg_duration) AS REAL) * CAST((K.duration - A.avg_duration) AS REAL)) / (COUNT(*) - 1)
|
||||
) AS std_dev_duration
|
||||
FROM
|
||||
`kernels` K
|
||||
JOIN avg_data A ON K.name = A.name
|
||||
GROUP BY
|
||||
K.name
|
||||
),
|
||||
total_duration AS (
|
||||
SELECT
|
||||
SUM(total_duration) AS grand_total_duration
|
||||
FROM
|
||||
aggregated_data
|
||||
)
|
||||
SELECT
|
||||
AD.name AS name,
|
||||
AD.calls,
|
||||
AD.total_duration AS "DURATION (nsec)",
|
||||
AD.sqr_duration AS "SQR (nsec)",
|
||||
AD.average_duration AS "AVERAGE (nsec)",
|
||||
(CAST(AD.total_duration AS REAL) / TD.grand_total_duration) * 100 AS "PERCENT (INC)",
|
||||
AD.min_duration AS "MIN (nsec)",
|
||||
AD.max_duration AS "MAX (nsec)",
|
||||
AD.variance_duration AS "VARIANCE",
|
||||
AD.std_dev_duration AS "STD_DEV"
|
||||
FROM
|
||||
aggregated_data AD
|
||||
CROSS JOIN total_duration TD;
|
||||
|
||||
--
|
||||
-- Kernel summary by region name
|
||||
CREATE VIEW
|
||||
`kernel_summary_region` AS
|
||||
WITH
|
||||
avg_data AS (
|
||||
SELECT
|
||||
region,
|
||||
AVG(duration) AS avg_duration
|
||||
FROM
|
||||
`kernels`
|
||||
GROUP BY
|
||||
region
|
||||
),
|
||||
aggregated_data AS (
|
||||
SELECT
|
||||
K.region AS name,
|
||||
COUNT(*) AS calls,
|
||||
SUM(K.duration) AS total_duration,
|
||||
SUM(CAST(K.duration AS REAL) * CAST(K.duration AS REAL)) AS sqr_duration,
|
||||
A.avg_duration AS average_duration,
|
||||
MIN(K.duration) AS min_duration,
|
||||
MAX(K.duration) AS max_duration,
|
||||
SUM(CAST((K.duration - A.avg_duration) AS REAL) * CAST((K.duration - A.avg_duration) AS REAL)) / (COUNT(*) - 1) AS variance_duration,
|
||||
SQRT(
|
||||
SUM(CAST((K.duration - A.avg_duration) AS REAL) * CAST((K.duration - A.avg_duration) AS REAL)) / (COUNT(*) - 1)
|
||||
) AS std_dev_duration
|
||||
FROM
|
||||
`kernels` K
|
||||
JOIN avg_data A ON K.region = A.region
|
||||
GROUP BY
|
||||
K.region
|
||||
),
|
||||
total_duration AS (
|
||||
SELECT
|
||||
SUM(total_duration) AS grand_total_duration
|
||||
FROM
|
||||
aggregated_data
|
||||
)
|
||||
SELECT
|
||||
AD.name AS name,
|
||||
AD.calls,
|
||||
AD.total_duration AS "DURATION (nsec)",
|
||||
AD.sqr_duration AS "SQR (nsec)",
|
||||
AD.average_duration AS "AVERAGE (nsec)",
|
||||
(CAST(AD.total_duration AS REAL) / TD.grand_total_duration) * 100 AS "PERCENT (INC)",
|
||||
AD.min_duration AS "MIN (nsec)",
|
||||
AD.max_duration AS "MAX (nsec)",
|
||||
AD.variance_duration AS "VARIANCE",
|
||||
AD.std_dev_duration AS "STD_DEV"
|
||||
FROM
|
||||
aggregated_data AD
|
||||
CROSS JOIN total_duration TD;
|
||||
|
||||
--
|
||||
-- Memory copy summary
|
||||
CREATE VIEW
|
||||
`memory_copy_summary` AS
|
||||
WITH
|
||||
avg_data AS (
|
||||
SELECT
|
||||
name,
|
||||
AVG(duration) AS avg_duration
|
||||
FROM
|
||||
`memory_copies`
|
||||
GROUP BY
|
||||
name
|
||||
),
|
||||
aggregated_data AS (
|
||||
SELECT
|
||||
MC.name,
|
||||
COUNT(*) AS calls,
|
||||
SUM(MC.duration) AS total_duration,
|
||||
SUM(CAST(MC.duration AS REAL) * CAST(MC.duration AS REAL)) AS sqr_duration,
|
||||
A.avg_duration AS average_duration,
|
||||
MIN(MC.duration) AS min_duration,
|
||||
MAX(MC.duration) AS max_duration,
|
||||
SUM(
|
||||
CAST((MC.duration - A.avg_duration) AS REAL) * CAST((MC.duration - A.avg_duration) AS REAL)
|
||||
) / (COUNT(*) - 1) AS variance_duration,
|
||||
SQRT(
|
||||
SUM(
|
||||
CAST((MC.duration - A.avg_duration) AS REAL) * CAST((MC.duration - A.avg_duration) AS REAL)
|
||||
) / (COUNT(*) - 1)
|
||||
) AS std_dev_duration
|
||||
FROM
|
||||
`memory_copies` MC
|
||||
JOIN avg_data A ON MC.name = A.name
|
||||
GROUP BY
|
||||
MC.name
|
||||
),
|
||||
total_duration AS (
|
||||
SELECT
|
||||
SUM(total_duration) AS grand_total_duration
|
||||
FROM
|
||||
aggregated_data
|
||||
)
|
||||
SELECT
|
||||
AD.name AS name,
|
||||
AD.calls,
|
||||
AD.total_duration AS "DURATION (nsec)",
|
||||
AD.sqr_duration AS "SQR (nsec)",
|
||||
AD.average_duration AS "AVERAGE (nsec)",
|
||||
(CAST(AD.total_duration AS REAL) / TD.grand_total_duration) * 100 AS "PERCENT (INC)",
|
||||
AD.min_duration AS "MIN (nsec)",
|
||||
AD.max_duration AS "MAX (nsec)",
|
||||
AD.variance_duration AS "VARIANCE",
|
||||
AD.std_dev_duration AS "STD_DEV"
|
||||
FROM
|
||||
aggregated_data AD
|
||||
CROSS JOIN total_duration TD;
|
||||
|
||||
--
|
||||
-- Memory allocation summary
|
||||
CREATE VIEW
|
||||
`memory_allocation_summary` AS
|
||||
WITH
|
||||
avg_data AS (
|
||||
SELECT
|
||||
type AS name,
|
||||
AVG(duration) AS avg_duration
|
||||
FROM
|
||||
`memory_allocations`
|
||||
GROUP BY
|
||||
type
|
||||
),
|
||||
aggregated_data AS (
|
||||
SELECT
|
||||
MA.type AS name,
|
||||
COUNT(*) AS calls,
|
||||
SUM(MA.duration) AS total_duration,
|
||||
SUM(CAST(MA.duration AS REAL) * CAST(MA.duration AS REAL)) AS sqr_duration,
|
||||
A.avg_duration AS average_duration,
|
||||
MIN(MA.duration) AS min_duration,
|
||||
MAX(MA.duration) AS max_duration,
|
||||
SUM(
|
||||
CAST((MA.duration - A.avg_duration) AS REAL) * CAST((MA.duration - A.avg_duration) AS REAL)
|
||||
) / (COUNT(*) - 1) AS variance_duration,
|
||||
SQRT(
|
||||
SUM(
|
||||
CAST((MA.duration - A.avg_duration) AS REAL) * CAST((MA.duration - A.avg_duration) AS REAL)
|
||||
) / (COUNT(*) - 1)
|
||||
) AS std_dev_duration
|
||||
FROM
|
||||
`memory_allocations` MA
|
||||
JOIN avg_data A ON MA.type = A.name
|
||||
GROUP BY
|
||||
MA.type
|
||||
),
|
||||
total_duration AS (
|
||||
SELECT
|
||||
SUM(total_duration) AS grand_total_duration
|
||||
FROM
|
||||
aggregated_data
|
||||
)
|
||||
SELECT
|
||||
'MEMORY_ALLOCATION_' || AD.name AS name,
|
||||
AD.calls,
|
||||
AD.total_duration AS "DURATION (nsec)",
|
||||
AD.sqr_duration AS "SQR (nsec)",
|
||||
AD.average_duration AS "AVERAGE (nsec)",
|
||||
(CAST(AD.total_duration AS REAL) / TD.grand_total_duration) * 100 AS "PERCENT (INC)",
|
||||
AD.min_duration AS "MIN (nsec)",
|
||||
AD.max_duration AS "MAX (nsec)",
|
||||
AD.variance_duration AS "VARIANCE",
|
||||
AD.std_dev_duration AS "STD_DEV"
|
||||
FROM
|
||||
aggregated_data AD
|
||||
CROSS JOIN total_duration TD;
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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 "insert_query_builders.hpp"
|
||||
|
||||
namespace rocprofsys
|
||||
{
|
||||
namespace rocpd
|
||||
{
|
||||
namespace data_storage
|
||||
{
|
||||
namespace queries
|
||||
{
|
||||
|
||||
struct table_insert_query
|
||||
{
|
||||
table_insert_query()
|
||||
: _query_columns_builder{ _ss }
|
||||
{}
|
||||
|
||||
query_builders::query_columns_builder& set_table_name(const std::string& tableName)
|
||||
{
|
||||
_ss.str("");
|
||||
_ss << "INSERT INTO " << tableName << " ";
|
||||
return _query_columns_builder;
|
||||
}
|
||||
|
||||
private:
|
||||
std::stringstream _ss;
|
||||
query_builders::query_columns_builder _query_columns_builder;
|
||||
};
|
||||
|
||||
} // namespace queries
|
||||
} // namespace data_storage
|
||||
} // namespace rocpd
|
||||
} // namespace rocprofsys
|
||||
@@ -0,0 +1,99 @@
|
||||
// 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.
|
||||
|
||||
#include "json.hpp"
|
||||
#include <sstream>
|
||||
|
||||
namespace rocpd
|
||||
{
|
||||
|
||||
std::shared_ptr<json>
|
||||
json::create()
|
||||
{
|
||||
return std::shared_ptr<json>(new json());
|
||||
}
|
||||
|
||||
void
|
||||
json::set(const std::string& key, const json_value& value)
|
||||
{
|
||||
data[key] = std::make_shared<json_value>(value);
|
||||
}
|
||||
|
||||
std::string
|
||||
json::to_string() const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "{";
|
||||
bool first = true;
|
||||
|
||||
for(const auto& [key, value] : data)
|
||||
{
|
||||
if(!first) oss << ", ";
|
||||
first = false;
|
||||
|
||||
oss << "\"" << key << "\": " << stringify(value);
|
||||
}
|
||||
|
||||
oss << "}";
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
std::string
|
||||
json::stringify(const std::shared_ptr<json_value>& value)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
std::visit(
|
||||
[&oss](auto&& arg) {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr(std::is_same_v<T, std::string>)
|
||||
oss << "\"" << arg << "\"";
|
||||
else if constexpr(std::is_same_v<T, bool>)
|
||||
oss << (arg ? "true" : "false");
|
||||
else if constexpr(std::is_same_v<T, std::nullptr_t>)
|
||||
oss << "null";
|
||||
else if constexpr(std::is_same_v<T, std::vector<json>>)
|
||||
{
|
||||
oss << "[";
|
||||
bool first = true;
|
||||
for(const auto& item : arg)
|
||||
{
|
||||
if(!first) oss << ", ";
|
||||
first = false;
|
||||
oss << item.to_string();
|
||||
}
|
||||
oss << "]";
|
||||
}
|
||||
else if constexpr(std::is_same_v<T, std::shared_ptr<json>>)
|
||||
{
|
||||
oss << arg->to_string();
|
||||
}
|
||||
else
|
||||
{
|
||||
// handle int + double
|
||||
oss << arg;
|
||||
}
|
||||
},
|
||||
*value);
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace rocpd
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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 <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace rocpd
|
||||
{
|
||||
|
||||
class json
|
||||
{
|
||||
public:
|
||||
static std::shared_ptr<json> create();
|
||||
|
||||
using json_value =
|
||||
std::variant<std::string, int, double, long long, bool, std::vector<json>,
|
||||
std::nullptr_t, std::shared_ptr<json>>;
|
||||
|
||||
void set(const std::string& key, const json_value& value);
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
private:
|
||||
json() = default;
|
||||
|
||||
private:
|
||||
static std::string stringify(const std::shared_ptr<json_value>& value);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::shared_ptr<json_value>> data;
|
||||
};
|
||||
|
||||
} // namespace rocpd
|
||||
Reference in New Issue
Block a user