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)