From 90accda15252ff24e524623e5e38edb94a7919b0 Mon Sep 17 00:00:00 2001 From: "Jonathan R. Madsen" Date: Wed, 17 Jul 2024 01:07:49 -0500 Subject: [PATCH] Common string entry (#971) * Common string entry * Add lib/common/string_entry.cpp + return const string* --- source/lib/common/CMakeLists.txt | 3 +- source/lib/common/string_entry.cpp | 74 +++++++++++++++++++ source/lib/common/string_entry.hpp | 35 +++++++++ source/lib/rocprofiler-sdk/agent.cpp | 46 +++--------- .../code_object/code_object.cpp | 34 +-------- .../code_object/hsa/code_object.hpp | 2 +- .../code_object/hsa/kernel_symbol.hpp | 2 +- 7 files changed, 125 insertions(+), 71 deletions(-) create mode 100644 source/lib/common/string_entry.cpp create mode 100644 source/lib/common/string_entry.hpp diff --git a/source/lib/common/CMakeLists.txt b/source/lib/common/CMakeLists.txt index e1b5d8ffc2..2769147990 100644 --- a/source/lib/common/CMakeLists.txt +++ b/source/lib/common/CMakeLists.txt @@ -4,7 +4,7 @@ rocprofiler_activate_clang_tidy() set(common_sources demangle.cpp elf_utils.cpp environment.cpp logging.cpp - static_object.cpp utility.cpp) + static_object.cpp string_entry.cpp utility.cpp) set(common_headers abi.hpp defines.hpp @@ -16,6 +16,7 @@ set(common_headers mpl.hpp scope_destructor.hpp static_object.hpp + string_entry.hpp stringize_arg.hpp synchronized.hpp units.hpp diff --git a/source/lib/common/string_entry.cpp b/source/lib/common/string_entry.cpp new file mode 100644 index 0000000000..34dd77a9a3 --- /dev/null +++ b/source/lib/common/string_entry.cpp @@ -0,0 +1,74 @@ +// MIT License +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 "lib/common/string_entry.hpp" +#include "lib/common/scope_destructor.hpp" +#include "lib/common/static_object.hpp" + +#include +#include +#include +#include +#include +#include + +namespace rocprofiler +{ +namespace common +{ +namespace +{ +using name_array_t = std::unordered_map>; + +auto& +get_sync() +{ + static auto*& _v = static_object::construct(); + return *CHECK_NOTNULL(_v); +} + +name_array_t* +get_string_array() +{ + static auto*& _v = static_object::construct(); + return _v; +} +} // namespace + +const std::string* +get_string_entry(std::string_view name) +{ + if(!get_string_array()) return nullptr; + + auto _hash_v = std::hash{}(name); + { + auto _lk = std::shared_lock{get_sync()}; + if(get_string_array()->count(_hash_v) > 0) return get_string_array()->at(_hash_v).get(); + } + + auto _lk = std::unique_lock{get_sync()}; + return get_string_array() + ->emplace(_hash_v, std::make_unique(name)) + .first->second.get(); +} +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/common/string_entry.hpp b/source/lib/common/string_entry.hpp new file mode 100644 index 0000000000..deeb200856 --- /dev/null +++ b/source/lib/common/string_entry.hpp @@ -0,0 +1,35 @@ +// MIT License +// +// Copyright (c) 2023 Advanced Micro Devices, Inc. +// +// 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 +#include + +namespace rocprofiler +{ +namespace common +{ +const std::string* +get_string_entry(std::string_view name); +} // namespace common +} // namespace rocprofiler diff --git a/source/lib/rocprofiler-sdk/agent.cpp b/source/lib/rocprofiler-sdk/agent.cpp index 7a969c855c..b1951e2c19 100644 --- a/source/lib/rocprofiler-sdk/agent.cpp +++ b/source/lib/rocprofiler-sdk/agent.cpp @@ -28,6 +28,7 @@ #include "lib/common/logging.hpp" #include "lib/common/scope_destructor.hpp" #include "lib/common/static_object.hpp" +#include "lib/common/string_entry.hpp" #include "lib/common/utility.hpp" #include "lib/rocprofiler-sdk/agent.hpp" #include "lib/rocprofiler-sdk/hsa/agent_cache.hpp" @@ -60,36 +61,6 @@ namespace { namespace fs = ::rocprofiler::common::filesystem; -using name_array_t = std::vector>>; - -name_array_t* -get_string_array() -{ - static auto*& _v = common::static_object::construct(); - return _v; -} - -std::string* -get_string_entry(std::string_view name) -{ - auto _hash_v = std::hash{}(name); - static auto _sync = std::shared_mutex{}; - if(!get_string_array()) return nullptr; - - { - auto _unlock = common::scope_destructor{[]() { _sync.unlock_shared(); }}; - _sync.lock_shared(); - for(const auto& itr : *get_string_array()) - if(itr.first == _hash_v) return itr.second.get(); - } - - auto _unlock = common::scope_destructor{[]() { _sync.unlock(); }}; - _sync.lock(); - return get_string_array() - ->emplace_back(std::make_pair(_hash_v, std::make_unique(name))) - .second.get(); -} - uint64_t get_agent_offset() { @@ -410,7 +381,7 @@ read_topology() if(!name_prop.empty()) agent_info.model_name = - get_string_entry(fmt::format("{}", fmt::join(name_prop, " ")))->c_str(); + common::get_string_entry(fmt::format("{}", fmt::join(name_prop, " ")))->c_str(); else agent_info.model_name = ""; @@ -497,10 +468,11 @@ read_topology() auto step = (agent_info.gfx_target_version % 100); agent_info.name = - get_string_entry(fmt::format("gfx{}{}{:x}", major, minor, step))->c_str(); + common::get_string_entry(fmt::format("gfx{}{}{:x}", major, minor, step)) + ->c_str(); agent_info.product_name = - get_string_entry(amdgpu_get_marketing_name(device_handle))->c_str(); - agent_info.vendor_name = get_string_entry("AMD")->c_str(); + common::get_string_entry(amdgpu_get_marketing_name(device_handle))->c_str(); + agent_info.vendor_name = common::get_string_entry("AMD")->c_str(); amdgpu_gpu_info gpu_info = {}; if(amdgpu_query_gpu_info(device_handle, &gpu_info) == 0) @@ -515,13 +487,13 @@ read_topology() else if(agent_info.type == ROCPROFILER_AGENT_TYPE_CPU) { agent_info.cu_count = agent_info.cpu_cores_count; - agent_info.vendor_name = get_string_entry("CPU")->c_str(); + agent_info.vendor_name = common::get_string_entry("CPU")->c_str(); for(const auto& itr : cpu_info_v) { if(agent_info.cpu_core_id_base == itr.apicid) { - agent_info.name = get_string_entry(itr.model_name)->c_str(); - agent_info.product_name = get_string_entry(agent_info.name)->c_str(); + agent_info.name = common::get_string_entry(itr.model_name)->c_str(); + agent_info.product_name = common::get_string_entry(agent_info.name)->c_str(); agent_info.family_id = itr.family; break; } diff --git a/source/lib/rocprofiler-sdk/code_object/code_object.cpp b/source/lib/rocprofiler-sdk/code_object/code_object.cpp index 8a42f95bde..a3a9a57737 100644 --- a/source/lib/rocprofiler-sdk/code_object/code_object.cpp +++ b/source/lib/rocprofiler-sdk/code_object/code_object.cpp @@ -23,6 +23,7 @@ #include "lib/rocprofiler-sdk/code_object/code_object.hpp" #include "lib/common/scope_destructor.hpp" #include "lib/common/static_object.hpp" +#include "lib/common/string_entry.hpp" #include "lib/common/synchronized.hpp" #include "lib/common/utility.hpp" #include "lib/rocprofiler-sdk/agent.hpp" @@ -158,7 +159,6 @@ using context_t = context::context; using user_data_t = rocprofiler_user_data_t; using context_array_t = context::context_array_t; using context_user_data_map_t = std::unordered_map; -using name_array_t = std::vector>>; using amd_compute_pgm_rsrc_three32_t = uint32_t; struct kernel_descriptor_t @@ -296,34 +296,6 @@ sgpr_count(std::string_view name, kernel_descriptor_t kernel_code) return 0; } -name_array_t* -get_string_array() -{ - static auto*& _v = common::static_object::construct(); - return _v; -} - -std::string* -get_string_entry(std::string_view name) -{ - auto _hash_v = std::hash{}(name); - static auto _sync = std::shared_mutex{}; - if(!get_string_array()) return nullptr; - - { - auto _unlock = common::scope_destructor{[]() { _sync.unlock_shared(); }}; - _sync.lock_shared(); - for(const auto& itr : *get_string_array()) - if(itr.first == _hash_v) return itr.second.get(); - } - - auto _unlock = common::scope_destructor{[]() { _sync.unlock(); }}; - _sync.lock(); - return get_string_array() - ->emplace_back(std::make_pair(_hash_v, std::make_unique(name))) - .second.get(); -} - hsa_loader_table_t& get_loader_table() { @@ -472,7 +444,7 @@ executable_iterate_agent_symbols_load_callback(hsa_executable_t executabl auto _name = std::string(_name_length + 1, '\0'); ROCP_HSA_CORE_GET_EXE_SYMBOL_INFO(HSA_EXECUTABLE_SYMBOL_INFO_NAME, _name.data()); - symbol_v.name = get_string_entry(_name.substr(0, _name.find_first_of('\0'))); + symbol_v.name = common::get_string_entry(_name.substr(0, _name.find_first_of('\0'))); } data.kernel_name = (symbol_v.name) ? symbol_v.name->c_str() : nullptr; @@ -648,7 +620,7 @@ code_object_load_callback(hsa_executable_t executable, ROCP_HSA_VEN_LOADER_GET_CODE_OBJECT_INFO(HSA_VEN_AMD_LOADER_LOADED_CODE_OBJECT_INFO_URI, _uri.data()); - code_obj_v.uri = get_string_entry(_uri); + code_obj_v.uri = common::get_string_entry(_uri); } data.uri = (code_obj_v.uri) ? code_obj_v.uri->data() : nullptr; diff --git a/source/lib/rocprofiler-sdk/code_object/hsa/code_object.hpp b/source/lib/rocprofiler-sdk/code_object/hsa/code_object.hpp index 87e5348f92..3ff4b1d2cf 100644 --- a/source/lib/rocprofiler-sdk/code_object/hsa/code_object.hpp +++ b/source/lib/rocprofiler-sdk/code_object/hsa/code_object.hpp @@ -61,7 +61,7 @@ struct code_object bool beg_notified = false; bool end_notified = false; - std::string* uri = {}; + const std::string* uri = nullptr; hsa_executable_t hsa_executable = {}; hsa_loaded_code_object_t hsa_code_object = {}; code_object_data_t rocp_data = common::init_public_api_struct(code_object_data_t{}); diff --git a/source/lib/rocprofiler-sdk/code_object/hsa/kernel_symbol.hpp b/source/lib/rocprofiler-sdk/code_object/hsa/kernel_symbol.hpp index c6c9947bb1..8c1a239ccd 100644 --- a/source/lib/rocprofiler-sdk/code_object/hsa/kernel_symbol.hpp +++ b/source/lib/rocprofiler-sdk/code_object/hsa/kernel_symbol.hpp @@ -60,7 +60,7 @@ struct kernel_symbol bool beg_notified = false; bool end_notified = false; - std::string* name = {}; + const std::string* name = nullptr; hsa_executable_t hsa_executable = {}; hsa_agent_t hsa_agent = {}; hsa_executable_symbol_t hsa_symbol = {};