From c42bdc312840ee19c3e579b0a63fd13de33cc4fe Mon Sep 17 00:00:00 2001 From: "Nagaraj, Sriraksha" Date: Wed, 4 Dec 2024 18:34:10 -0600 Subject: [PATCH] rocprofv3: rocprofv3-avail tool (#15) * support avail tool Updating avail library and script Listing on Std output incase the output folder is not given Extending list metrics test misc fix misc fix fixing memory leak changing list-metrics to list-avail fixing formatting issue Fixing CMakeLists Add test for list avil with trace Fix test fail clang tidy errors fixed Removing build commands for rocprofv3-trigger-list Addressing review changes addressing review comment moving avail to libexec merge fix Fix test failures updating doc Fix doc error * updating legacy doc * fix formatting issue * Addressing review comments --- CHANGELOG.md | 5 +- source/bin/CMakeLists.txt | 10 + source/bin/rocprofv3.py | 26 +- source/bin/rocprofv3_avail.py | 419 ++++++++++++++++++ .../comparing-with-legacy-tools.rst | 4 +- source/docs/how-to/using-rocprofv3.rst | 6 +- source/lib/rocprofiler-sdk-tool/tool.cpp | 177 -------- source/libexec/CMakeLists.txt | 2 +- .../libexec/rocprofiler-avail/CMakeLists.txt | 26 ++ .../rocprofiler-avail/rocprofv3_avail.cpp | 399 +++++++++++++++++ .../CMakeLists.txt | 21 - .../rocprofv3_trigger_list_metrics.cpp | 30 -- .../list_metrics/CMakeLists.txt | 40 +- .../list_metrics/conftest.py | 14 + .../list_metrics/input.json | 2 +- .../list_metrics/validate.py | 9 + 16 files changed, 933 insertions(+), 257 deletions(-) create mode 100644 source/bin/rocprofv3_avail.py create mode 100644 source/libexec/rocprofiler-avail/CMakeLists.txt create mode 100644 source/libexec/rocprofiler-avail/rocprofv3_avail.cpp delete mode 100644 source/libexec/rocprofv3-trigger-list-metrics/CMakeLists.txt delete mode 100644 source/libexec/rocprofv3-trigger-list-metrics/rocprofv3_trigger_list_metrics.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index ca9c4e5b..dd6a7bb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -100,8 +100,9 @@ Full documentation for ROCprofiler-SDK is available at [rocm.docs.amd.com/projec - `Dispatch_Id` - CSV column for counter collection - -## ROCprofiler-SDK 0.5.0 for ROCm release 6.3 (AFAR VII) +### Additions + --List supported PC Sampling Configurations +### Changes ### Added diff --git a/source/bin/CMakeLists.txt b/source/bin/CMakeLists.txt index 9e9e4660..055969db 100644 --- a/source/bin/CMakeLists.txt +++ b/source/bin/CMakeLists.txt @@ -14,3 +14,13 @@ install( PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE COMPONENT tools) + +configure_file(rocprofv3_avail.py + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/rocprofv3_avail COPYONLY) + +install( + FILES ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/rocprofv3_avail + DESTINATION ${CMAKE_INSTALL_BINDIR} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ + WORLD_EXECUTE + COMPONENT tools) diff --git a/source/bin/rocprofv3.py b/source/bin/rocprofv3.py index 69fa8558..e376d0d8 100755 --- a/source/bin/rocprofv3.py +++ b/source/bin/rocprofv3.py @@ -412,8 +412,8 @@ def add_parser_bool_argument(gparser, *args, **kwargs): add_parser_bool_argument( display_options, "-L", - "--list-metrics", - help="List metrics for counter collection. Backed by a valid YAML file. In earlier rocprof versions, this was known as --list-basic, --list-derived and --list-counters", + "--list-avail", + help="List available PC sampling configurations and metrics for counter collection. Backed by a valid YAML file. In earlier rocprof versions, this was known as --list-basic, --list-derived and --list-counters", ) advanced_options = parser.add_argument_group("Advanced options") @@ -678,9 +678,14 @@ def _write_env_value(): ROCPROF_KOKKOSP_LIBRARY = ( f"{ROCM_DIR}/lib/rocprofiler-sdk/librocprofiler-sdk-tool-kokkosp.so" ) + ROCPROF_LIST_AVAIL_TOOL_LIBRARY = f"{ROCM_DIR}/libexec/librocprofv3-list-avail.so" prepend_preload = [itr for itr in args.preload if itr] - append_preload = [ROCPROF_TOOL_LIBRARY, ROCPROF_SDK_LIBRARY] + append_preload = [ + ROCPROF_TOOL_LIBRARY, + ROCPROF_LIST_AVAIL_TOOL_LIBRARY, + ROCPROF_SDK_LIBRARY, + ] update_env("LD_PRELOAD", ":".join(prepend_preload), prepend=True) update_env("LD_PRELOAD", ":".join(append_preload), append=True) @@ -709,7 +714,7 @@ def _write_env_value(): ) if args.output_file is not None or args.output_directory is not None: - update_env("ROCPROF_OUTPUT_LIST_METRICS_FILE", True) + update_env("ROCPROF_OUTPUT_LIST_AVAIL_FILE", True) if not args.output_format: args.output_format = ["csv"] @@ -841,8 +846,8 @@ def _write_env_value(): overwrite_if_true=True, ) update_env( - "ROCPROF_LIST_METRICS", - args.list_metrics, + "ROCPROF_LIST_AVAIL", + args.list_avail, overwrite_if_true=True, ) @@ -891,8 +896,13 @@ def log_config(_env): sys.stderr.write("\n") sys.stderr.flush() - if args.list_metrics: - app_args = [f"{ROCM_DIR}/libexec/rocprofv3-trigger-list-metrics"] + if args.list_avail: + update_env("ROCPROFILER_PC_SAMPLING_BETA_ENABLED", "on") + path = os.path.join(f"{ROCM_DIR}", "bin/rocprofv3_avail") + if app_args: + exit_code = subprocess.check_call(["python3", path], env=app_env) + else: + app_args = ["python3", path] elif not app_args: log_config(app_env) diff --git a/source/bin/rocprofv3_avail.py b/source/bin/rocprofv3_avail.py new file mode 100644 index 00000000..e3329498 --- /dev/null +++ b/source/bin/rocprofv3_avail.py @@ -0,0 +1,419 @@ +#!/usr/bin/env python3 + +import ctypes +import pathlib +import os +import io +import csv +import socket + + +class derived_counter: + + def __init__( + self, counter_name, counter_description, counter_expression, counter_dimensions + ): + + self.name = counter_name + self.description = counter_description + self.expression = counter_expression + self.dimensions = counter_dimensions + + +class basic_counter: + + def __init__( + self, counter_name, counter_description, counter_block, counter_dimensions + ): + + self.name = counter_name + self.description = counter_description + self.block = counter_block + self.dimensions = counter_dimensions + + +class pc_config: + + def __init__(self, config_method, config_unit, min_interval, max_interval): + self.method = config_method + self.unit = config_unit + self.min_interval = min_interval + self.max_interval = max_interval + + +MAX_STR = 256 +libname = os.environ.get("ROCPROF_LIST_AVAIL_TOOL_LIBRARY") +c_lib = ctypes.CDLL(libname) + +c_lib.get_number_of_counters.restype = ctypes.c_ulong +c_lib.get_number_of_pc_sample_configs.restype = ctypes.c_ulong +c_lib.get_number_of_dimensions.restype = ctypes.c_ulong + +c_lib.get_number_of_counters.argtypes = [ctypes.c_int] +c_lib.get_number_of_pc_sample_configs.argtypes = [ctypes.c_int] +c_lib.get_number_of_dimensions.argtypes = [ctypes.c_int] + +c_lib.get_pc_sample_config.argtypes = [ + ctypes.c_ulong, + ctypes.c_ulong, + ctypes.POINTER(ctypes.POINTER(ctypes.c_char * MAX_STR)), + ctypes.POINTER(ctypes.POINTER(ctypes.c_char * MAX_STR)), + ctypes.POINTER(ctypes.c_ulong), + ctypes.POINTER(ctypes.c_ulong), +] + +c_lib.get_counters_info.argtypes = [ + ctypes.c_ulong, + ctypes.c_int, + ctypes.POINTER(ctypes.c_ulong), + ctypes.POINTER(ctypes.POINTER(ctypes.c_char * MAX_STR)), + ctypes.POINTER(ctypes.POINTER(ctypes.c_char * MAX_STR)), + ctypes.POINTER(ctypes.c_int), +] + +c_lib.get_counter_expression.argtypes = [ + ctypes.c_ulong, + ctypes.c_int, + ctypes.POINTER(ctypes.POINTER(ctypes.c_char * MAX_STR)), +] + +c_lib.get_counter_dimension.argtypes = [ + ctypes.c_ulong, + ctypes.c_ulong, + ctypes.POINTER(ctypes.c_ulong), + ctypes.POINTER(ctypes.POINTER(ctypes.c_char * MAX_STR)), + ctypes.POINTER(ctypes.c_ulong), +] + +c_lib.get_counter_block.argtypes = [ + ctypes.c_ulong, + ctypes.c_ulong, + ctypes.POINTER(ctypes.POINTER(ctypes.c_char * MAX_STR)), +] + +c_lib.get_number_of_agents.restype = ctypes.c_size_t + +c_lib.get_agent_node_id.restype = ctypes.c_ulong +c_lib.get_agent_node_id.argtypes = [ctypes.c_int] + + +agent_derived_counter_map = dict() +agent_basic_counter_map = dict() +agent_pc_sample_config_map = dict() + + +def get_counters(node_id): + + no_of_counters = c_lib.get_number_of_counters(node_id) + + basic_counters = [] + derived_counters = [] + for counter_idx in range(0, no_of_counters): + + name_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + description_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + block_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + is_derived_args = ctypes.c_int() + counter_id_args = ctypes.c_ulong() + + c_lib.get_counters_info( + node_id, + counter_idx, + ctypes.byref(counter_id_args), + name_args, + description_args, + ctypes.byref(is_derived_args), + ) + + is_derived = is_derived_args.value + counter_id = counter_id_args.value + no_of_dimensions = c_lib.get_number_of_dimensions(counter_id) + + name = ctypes.cast(name_args, ctypes.c_char_p).value.decode("utf-8") + description = ctypes.cast(description_args, ctypes.c_char_p).value.decode("utf-8") + dimensions_stream = io.StringIO() + + for dim in range(0, no_of_dimensions): + + dim_name_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + dim_instance_args = ctypes.c_ulong() + dimension_id_args = ctypes.c_ulong() + + c_lib.get_counter_dimension( + counter_id, + dim, + ctypes.byref(dimension_id_args), + dim_name_args, + ctypes.byref(dim_instance_args), + ) + + dim_name = ctypes.cast(dim_name_args, ctypes.c_char_p).value.decode("utf-8") + dim_instance = dim_instance_args.value + + dimensions_stream.write(dim_name) + dimensions_stream.write("[0:") + dimensions_stream.write(str(dim_instance - 1)) + dimensions_stream.write("]") + if dim != no_of_dimensions - 1: + dimensions_stream.write("\t") + + if is_derived: + + expression_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + c_lib.get_counter_expression(node_id, counter_idx, expression_args) + counter_expression = ctypes.cast( + expression_args, ctypes.c_char_p + ).value.decode("utf-8") + derived_counters.append( + derived_counter( + name, description, counter_expression, dimensions_stream.getvalue() + ) + ) + + else: + + block_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + c_lib.get_counter_block(node_id, counter_idx, block_args) + block = ctypes.cast(block_args, ctypes.c_char_p).value.decode("utf-8") + basic_counters.append( + basic_counter(name, description, block, dimensions_stream.getvalue()) + ) + dimensions_stream.close() + + agent_derived_counter_map[node_id] = derived_counters + agent_basic_counter_map[node_id] = basic_counters + + +def get_pc_sample_configs(node_id): + + no_of_pc_sample_configs = c_lib.get_number_of_pc_sample_configs(node_id) + pc_sample_configs = [] + if no_of_pc_sample_configs: + for config_idx in range(0, no_of_pc_sample_configs): + + method_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + unit_args = ctypes.POINTER(ctypes.c_char * MAX_STR)() + min_interval = ctypes.c_ulong() + max_interval = ctypes.c_ulong() + + c_lib.get_pc_sample_config( + node_id, + config_idx, + method_args, + unit_args, + ctypes.byref(min_interval), + ctypes.byref(max_interval), + ) + + method = ctypes.cast(method_args, ctypes.c_char_p).value.decode("utf-8") + unit = ctypes.cast(unit_args, ctypes.c_char_p).value.decode("utf-8") + pc_sample_configs.append( + pc_config(method, unit, min_interval.value, max_interval.value) + ) + + agent_pc_sample_config_map[node_id] = pc_sample_configs + + +def process_filename(file_path, file_type): + + filename = os.environ.get( + "ROCPROF_OUTPUT_FILE_NAME", socket.gethostname() + "/" + str(os.getpid()) + ) + + if os.path.exists(file_path) and os.path.isfile(file_path): + fatal_error("ROCPROFILER_OUTPUT_PATH already exists and is not a directory") + + elif not os.path.exists(file_path): + os.makedirs(file_path) + + output_filename = "" + if file_type == "derived": + output_filename = filename + "_" + "derived_metrics" + ".csv" + elif file_type == "basic": + output_filename = filename + "_" + "basic_metrics" + ".csv" + elif file_type == "pc_sample_config": + output_filename = filename + "_" + "pc_sample_config" + ".csv" + output_path = os.path.join(file_path, output_filename) + output_path_parent = os.path.dirname(output_path) + + if not os.path.exists(output_path_parent): + os.makedirs(output_path_parent) + + elif os.path.exists(output_path_parent) and os.path.isfile(output_path_parent): + fatal_error("ROCPROFILER_OUTPUT_PATH already exists and is not a directory") + + return output_path + + +def generate_output(agent_ids): + + list_avail_file = os.environ.get("ROCPROF_OUTPUT_LIST_AVAIL_FILE") + + if list_avail_file: + + file_path = os.environ.get("ROCPROF_OUTPUT_PATH") + derived_output_file = process_filename(file_path, "derived") + basic_output_file = process_filename(file_path, "basic") + pc_sample_config_file = process_filename(file_path, "pc_sample_config") + + with open(derived_output_file, "w") as csvfile: + print(f"Opened result file: {derived_output_file}") + fieldnames = ["Agent_Id", "Name", "Description", "Expression", "Dimensions"] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + for node_id, counters in agent_derived_counter_map.items(): + for counter in counters: + writer.writerow( + { + "Agent_Id": node_id, + "Name": counter.name, + "Description": counter.description, + "Expression": counter.expression, + "Dimensions": counter.dimensions, + } + ) + + with open(basic_output_file, "w") as csvfile: + print(f"Opened result file: {basic_output_file}") + fieldnames = ["Agent_Id", "Name", "Description", "Block", "Dimensions"] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + for node_id, counters in agent_basic_counter_map.items(): + for counter in counters: + if counter.block: + writer.writerow( + { + "Agent_Id": node_id, + "Name": counter.name, + "Description": counter.description, + "Block": counter.block, + "Dimensions": counter.dimensions, + } + ) + + with open(pc_sample_config_file, "w") as csvfile: + print(f"Opened result file: {pc_sample_config_file}") + fieldnames = [ + "Agent_Id", + "Method", + "Unit", + "Minimum_Interval", + "Maximum_Interval", + ] + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) + writer.writeheader() + for node_id, configs in agent_pc_sample_config_map.items(): + for config in configs: + writer.writerow( + { + "Agent_Id": node_id, + "Method": config.method, + "Unit": config.unit, + "Minimum_Interval": config.min_interval, + "Maximum_Interval": config.max_interval, + } + ) + else: + + for node_id in agent_ids: + print(f"gpu-agent:{node_id}\n") + if node_id in agent_basic_counter_map.keys(): + basic_counters_stream = io.StringIO() + counters = agent_basic_counter_map[node_id] + for counter in counters: + if counter.block: + basic_counters_stream.write("Name:") + basic_counters_stream.write("\t") + basic_counters_stream.write(str(counter.name)) + basic_counters_stream.write("\n") + basic_counters_stream.write("Description:") + basic_counters_stream.write("\t") + basic_counters_stream.write(str(counter.description)) + basic_counters_stream.write("\n") + basic_counters_stream.write("Block:") + basic_counters_stream.write("\t") + basic_counters_stream.write(str(counter.block)) + basic_counters_stream.write("\n") + basic_counters_stream.write("Dimensions:") + basic_counters_stream.write("\t") + basic_counters_stream.write(str(counter.dimensions)) + basic_counters_stream.write("\n") + basic_counters = basic_counters_stream.getvalue() + print("List Metrics Basic\n") + print(basic_counters) + print("\n") + basic_counters_stream.close() + + if node_id in agent_derived_counter_map.keys(): + derived_counters_stream = io.StringIO() + counters = agent_derived_counter_map[node_id] + for counter in counters: + derived_counters_stream.write("Name:") + derived_counters_stream.write("\t") + derived_counters_stream.write(str(counter.name)) + derived_counters_stream.write("\n") + derived_counters_stream.write("Description:") + derived_counters_stream.write("\t") + derived_counters_stream.write(str(counter.description)) + derived_counters_stream.write("\n") + derived_counters_stream.write("Expression:") + derived_counters_stream.write("\t") + derived_counters_stream.write(str(counter.expression)) + derived_counters_stream.write("\n") + derived_counters_stream.write("Dimensions:") + derived_counters_stream.write("\t") + derived_counters_stream.write(str(counter.dimensions)) + derived_counters_stream.write("\n") + derived_counters = derived_counters_stream.getvalue() + print("List Metrics Derived\n") + print(derived_counters) + print("\n") + derived_counters_stream.close() + + if node_id in agent_pc_sample_config_map.keys(): + pc_sample_config_stream = io.StringIO() + configs = agent_pc_sample_config_map[node_id] + for config in configs: + pc_sample_config_stream.write("Method:") + pc_sample_config_stream.write("\t") + pc_sample_config_stream.write(str(config.method)) + pc_sample_config_stream.write("\n") + pc_sample_config_stream.write("Unit:") + pc_sample_config_stream.write("\t") + pc_sample_config_stream.write(str(config.unit)) + pc_sample_config_stream.write("\n") + pc_sample_config_stream.write("Minimum_Interval:") + pc_sample_config_stream.write("\t") + pc_sample_config_stream.write(str(config.min_interval)) + pc_sample_config_stream.write("\n") + pc_sample_config_stream.write("Maximum_Interval:") + pc_sample_config_stream.write("\t") + pc_sample_config_stream.write(str(config.max_interval)) + pc_sample_config_stream.write("\n") + pc_sample = pc_sample_config_stream.getvalue() + print( + "List available PC Sample Configurations for node_id\t" + + str(node_id) + + "\n" + ) + print(pc_sample) + print("\n") + pc_sample_config_stream.close() + else: + print("PC Sampling not supported on node_id\t" + str(node_id) + "\n") + + +if __name__ == "__main__": + # Load the shared library into ctypes + + c_lib.avail_tool_init() + no_of_agents = c_lib.get_number_of_agents() + agent_ids = [] + for idx in range(0, no_of_agents): + + node_id = c_lib.get_agent_node_id(idx) + agent_ids.append(node_id) + get_counters(node_id) + get_pc_sample_configs(node_id) + + generate_output(agent_ids) diff --git a/source/docs/conceptual/comparing-with-legacy-tools.rst b/source/docs/conceptual/comparing-with-legacy-tools.rst index 16651196..d6847c98 100644 --- a/source/docs/conceptual/comparing-with-legacy-tools.rst +++ b/source/docs/conceptual/comparing-with-legacy-tools.rst @@ -214,10 +214,10 @@ ROCprofiler-SDK introduces a new command-line tool, `rocprofv3`, which is a more - New option to output summary in desired time units {sec,msec,usec,nsec} - * - Display options - - List Metrics + - List available basic and derived metrics and PC sampling configurations - `--list-basic`, `--list-derived` - `--list-counters` - - `-L`, `--list-metrics` + - `-L`, `--list-avail` - A valid YAML is supported for this option now - * - Perfetto-specific options diff --git a/source/docs/how-to/using-rocprofv3.rst b/source/docs/how-to/using-rocprofv3.rst index 5f1adf7a..09fe980c 100644 --- a/source/docs/how-to/using-rocprofv3.rst +++ b/source/docs/how-to/using-rocprofv3.rst @@ -122,9 +122,9 @@ Here is the sample of commonly used ``rocprofv3`` command-line options. Some opt - Iteration range for each kernel that match the filter [start-stop]. - Kernel Dispatch Counter Collection - * - ``-L`` \| ``--list-metrics`` - - List metrics for counter collection. - - Kernel Dispatch Counter Collection + * - ``-L`` \| ``--list-avail`` + - List metrics for counter collection + - List supported PC sampling configurations. * - ``-E`` \| ``--extra_counters`` - Specifies the path to a YAML file containing extra counter definitions. diff --git a/source/lib/rocprofiler-sdk-tool/tool.cpp b/source/lib/rocprofiler-sdk-tool/tool.cpp index dea1016b..6435cd03 100644 --- a/source/lib/rocprofiler-sdk-tool/tool.cpp +++ b/source/lib/rocprofiler-sdk-tool/tool.cpp @@ -121,30 +121,6 @@ add_destructor(Tp*& ptr) std::call_once(_once, []() { add_destructor(PTR); }); \ } -tool::csv_output_file*& -get_list_basic_metrics_file() -{ - static auto* _v = - new tool::csv_output_file{tool::get_config(), - "basic_metrics", - tool::csv::list_basic_metrics_csv_encoder{}, - {"Agent_Id", "Name", "Description", "Block", "Dimensions"}}; - ADD_DESTRUCTOR(_v); - return _v; -} - -tool::csv_output_file*& -get_list_derived_metrics_file() -{ - static auto* _v = - new tool::csv_output_file{tool::get_config(), - "derived_metrics", - tool::csv::list_derived_metrics_csv_encoder{}, - {"Agent_Id", "Name", "Description", "Expression", "Dimensions"}}; - ADD_DESTRUCTOR(_v); - return _v; -} - #undef ADD_DESTRUCTOR struct buffer_ids @@ -686,25 +662,6 @@ using counter_vec_t = std::vector; using agent_counter_map_t = std::unordered_map>; -rocprofiler_status_t -dimensions_info_callback(rocprofiler_counter_id_t /*id*/, - const rocprofiler_record_dimension_info_t* dim_info, - long unsigned int num_dims, - void* user_data) -{ - ROCP_FATAL_IF(user_data == nullptr) << "dimensions_info_callback invoked without user data"; - - if(user_data) - { - auto* _data = static_cast*>(user_data); - _data->reserve(num_dims); - for(size_t j = 0; j < num_dims; j++) - _data->emplace_back(dim_info[j]); - } - - return ROCPROFILER_STATUS_SUCCESS; -} - auto get_gpu_agents() { @@ -921,116 +878,6 @@ counter_record_callback(rocprofiler_dispatch_counting_service_data_t dispatch_da tool::write_ring_buffer(counter_record, domain_type::COUNTER_COLLECTION); } -rocprofiler_status_t -list_metrics_iterate_agents(rocprofiler_agent_version_t, - const void** agents, - size_t num_agents, - void*) -{ - for(size_t idx = 0; idx < num_agents; idx++) - { - const auto* agent = static_cast(agents[idx]); - auto counters_v = counter_vec_t{}; - // TODO(aelwazir): To be changed back to use node id once ROCR fixes - // the hsa_agents to use the real node id - uint32_t node_id = agent->logical_node_id; - if(agent->type != ROCPROFILER_AGENT_TYPE_GPU) continue; - - auto status = rocprofiler_iterate_agent_supported_counters( - agent->id, - [](rocprofiler_agent_id_t, - rocprofiler_counter_id_t* counters, - size_t num_counters, - void* user_data) { - auto* agent_node_id = static_cast(user_data); - for(size_t i = 0; i < num_counters; i++) - { - auto counter_info = rocprofiler_counter_info_v0_t{}; - auto dimensions = std::vector{}; - - ROCPROFILER_CALL(rocprofiler_iterate_counter_dimensions( - counters[i], dimensions_info_callback, &dimensions), - "iterate_dimension_info"); - - ROCPROFILER_CALL( - rocprofiler_query_counter_info(counters[i], - ROCPROFILER_COUNTER_INFO_VERSION_0, - static_cast(&counter_info)), - "Could not query counter_id"); - - auto dimensions_info = std::stringstream{}; - for(size_t j = 0; j != dimensions.size(); j++) - { - dimensions_info << dimensions[j].name - << "[0:" << dimensions[j].instance_size - 1 << "]"; - if(j != dimensions.size() - 1) dimensions_info << "\t"; - } - if(!counter_info.is_derived && tool::get_config().list_metrics && - !std::string(counter_info.block).empty()) - { - auto counter_info_ss = std::stringstream{}; - if(tool::get_config().list_metrics_output_file) - { - tool::csv::list_basic_metrics_csv_encoder::write_row( - counter_info_ss, - *agent_node_id, - counter_info.name, - counter_info.description, - counter_info.block, - dimensions_info.str()); - get_dereference(get_list_basic_metrics_file()) << counter_info_ss.str(); - } - else - { - counter_info_ss << "gpu-agent" << *agent_node_id << ":" - << "\t" << counter_info.name << "\n"; - counter_info_ss << "Description:" - << "\t" << counter_info.description << "\n"; - counter_info_ss << "Block:" - << "\t" << counter_info.block << "\n"; - counter_info_ss << "Dimensions:" - << "\t" << dimensions_info.str() << "\n"; - counter_info_ss << "\n"; - std::cout << counter_info_ss.str(); - } - } - else if(counter_info.is_derived && tool::get_config().list_metrics) - { - auto counter_info_ss = std::stringstream{}; - if(tool::get_config().list_metrics_output_file) - { - tool::csv::list_derived_metrics_csv_encoder::write_row( - counter_info_ss, - *agent_node_id, - counter_info.name, - counter_info.description, - counter_info.expression, - dimensions_info.str()); - get_dereference(get_list_derived_metrics_file()) - << counter_info_ss.str(); - } - else - { - counter_info_ss << "gpu-agent" << *agent_node_id << ":" - << "\t" << counter_info.name << "\n" - << "Description: " << counter_info.description << "\n"; - counter_info_ss << "Expression: " << counter_info.expression << "\n"; - counter_info_ss << "Dimensions: " << dimensions_info.str() << "\n"; - counter_info_ss << "\n"; - std::cout << counter_info_ss.str(); - } - } - } - return ROCPROFILER_STATUS_SUCCESS; - }, - reinterpret_cast(&node_id)); - - ROCP_ERROR_IF(status != ROCPROFILER_STATUS_SUCCESS) - << "Failed to iterate counters for agent " << node_id << " (" << agent->name << ")"; - } - return ROCPROFILER_STATUS_SUCCESS; -} - rocprofiler_client_finalize_t client_finalizer = nullptr; rocprofiler_client_id_t* client_identifier = nullptr; @@ -1418,21 +1265,6 @@ tool_init(rocprofiler_client_finalize_t fini_func, void* tool_data) return 0; } -void -api_registration_callback(rocprofiler_intercept_table_t, - uint64_t, - uint64_t, - void**, - uint64_t, - void*) -{ - ROCPROFILER_CALL(rocprofiler_query_available_agents(ROCPROFILER_AGENT_INFO_VERSION_0, - list_metrics_iterate_agents, - sizeof(rocprofiler_agent_t), - nullptr), - "Iterate rocporfiler agents") -} - using stats_data_t = tool::stats_data_t; using stats_entry_t = tool::stats_entry_t; using domain_stats_vec_t = tool::domain_stats_vec_t; @@ -1727,15 +1559,6 @@ rocprofiler_configure(uint32_t version, "Loading extra counters"); } - if(tool::get_config().list_metrics) - { - tool_metadata->init(tool::metadata::inprocess{}); - ROCPROFILER_CALL(rocprofiler_at_intercept_table_registration( - api_registration_callback, ROCPROFILER_HSA_TABLE, nullptr), - "api registration"); - return nullptr; - } - ROCP_INFO << id->name << " is using rocprofiler-sdk v" << major << "." << minor << "." << patch << " (" << runtime_version << ")"; diff --git a/source/libexec/CMakeLists.txt b/source/libexec/CMakeLists.txt index 38c96dae..c4edd0db 100644 --- a/source/libexec/CMakeLists.txt +++ b/source/libexec/CMakeLists.txt @@ -2,4 +2,4 @@ # # -add_subdirectory(rocprofv3-trigger-list-metrics) +add_subdirectory(rocprofiler-avail) diff --git a/source/libexec/rocprofiler-avail/CMakeLists.txt b/source/libexec/rocprofiler-avail/CMakeLists.txt new file mode 100644 index 00000000..fd6e9b31 --- /dev/null +++ b/source/libexec/rocprofiler-avail/CMakeLists.txt @@ -0,0 +1,26 @@ +rocprofiler_activate_clang_tidy() + +add_library(rocprofv3-list-avail SHARED) +target_sources(rocprofv3-list-avail PRIVATE rocprofv3_avail.cpp) + +target_link_libraries( + rocprofv3-list-avail + PRIVATE rocprofiler-sdk::rocprofiler-sdk-shared-library + rocprofiler-sdk::rocprofiler-sdk-headers + rocprofiler-sdk::rocprofiler-sdk-build-flags + rocprofiler-sdk::rocprofiler-sdk-common-library + rocprofiler-sdk::rocprofiler-sdk-cereal) + +set_target_properties( + rocprofv3-list-avail + PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBEXECDIR} + SOVERSION ${PROJECT_VERSION_MAJOR} + VERSION ${PROJECT_VERSION} + BUILD_RPATH "\$ORIGIN:\$ORIGIN/.." + INSTALL_RPATH "\$ORIGIN:\$ORIGIN/..") + +install( + TARGETS rocprofv3-list-avail + DESTINATION ${CMAKE_INSTALL_LIBEXECDIR} + COMPONENT tools + EXPORT rocprofiler-sdk-tool-targets) diff --git a/source/libexec/rocprofiler-avail/rocprofv3_avail.cpp b/source/libexec/rocprofiler-avail/rocprofv3_avail.cpp new file mode 100644 index 00000000..d2d2b1de --- /dev/null +++ b/source/libexec/rocprofiler-avail/rocprofv3_avail.cpp @@ -0,0 +1,399 @@ +// MIT License +// +// Copyright (c) 2023 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 "lib/common/environment.hpp" +#include "lib/common/filesystem.hpp" +#include "lib/common/logging.hpp" +#include "lib/common/scope_destructor.hpp" +#include "lib/common/string_entry.hpp" +#include "lib/common/synchronized.hpp" +#include "lib/common/units.hpp" +#include "lib/common/utility.hpp" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +auto destructors = new std::vector>{}; + +namespace common = ::rocprofiler::common; + +namespace +{ +auto pc_sampling_method = std::deque{ + "ROCPROFILER_PC_SAMPLING_METHOD_NONE", + "ROCPROFILER_PC_SAMPLING_METHOD_STOCHASTIC", + "ROCPROFILER_PC_SAMPLING_METHOD_HOST_TRAP", + "ROCPROFILER_PC_SAMPLING_METHOD_LAST", +}; + +auto pc_sampling_unit = std::deque{ + "ROCPROFILER_PC_SAMPLING_UNIT_NONE", + "ROCPROFILER_PC_SAMPLING_UNIT_INSTRUCTIONS", + "ROCPROFILER_PC_SAMPLING_UNIT_CYCLES", + "ROCPROFILER_PC_SAMPLING_UNIT_TIME", + "ROCPROFILER_PC_SAMPLING_UNIT_LAST", +}; +} // namespace + +using counter_info_t = std::vector>; +using pc_sample_info_t = std::vector>; +auto agent_counter_info = std::unordered_map{}; +auto agent_pc_sample_info = std::unordered_map{}; +// auto agent_configs_info = std::unordered_map{}; +using counter_dimension_info_t = + std::unordered_map>>; +auto counter_dim_info = counter_dimension_info_t{}; +std::vector agent_node_ids; + +constexpr size_t pc_config_fields = 4, method_idx = 0, unit_idx = 1, min_interval_idx = 2, + max_interval_idx = 3; +constexpr size_t dimensions_fields = 3, dim_id_idx = 0, dim_name_idx = 1, size_idx = 2; +constexpr size_t counter_fields = 5, counter_id_idx = 0, name_idx = 1, description_idx = 2, + is_derived_idx = 3, block_idx = 4, expression_idx = 4; + +#define ROCPROFILER_CALL(result, msg) \ + { \ + rocprofiler_status_t ROCPROFILER_VARIABLE(CHECKSTATUS, __LINE__) = result; \ + if(ROCPROFILER_VARIABLE(CHECKSTATUS, __LINE__) != ROCPROFILER_STATUS_SUCCESS) \ + { \ + std::string status_msg = \ + rocprofiler_get_status_string(ROCPROFILER_VARIABLE(CHECKSTATUS, __LINE__)); \ + std::cerr << "[" #result "][" << __FILE__ << ":" << __LINE__ << "] " << msg \ + << " failed with error code " << ROCPROFILER_VARIABLE(CHECKSTATUS, __LINE__) \ + << ": " << status_msg << "\n" \ + << std::flush; \ + std::stringstream errmsg{}; \ + errmsg << "[" #result "][" << __FILE__ << ":" << __LINE__ << "] " << msg " failure (" \ + << status_msg << ")"; \ + throw std::runtime_error(errmsg.str()); \ + } \ + } + +using counter_vec_t = std::vector; + +ROCPROFILER_EXTERN_C_INIT +void +avail_tool_init() ROCPROFILER_EXPORT; +size_t +get_number_of_agents() ROCPROFILER_EXPORT; +uint64_t +get_agent_node_id(int idx) ROCPROFILER_EXPORT; +int +get_number_of_counters(uint64_t node_id) ROCPROFILER_EXPORT; +void +get_counters_info(uint64_t node_id, + int idx, + uint64_t* counter_id, + const char** counter_name, + const char** counter_description, + uint8_t* is_derived) ROCPROFILER_EXPORT; +void +get_counter_expression(uint64_t node_id, int idx, const char** counter_expr) ROCPROFILER_EXPORT; + +void +get_counter_block(uint64_t node_id, int idx, const char** counter_block) ROCPROFILER_EXPORT; + +int +get_number_of_dimensions(int counter_id) ROCPROFILER_EXPORT; + +void +get_counter_dimension(uint64_t counter_id, + uint64_t dimension_idx, + uint64_t* dimension_id, + const char** dimension_name, + uint64_t* dimension_instance) ROCPROFILER_EXPORT; + +int +get_number_of_pc_sample_configs(uint64_t node_id) ROCPROFILER_EXPORT; + +void +get_pc_sample_config(uint64_t node_id, + int idx, + const char** method, + const char** unit, + uint64_t* min_interval, + uint64_t* max_interval) ROCPROFILER_EXPORT; +ROCPROFILER_EXTERN_C_FINI + +void +initialize_logging() +{ + auto logging_cfg = rocprofiler::common::logging_config{.install_failure_handler = true}; + common::init_logging("ROCPROF", logging_cfg); + FLAGS_colorlogtostderr = true; +} + +rocprofiler_status_t +pc_configuration_callback(const rocprofiler_pc_sampling_configuration_t* configs, + long unsigned int num_config, + void* user_data) +{ + auto* avail_configs = static_cast>*>(user_data); + + for(size_t i = 0; i < num_config; i++) + { + auto config = std::vector{}; + config.reserve(pc_config_fields); + auto it = config.begin(); + config.insert(it + method_idx, pc_sampling_method.at(configs[i].method)); + config.insert(it + unit_idx, pc_sampling_unit.at(configs[i].unit)); + config.insert(it + min_interval_idx, std::to_string(configs[i].min_interval)); + config.insert(it + max_interval_idx, std::to_string(configs[i].max_interval)); + avail_configs->push_back(config); + } + + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +dimensions_info_callback(rocprofiler_counter_id_t /*id*/, + const rocprofiler_record_dimension_info_t* dim_info, + long unsigned int num_dims, + void* user_data) +{ + auto* dimensions_info = + static_cast*>(user_data); + dimensions_info->reserve(num_dims); + for(size_t j = 0; j < num_dims; j++) + dimensions_info->emplace_back(dim_info[j]); + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +iterate_agent_counters_callback(rocprofiler_agent_id_t, + rocprofiler_counter_id_t* counters, + size_t num_counters, + void* user_data) +{ + auto* _counters_info = reinterpret_cast>*>(user_data); + auto dimensions_data = std::vector{}; + for(size_t i = 0; i < num_counters; i++) + { + rocprofiler_counter_info_v0_t _info; + ROCPROFILER_CALL( + rocprofiler_iterate_counter_dimensions( + counters[i], dimensions_info_callback, static_cast(&dimensions_data)), + "iterate_dimension_info"); + auto dimensions_info = std::vector>{}; + dimensions_info.reserve(dimensions_data.size()); + for(auto& dim : dimensions_data) + { + auto dimensions = std::vector{}; + dimensions.reserve(dimensions_fields); + auto it = dimensions.begin(); + dimensions.insert(it + dim_id_idx, std::to_string(dim.id)); + dimensions.insert(it + dim_name_idx, std::string(dim.name)); + dimensions.insert(it + size_idx, std::to_string(dim.instance_size - 1)); + dimensions_info.emplace_back(dimensions); + } + counter_dim_info.emplace(counters[i].handle, dimensions_info); + ROCPROFILER_CALL( + rocprofiler_query_counter_info( + counters[i], ROCPROFILER_COUNTER_INFO_VERSION_0, static_cast(&_info)), + "Could not query counter_id"); + + auto counter = std::vector{}; + + if(_info.is_derived) + { + counter.reserve(counter_fields); + auto it = counter.begin(); + counter.insert(it + counter_id_idx, std::to_string(_info.id.handle)); + counter.insert(it + name_idx, std::string(_info.name)); + counter.insert(it + description_idx, std::string(_info.description)); + counter.insert(it + is_derived_idx, std::to_string(_info.is_derived)); + counter.insert(it + expression_idx, std::string(_info.expression)); + } + else + { + counter.reserve(counter_fields); + auto it = counter.begin(); + counter.insert(it + counter_id_idx, std::to_string(_info.id.handle)); + counter.insert(it + name_idx, std::string(_info.name)); + counter.insert(it + description_idx, std::string(_info.description)); + counter.insert(it + is_derived_idx, std::to_string(_info.is_derived)); + counter.insert(it + block_idx, std::string(_info.block)); + } + + _counters_info->emplace_back(counter); + } + return ROCPROFILER_STATUS_SUCCESS; +} + +rocprofiler_status_t +list_avail_configs(rocprofiler_agent_version_t, const void** agents, size_t num_agents, void*) +{ + for(size_t idx = 0; idx < num_agents; idx++) + { + const auto* agent = static_cast(agents[idx]); + if(agent->type == ROCPROFILER_AGENT_TYPE_GPU) + { + auto counters_v = counter_vec_t{}; + + // TODO(aelwazir): To be changed back to use node id once ROCR fixes + // the hsa_agents to use the real node id + uint32_t node_id = agent->node_id; + std::vector> configs = {}; + std::vector> _counter_dim_info = {}; + agent_node_ids.emplace_back(node_id); + rocprofiler_query_pc_sampling_agent_configurations( + agent->id, pc_configuration_callback, &configs); + ROCPROFILER_CALL( + rocprofiler_iterate_agent_supported_counters( + agent->id, iterate_agent_counters_callback, (void*) (&_counter_dim_info)), + "Iterate rocprofiler counters"); + if(!_counter_dim_info.empty()) agent_counter_info.emplace(node_id, _counter_dim_info); + if(!configs.empty()) + + { + agent_pc_sample_info.emplace(node_id, configs); + } + } + } + + return ROCPROFILER_STATUS_SUCCESS; +} + +ROCPROFILER_EXTERN_C_INIT + +void +avail_tool_init() +{ + initialize_logging(); + ROCPROFILER_CALL(rocprofiler_query_available_agents(ROCPROFILER_AGENT_INFO_VERSION_0, + list_avail_configs, + sizeof(rocprofiler_agent_t), + nullptr), + "Iterate rocporfiler agents"); +} + +size_t +get_number_of_agents() +{ + return agent_node_ids.size(); +} + +uint64_t +get_agent_node_id(int idx) +{ + return agent_node_ids.at(idx); +} + +int +get_number_of_counters(uint64_t node_id) +{ + if(agent_counter_info.find(node_id) != agent_counter_info.end()) + return agent_counter_info.at(node_id).size(); + else + return 0; +} + +void +get_counters_info(uint64_t node_id, + int counter_idx, + uint64_t* counter_id, + const char** counter_name, + const char** counter_description, + uint8_t* is_derived) +{ + if(agent_counter_info.find(node_id) == agent_counter_info.end()) return; + *counter_id = + std::stoull(agent_counter_info.at(node_id).at(counter_idx).at(0).c_str(), nullptr, 10); + *counter_name = agent_counter_info.at(node_id).at(counter_idx).at(1).c_str(); + *counter_description = agent_counter_info.at(node_id).at(counter_idx).at(2).c_str(); + *is_derived = std::stoi(agent_counter_info.at(node_id).at(counter_idx).at(3).c_str()); +} + +void +get_counter_block(uint64_t node_id, int counter_idx, const char** counter_block) +{ + if(agent_counter_info.find(node_id) == agent_counter_info.end()) return; + *counter_block = agent_counter_info.at(node_id).at(counter_idx).at(4).c_str(); +} + +void +get_counter_expression(uint64_t node_id, int idx, const char** counter_expr) +{ + if(agent_counter_info.find(node_id) == agent_counter_info.end()) return; + *counter_expr = agent_counter_info.at(node_id).at(idx).at(4).c_str(); +} + +int +get_number_of_dimensions(int counter_id) +{ + if(counter_dim_info.find(counter_id) == counter_dim_info.end()) return 0; + return counter_dim_info.at(counter_id).size(); +} +void +get_counter_dimension(uint64_t counter_id, + uint64_t dimension_idx, + uint64_t* dimension_id, + const char** dimension_name, + uint64_t* dimension_instance) +{ + if(counter_dim_info.find(counter_id) == counter_dim_info.end()) return; + *dimension_id = + std::stoull(counter_dim_info.at(counter_id).at(dimension_idx).at(0).c_str(), nullptr, 10); + *dimension_name = counter_dim_info.at(counter_id).at(dimension_idx).at(1).c_str(); + *dimension_instance = + std::stoull(counter_dim_info.at(counter_id).at(dimension_idx).at(2).c_str(), nullptr, 10); +} + +int +get_number_of_pc_sample_configs(uint64_t node_id) +{ + if(agent_pc_sample_info.find(node_id) == agent_pc_sample_info.end()) return 0; + return agent_pc_sample_info.at(node_id).size(); +} + +void +get_pc_sample_config(uint64_t node_id, + int config_idx, + const char** method, + const char** unit, + uint64_t* min_interval, + uint64_t* max_interval) +{ + if(agent_pc_sample_info.find(node_id) == agent_pc_sample_info.end()) return; + *method = agent_pc_sample_info.at(node_id).at(config_idx).at(0).c_str(); + *unit = agent_pc_sample_info.at(node_id).at(config_idx).at(1).c_str(); + *min_interval = + std::stoull(agent_pc_sample_info.at(node_id).at(config_idx).at(2).c_str(), nullptr, 10); + *max_interval = + std::stoull(agent_pc_sample_info.at(node_id).at(config_idx).at(3).c_str(), nullptr, 10); +} + +ROCPROFILER_EXTERN_C_FINI diff --git a/source/libexec/rocprofv3-trigger-list-metrics/CMakeLists.txt b/source/libexec/rocprofv3-trigger-list-metrics/CMakeLists.txt deleted file mode 100644 index 3a958c0c..00000000 --- a/source/libexec/rocprofv3-trigger-list-metrics/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# -# -# - -set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "tools") - -add_executable(rocprofv3-trigger-list-metrics) -target_sources(rocprofv3-trigger-list-metrics PRIVATE rocprofv3_trigger_list_metrics.cpp) -target_link_libraries(rocprofv3-trigger-list-metrics - PRIVATE rocprofiler-sdk::rocprofiler-sdk-hsa-runtime) -set_target_properties( - rocprofv3-trigger-list-metrics - PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBEXECDIR} - BUILD_RPATH "\$ORIGIN:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}" - INSTALL_RPATH "\$ORIGIN:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") - -install( - TARGETS rocprofv3-trigger-list-metrics - DESTINATION ${CMAKE_INSTALL_LIBEXECDIR} - COMPONENT tools - EXPORT rocprofiler-sdk-tool-targets) diff --git a/source/libexec/rocprofv3-trigger-list-metrics/rocprofv3_trigger_list_metrics.cpp b/source/libexec/rocprofv3-trigger-list-metrics/rocprofv3_trigger_list_metrics.cpp deleted file mode 100644 index ee1df1eb..00000000 --- a/source/libexec/rocprofv3-trigger-list-metrics/rocprofv3_trigger_list_metrics.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// MIT License -// -// Copyright (c) 2023 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 - -int -main() -{ - hsa_init(); - return 0; -} diff --git a/tests/rocprofv3/counter-collection/list_metrics/CMakeLists.txt b/tests/rocprofv3/counter-collection/list_metrics/CMakeLists.txt index 20a2d58d..afe6276f 100644 --- a/tests/rocprofv3/counter-collection/list_metrics/CMakeLists.txt +++ b/tests/rocprofv3/counter-collection/list_metrics/CMakeLists.txt @@ -15,28 +15,35 @@ rocprofiler_configure_pytest_files(CONFIG pytest.ini COPY validate.py conftest.p # basic-metrics add_test( - NAME rocprofv3-test-list-metrics-execute - COMMAND - $ -d - ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2 -o metrics --list-metrics) + NAME rocprofv3-test-list-avail-execute + COMMAND $ -d + ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2 -o metrics --list-avail) # list-metrics-stdout -add_test(NAME rocprofv3-test-list-metrics-std-out-execute +add_test(NAME rocprofv3-test-list-avail-std-out-execute COMMAND $ -i ${CMAKE_CURRENT_BINARY_DIR}/input.json) +# list-metrics with tracing +add_test( + NAME rocprofv3-test-list-avail-trace-execute + COMMAND + $ -d + ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2 -o metrics --list-avail + --sys-trace -- $) + string(REPLACE "LD_PRELOAD=" "ROCPROF_PRELOAD=" PRELOAD_ENV "${ROCPROFILER_MEMCHECK_PRELOAD_ENV}") set(cc-env-list-metrics "${PRELOAD_ENV}") set_tests_properties( - rocprofv3-test-list-metrics-execute + rocprofv3-test-list-avail-execute PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT "${cc-env-list-metrics}" FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}") set_tests_properties( - rocprofv3-test-list-metrics-std-out-execute + rocprofv3-test-list-avail-std-out-execute PROPERTIES TIMEOUT 45 @@ -45,23 +52,32 @@ set_tests_properties( ENVIRONMENT "${cc-env-list-metrics}" PASS_REGULAR_EXPRESSION - "gpu-agent[0-9]*:[a-zA-Z_]*\\n;Description:(.*)\\n*;Expression:(.)*\\n*;Block:[a-zA-Z]*\\n*;Dimensions:([A-Z_]*\\[[0-9]*:[0-9]*\\])*\\n*;" + "gpu-agent:[0-9]*\\n*; Name:\t[a-zA-Z_]*\\n;Description:\t(.*)\\n*;Expression:\t(.)*\\n*;Block:\t[a-zA-Z]*\\n*;Dimensions:\t([A-Z_]*\\[[0-9]*:[0-9]*\\];Method:\t(.*);Unit:\t(.*);Minimum_Interval:\t[0-9]*;Maximum_Interval:\t[0-9]*)*\\n*;" ) + +set_tests_properties( + rocprofv3-test-list-avail-trace-execute + PROPERTIES TIMEOUT 45 LABELS "integration-tests" ENVIRONMENT "${cc-env-list-metrics}" + FAIL_REGULAR_EXPRESSION "${ROCPROFILER_DEFAULT_FAIL_REGEX}") + set(VALIDATION_FILES ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_basic_metrics.csv - ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_derived_metrics.csv) + ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_derived_metrics.csv + ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_pc_sample_config.csv) add_test( - NAME rocprofv3-test-list-metrics-validate + NAME rocprofv3-test-list-avail-validate COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/validate.py --derived-metrics-input ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_derived_metrics.csv --basic-metrics-input - ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_basic_metrics.csv) + ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_basic_metrics.csv + --pc-sample-config-input + ${CMAKE_CURRENT_BINARY_DIR}/out_counter_collection_2/metrics_pc_sample_config.csv) set_tests_properties( - rocprofv3-test-list-metrics-validate + rocprofv3-test-list-avail-validate PROPERTIES TIMEOUT 45 LABELS diff --git a/tests/rocprofv3/counter-collection/list_metrics/conftest.py b/tests/rocprofv3/counter-collection/list_metrics/conftest.py index 99db2d57..95e99079 100644 --- a/tests/rocprofv3/counter-collection/list_metrics/conftest.py +++ b/tests/rocprofv3/counter-collection/list_metrics/conftest.py @@ -7,6 +7,7 @@ def pytest_addoption(parser): parser.addoption("--basic-metrics-input", action="store", help="Path to csv file.") parser.addoption("--derived-metrics-input", action="store", help="Path to csv file.") + parser.addoption("--pc-sample-config-input", action="store", help="Path to csv file.") @pytest.fixture @@ -33,3 +34,16 @@ def basic_metrics_input_data(request): data.append(row) return data + + +@pytest.fixture +def pc_sample_config_input_data(request): + filename = request.config.getoption("--pc-sample-config-input") + data = [] + if filename: + with open(filename, "r") as inp: + reader = csv.DictReader(inp) + for row in reader: + data.append(row) + + return data diff --git a/tests/rocprofv3/counter-collection/list_metrics/input.json b/tests/rocprofv3/counter-collection/list_metrics/input.json index 383712c5..eb148d7b 100644 --- a/tests/rocprofv3/counter-collection/list_metrics/input.json +++ b/tests/rocprofv3/counter-collection/list_metrics/input.json @@ -1,7 +1,7 @@ { "jobs": [ { - "list_metrics": true + "list_avail": true } ] } diff --git a/tests/rocprofv3/counter-collection/list_metrics/validate.py b/tests/rocprofv3/counter-collection/list_metrics/validate.py index 396842d5..93f2c8ac 100644 --- a/tests/rocprofv3/counter-collection/list_metrics/validate.py +++ b/tests/rocprofv3/counter-collection/list_metrics/validate.py @@ -29,6 +29,15 @@ def test_validate_list_derived_metrics(derived_metrics_input_data): row["Expression"] == "reduce(TA_TA_BUSY,min)" +def test_validate_list_pc_sample_config(pc_sample_config_input_data): + for row in pc_sample_config_input_data: + assert row["Agent_Id"].isdigit() == True + assert row["Method"] != "" + assert row["Unit"] != "" + assert row["Minimum_Interval"].isdigit() == True + assert row["Maximum_Interval"].isdigit() == True + + if __name__ == "__main__": exit_code = pytest.main(["-x", __file__] + sys.argv[1:]) sys.exit(exit_code)