SWDEV-465322: Adding support for Perfcounter SIMD Mask in ATT (#910)

* SWDEV-465322: Adding support for r Perfcounter SIMD Mask in ATT

* Apply suggestions from code review

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Welton <bewelton@amd.com>

* Adding unit tests

* Adding counters check for gfx9 and SQ block only

* Addressing review comments

* changing the struct size

* fixing header includes

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Welton <bewelton@amd.com>
Αυτή η υποβολή περιλαμβάνεται σε:
Manjunath P Jakaraddi
2024-06-12 16:25:06 -07:00
υποβλήθηκε από GitHub
γονέας cfe3af9d7e
υποβολή c49719649b
12 αρχεία άλλαξαν με 227 προσθήκες και 43 διαγραφές
@@ -26,6 +26,7 @@
#include <rocprofiler-sdk/defines.h>
#include <rocprofiler-sdk/fwd.h>
#include <rocprofiler-sdk/hsa.h>
#include <cstdint>
ROCPROFILER_EXTERN_C_INIT
@@ -43,13 +44,23 @@ typedef enum
ROCPROFILER_ATT_PARAMETER_BUFFER_SIZE, ///< Size of combined GPU buffer for ATT
ROCPROFILER_ATT_PARAMETER_SIMD_SELECT, ///< Bitmask (GFX9) or ID (Navi) of SIMDs
ROCPROFILER_ATT_PARAMETER_CODE_OBJECT_TRACE_ENABLE, ///< Enables Codeobj Markers IDs into ATT
ROCPROFILER_ATT_PARAMETER_PERFCOUNTER, ///< Enables Perfcounter with simd mask (GFX9 only)
ROCPROFILER_ATT_PARAMETER_PERFCOUNTERS_CTRL, ///< Defines the update period (GFX9 only)
ROCPROFILER_ATT_PARAMETER_LAST
} rocprofiler_att_parameter_type_t;
typedef struct
{
rocprofiler_att_parameter_type_t type;
uint64_t value;
union
{
uint64_t value;
struct
{
rocprofiler_counter_id_t counter_id;
uint64_t simd_mask : 4;
};
};
} rocprofiler_att_parameter_t;
typedef enum
@@ -216,20 +216,34 @@ ThreadTraceAQLPacketFactory::ThreadTraceAQLPacketFactory(const hsa::AgentCache&
uint32_t shader_engine_mask = static_cast<uint32_t>(params.shader_engine_mask);
uint32_t simd = static_cast<uint32_t>(params.simd_select);
uint32_t buffer_size = static_cast<uint32_t>(params.buffer_size);
uint32_t perf_ctrl = static_cast<uint32_t>(params.perfcounter_ctrl);
aql_params.clear();
aql_params.push_back({HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_COMPUTE_UNIT_TARGET, cu});
aql_params.push_back({HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SE_MASK, shader_engine_mask});
aql_params.push_back({HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SIMD_SELECTION, simd});
aql_params.push_back({HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_ATT_BUFFER_SIZE, buffer_size});
aql_params.push_back({HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_PERFCOUNTER_CTRL, perf_ctrl});
for(uint32_t perf_counter : params.perfcounters)
{
aql_params.push_back(
{HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_PERFCOUNTER_NAME, perf_counter});
}
}
const std::vector<hsa_ven_amd_aqlprofile_parameter_t>&
ThreadTraceAQLPacketFactory::get_aql_params()
{
return aql_params;
}
std::unique_ptr<hsa::TraceControlAQLPacket>
ThreadTraceAQLPacketFactory::construct_packet()
{
uint32_t num_params = static_cast<uint32_t>(aql_params.size());
auto profile = aqlprofile_att_profile_t{tracepool.gpu_agent, aql_params.data(), num_params};
auto packet = std::make_unique<hsa::TraceControlAQLPacket>(this->tracepool, profile);
uint32_t num_params = static_cast<uint32_t>(get_aql_params().size());
auto profile =
aqlprofile_att_profile_t{tracepool.gpu_agent, get_aql_params().data(), num_params};
auto packet = std::make_unique<hsa::TraceControlAQLPacket>(this->tracepool, profile);
packet->clear();
return packet;
}
@@ -91,10 +91,11 @@ public:
const thread_trace_parameter_pack& params,
const CoreApiTable& coreapi,
const AmdExtTable& ext);
std::unique_ptr<hsa::TraceControlAQLPacket> construct_packet();
std::unique_ptr<hsa::CodeobjMarkerAQLPacket> construct_load_marker_packet(uint64_t id,
uint64_t addr,
uint64_t size);
const std::vector<hsa_ven_amd_aqlprofile_parameter_t>& get_aql_params();
std::unique_ptr<hsa::TraceControlAQLPacket> construct_packet();
std::unique_ptr<hsa::CodeobjMarkerAQLPacket> construct_load_marker_packet(uint64_t id,
uint64_t addr,
uint64_t size);
std::unique_ptr<hsa::CodeobjMarkerAQLPacket> construct_unload_marker_packet(uint64_t id);
private:
@@ -195,6 +195,26 @@ getMetricIdMap()
return id_map;
}
const MetricIdMap*
getPerfCountersIdMap()
{
// Only GFX9 counters in SQ Block are supported
static MetricIdMap*& att_perf_counters_map =
common::static_object<MetricIdMap>::construct([]() {
MetricIdMap map;
std::string agent_prefix{"gfx9"};
auto is_gfx9 = [&](auto& agent_name) {
return (agent_name.find(agent_prefix) != std::string::npos);
};
for(const auto& [agent_name, metrics] : *CHECK_NOTNULL(getMetricMap()))
if(is_gfx9(agent_name))
for(const auto& metric : metrics)
if(metric.block() == "SQ") map.emplace(metric.id(), metric);
return map;
}());
return att_perf_counters_map;
}
const MetricMap*
getMetricMap()
{
@@ -114,6 +114,13 @@ getMetricsForAgent(const std::string&);
const MetricIdMap*
getMetricIdMap();
/**
* Get the metrics for perfcounters options in thread trace
* applicable only for GFX9 agents and SQ block counters
*/
const MetricIdMap*
getPerfCountersIdMap();
/**
* Checks if a metric is valid for a given agent
**/
@@ -55,11 +55,13 @@ struct thread_trace_parameter_pack
uint64_t buffer_size = DEFAULT_BUFFER_SIZE;
// GFX9 Only
std::vector<std::string> perfcounters;
std::vector<uint32_t> perfcounters;
static constexpr size_t DEFAULT_SIMD = 0x7;
static constexpr size_t DEFAULT_SE_MASK = 0x21;
static constexpr size_t DEFAULT_BUFFER_SIZE = 0x8000000;
static constexpr size_t DEFAULT_SIMD = 0x7;
static constexpr size_t DEFAULT_PERFCOUNTER_SIMD_MASK = 0xF;
static constexpr size_t DEFAULT_SE_MASK = 0x21;
static constexpr size_t DEFAULT_BUFFER_SIZE = 0x8000000;
static constexpr size_t PERFCOUNTER_SIMD_MASK_SHIFT = 28;
};
namespace hsa
@@ -20,12 +20,28 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <glog/logging.h>
#include <rocprofiler-sdk/rocprofiler.h>
#include <cstdint>
#include "lib/rocprofiler-sdk/aql/helpers.hpp"
#include "lib/rocprofiler-sdk/context/context.hpp"
#include "lib/rocprofiler-sdk/hsa/agent_cache.hpp"
#include "lib/rocprofiler-sdk/registration.hpp"
#include "rocprofiler-sdk/amd_detail/thread_trace.h"
namespace
{
uint32_t
get_mask(const rocprofiler::counters::Metric* metric, uint64_t simds_selected)
{
uint32_t mask = std::atoi(metric->event().c_str());
if(simds_selected == 0)
simds_selected = rocprofiler::thread_trace_parameter_pack::DEFAULT_PERFCOUNTER_SIMD_MASK;
mask |= simds_selected << rocprofiler::thread_trace_parameter_pack::PERFCOUNTER_SIMD_MASK_SHIFT;
return mask;
}
} // namespace
extern "C" {
rocprofiler_status_t ROCPROFILER_API
@@ -51,6 +67,7 @@ rocprofiler_configure_thread_trace_service(rocprofiler_context_id_t
param_pack.callback_userdata = callback_userdata;
bool bEnableCodeobj = false;
const auto& id_map = *CHECK_NOTNULL(rocprofiler::counters::getPerfCountersIdMap());
for(size_t p = 0; p < num_parameters; p++)
{
const rocprofiler_att_parameter_t& param = parameters[p];
@@ -68,10 +85,16 @@ rocprofiler_configure_thread_trace_service(rocprofiler_context_id_t
case ROCPROFILER_ATT_PARAMETER_CODE_OBJECT_TRACE_ENABLE:
bEnableCodeobj = param.value != 0;
break;
case ROCPROFILER_ATT_PARAMETER_PERFCOUNTER:
if(const auto* metric_ptr =
rocprofiler::common::get_val(id_map, param.counter_id.handle))
param_pack.perfcounters.push_back(get_mask(metric_ptr, param.simd_mask));
break;
case ROCPROFILER_ATT_PARAMETER_PERFCOUNTERS_CTRL:
param_pack.perfcounter_ctrl = param.value;
break;
case ROCPROFILER_ATT_PARAMETER_LAST: return ROCPROFILER_STATUS_ERROR_INVALID_ARGUMENT;
}
// for(int i = 0; i < parameters.perfcounter_num; i++)
// thread_tracer->perfcounters.emplace_back(parameters.perfcounter[i]);
}
ctx->thread_trace = std::make_shared<rocprofiler::GlobalThreadTracer>(param_pack);
@@ -20,15 +20,28 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include "lib/rocprofiler-sdk/agent.hpp"
#include "lib/rocprofiler-sdk/aql/helpers.hpp"
#include "lib/rocprofiler-sdk/aql/packet_construct.hpp"
#include "lib/rocprofiler-sdk/context/context.hpp"
#include "lib/rocprofiler-sdk/counters/metrics.hpp"
#include "lib/rocprofiler-sdk/counters/tests/hsa_tables.hpp"
#include "lib/rocprofiler-sdk/hsa/agent_cache.hpp"
#include "lib/rocprofiler-sdk/hsa/queue.hpp"
#include "lib/rocprofiler-sdk/hsa/queue_controller.hpp"
#include "lib/rocprofiler-sdk/registration.hpp"
#include "lib/rocprofiler-sdk/thread_trace/att_core.hpp"
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <algorithm>
#include <cstdint>
#include <functional>
#include <map>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <hsa/hsa.h>
#include <hsa/hsa_api_trace.h>
#include <hsa/hsa_ven_amd_aqlprofile.h>
@@ -127,10 +140,10 @@ TEST(thread_trace, configure_test)
ROCPROFILER_CALL(rocprofiler_create_context(&ctx), "context creation failed");
std::vector<rocprofiler_att_parameter_t> params;
params.push_back({ROCPROFILER_ATT_PARAMETER_TARGET_CU, 1});
params.push_back({ROCPROFILER_ATT_PARAMETER_SHADER_ENGINE_MASK, 0xF});
params.push_back({ROCPROFILER_ATT_PARAMETER_BUFFER_SIZE, 0x1000000});
params.push_back({ROCPROFILER_ATT_PARAMETER_SIMD_SELECT, 0xF});
params.push_back({ROCPROFILER_ATT_PARAMETER_TARGET_CU, {1}});
params.push_back({ROCPROFILER_ATT_PARAMETER_SHADER_ENGINE_MASK, {0xF}});
params.push_back({ROCPROFILER_ATT_PARAMETER_BUFFER_SIZE, {0x1000000}});
params.push_back({ROCPROFILER_ATT_PARAMETER_SIMD_SELECT, {0xF}});
rocprofiler_configure_thread_trace_service(
ctx,
@@ -147,5 +160,88 @@ TEST(thread_trace, configure_test)
ASSERT_EQ(hsa_init(), HSA_STATUS_SUCCESS);
ROCPROFILER_CALL(rocprofiler_start_context(ctx), "context start failed");
ROCPROFILER_CALL(rocprofiler_stop_context(ctx), "context stop failed");
context::pop_client(1);
hsa_shut_down();
}
TEST(thread_trace, perfcounters_configure_test)
{
test_init();
registration::init_logging();
registration::set_init_status(-1);
context::push_client(1);
rocprofiler_context_id_t ctx;
ROCPROFILER_CALL(rocprofiler_create_context(&ctx), "context creation failed");
// Only GFX9 SQ Block counters are supported
std::vector<std::pair<std::string, uint64_t>> perf_counters = {
{"SQ_WAVES", 0x1}, {"SQ_WAVES", 0x2}, {"SQ_WAVES", 0x2}, {"GRBM_COUNT", 0x3}};
std::set<uint32_t> expected;
std::vector<rocprofiler_att_parameter_t> params;
params.push_back({ROCPROFILER_ATT_PARAMETER_PERFCOUNTERS_CTRL, {1}});
auto metrics = rocprofiler::counters::getMetricsForAgent("gfx90a");
for(auto& [counter_name, simd_mask] : perf_counters)
for(auto& metric : metrics)
if(metric.name() == counter_name)
{
params.push_back({ROCPROFILER_ATT_PARAMETER_PERFCOUNTER,
{.counter_id = {metric.id()}, .simd_mask = simd_mask}});
expected.insert(std::atoi(metric.event().c_str()) | (simd_mask << 28));
}
rocprofiler_configure_thread_trace_service(
ctx,
params.data(),
params.size(),
[](rocprofiler_queue_id_t,
const rocprofiler_agent_t*,
rocprofiler_correlation_id_t,
rocprofiler_kernel_id_t,
void*) { return ROCPROFILER_ATT_CONTROL_NONE; },
[](int64_t, void*, size_t, void*) {},
nullptr);
auto* context = rocprofiler::context::get_mutable_registered_context(ctx);
thread_trace_parameter_pack _params = context->thread_trace->params;
ASSERT_EQ(_params.perfcounter_ctrl, 1);
ASSERT_EQ(_params.perfcounters.size(), 3);
for(uint32_t param : _params.perfcounters)
EXPECT_TRUE(expected.find(param) != expected.end())
<< "valid AQLprofile mask not generated for perfcounters";
context::pop_client(1);
hsa_shut_down();
}
TEST(thread_trace, perfcounters_aql_options_test)
{
hsa_init();
test_init();
registration::init_logging();
registration::set_init_status(-1);
context::push_client(1);
const std::uint8_t sqtt_default_num_options = 5;
auto agents = hsa::get_queue_controller()->get_supported_agents();
thread_trace_parameter_pack _params = {};
auto metrics = rocprofiler::counters::getMetricsForAgent("gfx90a");
std::vector<std::pair<std::string, uint64_t>> perf_counters = {
{"SQ_WAVES", 0x1}, {"SQ_WAVES", 0x2}, {"GRBM_COUNT", 0x3}};
for(auto& [counter_name, simd_mask] : perf_counters)
for(auto& metric : metrics)
if(metric.name() == counter_name)
_params.perfcounters.push_back(std::atoi(metric.event().c_str()) |
(simd_mask << 28));
_params.perfcounter_ctrl = 2;
auto new_tracer = std::make_unique<AgentThreadTracer>(
_params, begin(agents)->second, get_api_table(), get_ext_table());
ASSERT_EQ(new_tracer->factory->get_aql_params().size(),
sqtt_default_num_options + perf_counters.size());
context::pop_client(1);
hsa_shut_down();
}