diff --git a/Readme.txt b/Readme.txt index 6ab4a3bc82..e6a1f46111 100644 --- a/Readme.txt +++ b/Readme.txt @@ -1,5 +1,5 @@ ROC Profiler library. -Profiling with metrics and traces based on perfcounters (PMC) and SQ threadtraces (SQTT). +Profiling with metrics and traces based on perfcounters (PMC) and traces (SQTT, PMC). Implementation is based on AqlProfile HSA extension. Library supports GFX8/GFX9. diff --git a/cmake_modules/env.cmake b/cmake_modules/env.cmake index 6bf6ed4545..44fb0cd0c8 100644 --- a/cmake_modules/env.cmake +++ b/cmake_modules/env.cmake @@ -56,6 +56,8 @@ set ( CMAKE_SHARED_LINKER_FLAGS "-Wl,-Bdynamic -Wl,-z,noexecstack" ) set ( CMAKE_SKIP_BUILD_RPATH TRUE ) +add_definitions ( -DNEW_TRACE_API=1 ) + ## CLANG options if ( "$ENV{CXX}" STREQUAL "/usr/bin/clang++" ) set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ferror-limit=1000000" ) diff --git a/inc/rocprofiler.h b/inc/rocprofiler.h index 1e74c46499..fc723c5d32 100644 --- a/inc/rocprofiler.h +++ b/inc/rocprofiler.h @@ -27,8 +27,7 @@ THE SOFTWARE. // The goal of the implementation is to provide a HW specific low-level // performance analysis interface for profiling of GPU compute applications. // The profiling includes HW performance counters (PMC) with complex -// performance metrics and thread traces (SQTT). The profiling is supported -// by the SQTT, PMC and Callback APIs. +// performance metrics and traces: SQTT, SPM. // // The library can be used by a tool library loaded by HSA runtime or by // higher level HW independent performance analysis API like PAPI. @@ -66,8 +65,8 @@ uint32_t rocprofiler_version_minor(); typedef struct { uint32_t intercept_mode; uint32_t memcopy_tracking; - uint32_t sqtt_size; - uint32_t sqtt_local; + uint32_t trace_size; + uint32_t trace_local; uint64_t timeout; uint32_t timestamp_on; } rocprofiler_settings_t; diff --git a/src/core/context.h b/src/core/context.h index a59effd0d3..38a58262e7 100644 --- a/src/core/context.h +++ b/src/core/context.h @@ -83,7 +83,7 @@ class Group { Group(const util::AgentInfo* agent_info, Context* context, const uint32_t& index) : pmc_profile_(agent_info), - sqtt_profile_(agent_info), + trace_profile_(agent_info), n_profiles_(0), refs_(1), context_(context), @@ -97,7 +97,7 @@ class Group { pmc_profile_.Insert(info); break; case ROCPROFILER_FEATURE_KIND_TRACE: - sqtt_profile_.Insert(info); + trace_profile_.Insert(info); break; default: EXC_RAISING(HSA_STATUS_ERROR, "bad rocprofiler feature kind (" << kind << ")"); @@ -107,21 +107,21 @@ class Group { hsa_status_t Finalize() { hsa_status_t status = pmc_profile_.Finalize(start_vector_, stop_vector_, read_vector_); if (status == HSA_STATUS_SUCCESS) { - status = sqtt_profile_.Finalize(start_vector_, stop_vector_, read_vector_); + status = trace_profile_.Finalize(start_vector_, stop_vector_, read_vector_); } if (status == HSA_STATUS_SUCCESS) { if (!pmc_profile_.Empty()) ++n_profiles_; - if (!sqtt_profile_.Empty()) ++n_profiles_; + if (!trace_profile_.Empty()) ++n_profiles_; } return status; } void GetProfiles(profile_vector_t& vec) { pmc_profile_.GetProfiles(vec); - sqtt_profile_.GetProfiles(vec); + trace_profile_.GetProfiles(vec); } - void GetTraceProfiles(profile_vector_t& vec) { sqtt_profile_.GetProfiles(vec); } + void GetTraceProfiles(profile_vector_t& vec) { trace_profile_.GetProfiles(vec); } info_vector_t& GetInfoVector() { return info_vector_; } const pkt_vector_t& GetStartVector() const { return start_vector_; } @@ -137,7 +137,7 @@ class Group { private: PmcProfile pmc_profile_; - SqttProfile sqtt_profile_; + TraceProfile trace_profile_; info_vector_t info_vector_; pkt_vector_t start_vector_; pkt_vector_t stop_vector_; @@ -361,9 +361,9 @@ class Context { rocprofiler_feature_t* info = &info_array[i]; const rocprofiler_feature_kind_t kind = info->kind; const char* name = info->name; - if (!name) EXC_RAISING(HSA_STATUS_ERROR, "input feature name is NULL"); - info_map_[name] = info; if (kind == ROCPROFILER_FEATURE_KIND_METRIC) { + if (name == NULL) EXC_RAISING(HSA_STATUS_ERROR, "metric name is NULL"); + info_map_[name] = info; auto ret = metrics_map_.insert({name, NULL}); if (!ret.second) EXC_RAISING(HSA_STATUS_ERROR, "input metric '" << name @@ -435,7 +435,19 @@ class Context { set_[group_index].Insert(profile_info_t{event, NULL, 0, info}); } } else if (kind == ROCPROFILER_FEATURE_KIND_TRACE) { // Processing traces features - set_[0].Insert(profile_info_t{NULL, info->parameters, info->parameter_count, info}); + if (name != NULL) { + const Metric* metric = metrics_->Get(name); + if (metric == NULL) + EXC_RAISING(HSA_STATUS_ERROR, "input metric '" << name << "' is not found"); + counters_vec_t counters_vec = metric->GetCounters(); + if (counters_vec.size() != 1) + EXC_RAISING(HSA_STATUS_ERROR, "trace bad metric '" << name << "' is not base counter"); + const counter_t* counter = counters_vec[0]; + const event_t* event = &(counter->event); + set_[0].Insert(profile_info_t{event, NULL, 0, info}); + } else { + set_[0].Insert(profile_info_t{NULL, info->parameters, info->parameter_count, info}); + } } else { EXC_RAISING(HSA_STATUS_ERROR, "bad rocprofiler feature kind (" << kind << ")"); } @@ -484,15 +496,15 @@ class Context { if (ainfo_data->sample_id == 0) rinfo->data.result_int64 = 0; rinfo->data.result_int64 += ainfo_data->pmc_data.result; rinfo->data.kind = ROCPROFILER_DATA_KIND_INT64; - } else if (ainfo_type == HSA_VEN_AMD_AQLPROFILE_INFO_SQTT_DATA) { + } else if (ainfo_type == HSA_VEN_AMD_AQLPROFILE_INFO_TRACE_DATA) { if (rinfo->data.result_bytes.copy) { - const bool sqtt_local = SqttProfile::IsLocal(); + const bool trace_local = TraceProfile::IsLocal(); util::HsaRsrcFactory* hsa_rsrc = &util::HsaRsrcFactory::Instance(); if (sample_id == 0) { const uint32_t output_buffer_size = profile->output_buffer.size; const uint32_t output_buffer_size64 = profile->output_buffer.size / sizeof(uint64_t); const util::AgentInfo* agent_info = hsa_rsrc->GetAgentInfo(profile->agent); - void* ptr = (sqtt_local) ? hsa_rsrc->AllocateSysMemory(agent_info, output_buffer_size) : + void* ptr = (trace_local) ? hsa_rsrc->AllocateSysMemory(agent_info, output_buffer_size) : calloc(output_buffer_size64, sizeof(uint64_t)); rinfo->data.result_bytes.size = output_buffer_size; rinfo->data.result_bytes.ptr = ptr; @@ -500,19 +512,19 @@ class Context { } char* result_bytes_ptr = reinterpret_cast(rinfo->data.result_bytes.ptr); const char* end = result_bytes_ptr + rinfo->data.result_bytes.size; - const char* src = reinterpret_cast(ainfo_data->sqtt_data.ptr); - uint32_t size = ainfo_data->sqtt_data.size; + const char* src = reinterpret_cast(ainfo_data->trace_data.ptr); + uint32_t size = ainfo_data->trace_data.size; char* ptr = callback_data->ptr; uint32_t* header = reinterpret_cast(ptr); char* dest = ptr + sizeof(*header); if ((dest + size) >= end) { if (dest < end) size = end - dest; - else EXC_RAISING(HSA_STATUS_ERROR, "SQTT data out of output buffer"); + else EXC_RAISING(HSA_STATUS_ERROR, "Trace data out of output buffer"); } bool suc = true; - if (sqtt_local) { + if (trace_local) { suc = hsa_rsrc->Memcpy(profile->agent, dest, src, size); } else { memcpy(dest, src, size); diff --git a/src/core/profile.h b/src/core/profile.h index 6d91192b3b..3658ebb0bf 100644 --- a/src/core/profile.h +++ b/src/core/profile.h @@ -236,19 +236,22 @@ class PmcProfile : public Profile { } }; -class SqttProfile : public Profile { +class TraceProfile : public Profile { public: static inline void SetSize(const uint32_t& size) { output_buffer_size_ = size; } static inline uint32_t GetSize() { return output_buffer_size_; } static inline void SetLocal(const bool& b) { output_buffer_local_ = b; } static inline bool IsLocal() { return output_buffer_local_; } - SqttProfile(const util::AgentInfo* agent_info) : Profile(agent_info) { - profile_.type = HSA_VEN_AMD_AQLPROFILE_EVENT_TYPE_SQTT; + TraceProfile(const util::AgentInfo* agent_info) : Profile(agent_info) { + profile_.type = HSA_VEN_AMD_AQLPROFILE_EVENT_TYPE_TRACE; } void Insert(const profile_info_t& info) { Profile::Insert(info); + if (info.event != NULL) { + Config(&profile_).Insert(*(info.event)); + } for (unsigned j = 0; j < info.parameter_count; ++j) { Config(&profile_).Insert(info.parameters[j]); } diff --git a/src/core/rocprofiler.cpp b/src/core/rocprofiler.cpp index 81e146a003..090e549286 100644 --- a/src/core/rocprofiler.cpp +++ b/src/core/rocprofiler.cpp @@ -175,16 +175,16 @@ uint32_t LoadTool() { rocprofiler_settings_t settings{}; settings.intercept_mode = (intercept_mode != 0) ? 1 : 0; - settings.sqtt_size = SqttProfile::GetSize(); - settings.sqtt_local = SqttProfile::IsLocal() ? 1: 0; + settings.trace_size = TraceProfile::GetSize(); + settings.trace_local = TraceProfile::IsLocal() ? 1: 0; settings.timeout = util::HsaRsrcFactory::GetTimeoutNs(); settings.timestamp_on = InterceptQueue::IsTrackerOn() ? 1 : 0; if (handler) handler(); else if (handler_prop) handler_prop(&settings); - SqttProfile::SetSize(settings.sqtt_size); - SqttProfile::SetLocal(settings.sqtt_local != 0); + TraceProfile::SetSize(settings.trace_size); + TraceProfile::SetLocal(settings.trace_local != 0); util::HsaRsrcFactory::SetTimeoutNs(settings.timeout); InterceptQueue::TrackerOn(settings.timestamp_on != 0); if (settings.intercept_mode != 0) intercept_mode = DISPATCH_INTERCEPT_MODE; @@ -384,8 +384,8 @@ hsa_status_t hsa_amd_memory_async_copy_rect_interceptor( } rocprofiler_properties_t rocprofiler_properties; -uint32_t SqttProfile::output_buffer_size_ = 0x2000000; // 32M -bool SqttProfile::output_buffer_local_ = true; +uint32_t TraceProfile::output_buffer_size_ = 0x2000000; // 32M +bool TraceProfile::output_buffer_local_ = true; std::atomic Tracker::instance_{}; Tracker::mutex_t Tracker::glob_mutex_; Tracker::counter_t Tracker::counter_ = 0; diff --git a/src/core/types.h b/src/core/types.h index ef8600f0a7..c72bb34302 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -23,6 +23,8 @@ THE SOFTWARE. #ifndef SRC_CORE_TYPES_H_ #define SRC_CORE_TYPES_H_ +#include + #include namespace rocprofiler { @@ -33,6 +35,16 @@ typedef hsa_ven_amd_aqlprofile_profile_t profile_t; typedef hsa_ext_amd_aql_pm4_packet_t packet_t; typedef uint32_t packet_word_t; typedef uint64_t timestamp_t; + +inline std::ostream& operator<< (std::ostream& out, const event_t& event) { + out << "[block_name(" << event.block_name << "). block_index(" << event.block_index << "). counter_id(" << event.counter_id << ")]"; + return out; +} +inline std::ostream& operator<< (std::ostream& out, const parameter_t& parameter) { + out << "[parameter_name(" << parameter.parameter_name << "). value(" << parameter.value << ")]"; + return out; +} + } // namespace rocprofiler #endif // SRC_CORE_TYPES_H_ diff --git a/test/run.sh b/test/run.sh index ed5bbe9afd..44d78e14e5 100755 --- a/test/run.sh +++ b/test/run.sh @@ -22,21 +22,31 @@ # THE SOFTWARE. ################################################################################ +test_filter=-1 +if [ -n "$1" ] ; then + test_filter=$1 +fi + # test check routin test_status=0 test_number=0 +xeval_test() { + test_number=$test_number +} eval_test() { label=$1 cmdline=$2 - echo "$label: \"$cmdline\"" - eval "$cmdline" - if [ $? != 0 ] ; then - echo "$label: FAILED" - test_status=$(($test_status + 1)) - else - echo "$label: PASSED" + if [ $test_filter = -1 -o $test_filter = $test_number ] ; then + echo "$label: \"$cmdline\"" + eval "$cmdline" + if [ $? != 0 ] ; then + echo "$label: FAILED" + test_status=$(($test_status + 1)) + else + echo "$label: PASSED" + fi fi - test_number=$(($test_number + 1)) + test_number=$((test_number + 1)) } # enable tools load failure reporting @@ -97,6 +107,15 @@ export ROCP_THRS=10 export ROCP_INPUT=input1.xml eval_test "'rocprof' libtool test n-threads" ./test/ctrl +## SPM test + +export ROCP_KITER=1 +export ROCP_DITER=1 +export ROCP_AGENTS=1 +export ROCP_THRS=1 +export ROCP_INPUT=spm_input.xml +xeval_test "libtool test, SPM trace test" ./test/ctrl + ## Libtool test, counter sets # Memcopies tracking diff --git a/test/tool/spm_input.xml b/test/tool/spm_input.xml new file mode 100644 index 0000000000..544d590635 --- /dev/null +++ b/test/tool/spm_input.xml @@ -0,0 +1,11 @@ +# List of metrics + + +# SPM trace with parameters + + + diff --git a/test/tool/tool.cpp b/test/tool/tool.cpp index 11d14716bc..e3e46d5113 100644 --- a/test/tool/tool.cpp +++ b/test/tool/tool.cpp @@ -134,8 +134,10 @@ static uint32_t CTX_OUTSTANDING_MAX = 0; static uint32_t CTX_OUTSTANDING_MON = 0; // to truncate kernel names uint32_t to_truncate_names = 0; -// local SQTT buffer -bool is_sqtt_local = true; +// local trace buffer +bool is_trace_local = true; +// SPM trace enabled +bool is_spm_trace = false; static inline uint32_t GetPid() { return syscall(__NR_getpid); } static inline uint32_t GetTid() { return syscall(__NR_gettid); } @@ -281,7 +283,7 @@ void dealloc_context_entry(context_entry_t* entry) { // Dump trace data to file void dump_sqtt_trace(const char* label, const uint32_t chunk, const void* data, const uint32_t& size) { if (result_prefix != NULL) { - // Open SQTT file + // Open file std::ostringstream oss; oss << result_prefix << "/thread_trace_" << label << "_se" << chunk << ".out"; FILE* file = fopen(oss.str().c_str(), "w"); @@ -298,11 +300,36 @@ void dump_sqtt_trace(const char* label, const uint32_t chunk, const void* data, fprintf(file, "%04x\n", ptr[i]); } - // Close SQTT file + // Close file fclose(file); } } +// Dump trace data to file +void dump_spm_trace(const char* label, const void* data, const uint32_t& size) { + if (result_prefix != NULL) { + // Open trace file + std::ostringstream oss; + oss << result_prefix << "/spm_trace_" << label << ".out"; + const int fd = open(oss.str().c_str(), O_CREAT|O_WRONLY|O_TRUNC, 0666); + if (fd == -1) { + std::ostringstream errmsg; + errmsg << "open error, file '" << oss.str().c_str() << "'"; + perror(errmsg.str().c_str()); + abort(); + } + // write trace binary data + if (write(fd, data, size) == -1) { + std::ostringstream errmsg; + errmsg << "write error, file '" << oss.str().c_str() << "'"; + perror(errmsg.str().c_str()); + abort(); + } + // Close file + close(fd); + } +} + struct trace_data_arg_t { FILE* file; const char* label; @@ -314,23 +341,43 @@ hsa_status_t trace_data_cb(hsa_ven_amd_aqlprofile_info_type_t info_type, hsa_ven_amd_aqlprofile_info_data_t* info_data, void* data) { hsa_status_t status = HSA_STATUS_SUCCESS; trace_data_arg_t* arg = reinterpret_cast(data); - if (info_type == HSA_VEN_AMD_AQLPROFILE_INFO_SQTT_DATA) { - const void* data_ptr = info_data->sqtt_data.ptr; - const uint32_t data_size = info_data->sqtt_data.size; - fprintf(arg->file, " SE(%u) size(%u)\n", info_data->sample_id, data_size); + if (info_type == HSA_VEN_AMD_AQLPROFILE_INFO_TRACE_DATA) { + if (is_spm_trace) { + if (info_data->sample_id != 0) { + fatal("Only one SPM sample expected"); + } + const void* data_ptr = info_data->trace_data.ptr; + const uint32_t data_size = info_data->trace_data.size; + fprintf(arg->file, " size(%u)\n", data_size); - if (is_sqtt_local) { + if (is_trace_local == false) fatal("SPM trace supports only local trace allocation"); HsaRsrcFactory* hsa_rsrc = &HsaRsrcFactory::Instance(); const AgentInfo* agent_info = hsa_rsrc->GetAgentInfo(arg->agent); const uint32_t mem_size = data_size; void* buffer = hsa_rsrc->AllocateSysMemory(agent_info, mem_size); if(!hsa_rsrc->Memcpy(agent_info, buffer, data_ptr, mem_size)) { - fatal("SQTT data memcopy to host failed"); + fatal("Trace data memcopy to host failed"); } - dump_sqtt_trace(arg->label, info_data->sample_id, buffer, data_size); + dump_spm_trace(arg->label, buffer, data_size); HsaRsrcFactory::FreeMemory(buffer); } else { - dump_sqtt_trace(arg->label, info_data->sample_id, data_ptr, data_size); + const void* data_ptr = info_data->trace_data.ptr; + const uint32_t data_size = info_data->trace_data.size; + fprintf(arg->file, " SE(%u) size(%u)\n", info_data->sample_id, data_size); + + if (is_trace_local) { + HsaRsrcFactory* hsa_rsrc = &HsaRsrcFactory::Instance(); + const AgentInfo* agent_info = hsa_rsrc->GetAgentInfo(arg->agent); + const uint32_t mem_size = data_size; + void* buffer = hsa_rsrc->AllocateSysMemory(agent_info, mem_size); + if(!hsa_rsrc->Memcpy(agent_info, buffer, data_ptr, mem_size)) { + fatal("Trace data memcopy to host failed"); + } + dump_sqtt_trace(arg->label, info_data->sample_id, buffer, data_size); + HsaRsrcFactory::FreeMemory(buffer); + } else { + dump_sqtt_trace(arg->label, info_data->sample_id, data_ptr, data_size); + } } } else status = HSA_STATUS_ERROR; @@ -367,12 +414,12 @@ void output_results(const context_entry_t* entry, const char* label) { for (unsigned i = 0; i < p->data.result_bytes.instance_count; ++i) { const uint32_t chunk_size = *reinterpret_cast(ptr); const char* chunk_data = ptr + sizeof(uint32_t); - if (chunk_data >= end) fatal("SQTT data is out of the result buffer size"); + if (chunk_data >= end) fatal("Trace data is out of the result buffer size"); dump_sqtt_trace(label, i, chunk_data, chunk_size); const uint32_t off = align_size(chunk_size, sizeof(uint32_t)); ptr = chunk_data + off; - if (chunk_data >= end) fatal("SQTT data ptr is out of the result buffer size"); + if (chunk_data >= end) fatal("Trace data ptr is out of the result buffer size"); size += chunk_size; } fprintf(file, "size(%lu)\n", size); @@ -821,19 +868,19 @@ extern "C" PUBLIC_API void OnLoadToolProp(rocprofiler_settings_t* settings) if (it != opts.end()) { CTX_OUTSTANDING_MAX = atol(it->second.c_str()); } it = opts.find("heartbeat"); if (it != opts.end()) { CTX_OUTSTANDING_MON = atol(it->second.c_str()); } - it = opts.find("sqtt-size"); + it = opts.find("trace-size"); if (it != opts.end()) { - std::string str = normalize_token(it->second, true, "option sqtt-size"); + std::string str = normalize_token(it->second, true, "option trace-size"); uint32_t multiplier = 1; switch (str.back()) { case 'K': multiplier = 1024; break; case 'M': multiplier = 1024 * 1024; break; } if (multiplier != 1) str = str.substr(0, str.length() - 1); - settings->sqtt_size = strtoull(str.c_str(), NULL, 0) * multiplier; + settings->trace_size = strtoull(str.c_str(), NULL, 0) * multiplier; } - it = opts.find("sqtt-local"); - if (it != opts.end()) { settings->sqtt_local = (it->second == "on"); } + it = opts.find("trace-local"); + if (it != opts.end()) { settings->trace_local = (it->second == "on"); } it = opts.find("memcopies"); if (it != opts.end()) { settings->memcopy_tracking = (it->second == "on"); } } @@ -850,14 +897,14 @@ extern "C" PUBLIC_API void OnLoadToolProp(rocprofiler_settings_t* settings) check_env_var("ROCP_TIMESTAMP_ON", settings->timestamp_on); // Set data timeout check_env_var("ROCP_DATA_TIMEOUT", settings->timeout); - // Set SQTT size - check_env_var("ROCP_SQTT_SIZE", settings->sqtt_size); - // Set SQTT local buffer - check_env_var("ROCP_SQTT_LOCAL", settings->sqtt_local); + // Set trace size + check_env_var("ROCP_TRACE_SIZE", settings->trace_size); + // Set trace local buffer + check_env_var("ROCP_TRACE_LOCAL", settings->trace_local); // Set memcopies tracking check_env_var("ROCP_MCOPY_TRACKING", settings->memcopy_tracking); - is_sqtt_local = settings->sqtt_local; + is_trace_local = settings->trace_local; // Printing out info char* info_symb = getenv("ROCP_INFO"); @@ -943,6 +990,7 @@ extern "C" PUBLIC_API void OnLoadToolProp(rocprofiler_settings_t* settings) // Getting traces const auto traces_list = xml->GetNodes("top.trace"); + if (traces_list.size() > 1) fatal("ROCProfiler: only one trace supported at a time"); const unsigned feature_count = metrics_vec.size() + traces_list.size(); rocprofiler_feature_t* features = new rocprofiler_feature_t[feature_count]; @@ -966,7 +1014,8 @@ extern "C" PUBLIC_API void OnLoadToolProp(rocprofiler_settings_t* settings) auto it = entry->opts.find("name"); if (it == entry->opts.end()) fatal("ROCProfiler: trace name is missing"); const std::string& name = it->second; - if (name != "SQTT") continue; + if (name == "SPM") is_spm_trace = true; + traces_found++; bool to_copy_data = false; @@ -988,15 +1037,14 @@ extern "C" PUBLIC_API void OnLoadToolProp(rocprofiler_settings_t* settings) HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_TOKEN_MASK; parameters_dict["TOKEN_MASK2"] = HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_TOKEN_MASK2; -#ifdef AQLPROF_NEW_API parameters_dict["SE_MASK"] = HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SE_MASK; -#endif + parameters_dict["SAMPLE_RATE"] = + HSA_VEN_AMD_AQLPROFILE_PARAMETER_NAME_SAMPLE_RATE; printf(" %s (", name.c_str()); features[index] = {}; features[index].kind = ROCPROFILER_FEATURE_KIND_TRACE; - features[index].name = strdup(name.c_str()); features[index].data.result_bytes.copy = to_copy_data; uint32_t parameter_count = 0; @@ -1036,6 +1084,12 @@ extern "C" PUBLIC_API void OnLoadToolProp(rocprofiler_settings_t* settings) fflush(stdout); const uint32_t features_found = metrics_vec.size() + traces_found; + if (is_spm_trace) { + for (uint32_t index = 0; index < features_found; index++) { + features[index].kind = ROCPROFILER_FEATURE_KIND_TRACE; + } + } + // Context array aloocation context_array = new context_array_t;