diff --git a/source/bin/rocprofv3-avail.py b/source/bin/rocprofv3-avail.py index 84e4b31a3b..66d6ddb98e 100755 --- a/source/bin/rocprofv3-avail.py +++ b/source/bin/rocprofv3-avail.py @@ -185,20 +185,32 @@ def get_basic_agent_info(info): return basic_info +def get_number_columns(max_name_len): + total_column_width = 120 + if sys.stdout.isatty(): + total_column_width = os.get_terminal_size().columns + width = total_column_width / (max_name_len + 1) + if width < 1: + return 1 + return int(width) + + def list_basic_agent(args, list_counters): - def print_agent_counter(counters, info): - names = ["{:20}".format(counter.name) for counter in counters] - print(" PMC:\n") - for idx in range(0, len(names), int(len(names) / 20)): - print( - " {}".format( - " ".join(names[idx : (idx + int(len(names) / 20))]) - ) - ) + def print_agent_counter(counters): + names_len = [len(counter.name) for counter in counters] + names = [ + "{name:{width}}".format(name=counter.name, width=max(names_len)) + for counter in counters + ] + columns = get_number_columns(max(names_len)) + print("{:30}:\n".format("PMC")) + for idx in range(0, len(names), columns): + print("{}".format(" ".join(names[idx : (idx + columns)]))) + print("\n") def print_basic_info(info): print("GPU:{}\n".format(info["logical_node_type_id"])) - print("\n".join([" {:20}: {}".format(key, itr) for key, itr in info.items()])) + print("\n".join(["{:30}:\t{}".format(key, itr) for key, itr in info.items()])) if not list_counters: print("\n") @@ -213,13 +225,13 @@ def list_basic_agent(args, list_counters): ): print_basic_info(get_basic_agent_info(info)) if list_counters: - print_agent_counter(agent_counters[agent], info) + print_agent_counter(agent_counters[agent]) break elif info["type"] == 2 and args.device is None: print_basic_info(get_basic_agent_info(info)) if list_counters: - print_agent_counter(agent_counters[agent], info) + print_agent_counter(agent_counters[agent]) def list_pc_sampling(args): @@ -228,7 +240,12 @@ def list_pc_sampling(args): print("Agents supporting PC Sampling\n") for agent in sampling_agents.keys(): info = agent_info_map[agent] - print("GPU:{}\nNAME:{}\n".format(info["logical_node_type_id"], info["name"])) + print( + "{:8}:\t{}\n{:8}:\t{}".format( + "GPU", info["logical_node_type_id"], "Name", info["name"] + ) + ) + print("\n") def info_pc_sampling(args): @@ -236,8 +253,12 @@ def info_pc_sampling(args): agent_info_map = avail.get_agent_info_map() for agent, configs in sampling_agents.items(): info = agent_info_map[agent] - print("GPU:{}\nNAME:{}".format(info["logical_node_type_id"], info["name"])) - print("configs:") + print( + "{:8}:\t{}\n{:8}:\t{}".format( + "GPU", info["logical_node_type_id"], "Name", info["name"] + ) + ) + print("{:8}:".format("configs")) for config in configs: print(config) print("\n") @@ -245,15 +266,16 @@ def info_pc_sampling(args): def listing(args): - def print_agent_counter(counters, info): - names = ["{:20}".format(counter.name) for counter in counters] - print("PMC:\n") - for idx in range(0, len(names), int(len(names) / 20)): - print( - " {}".format( - " ".join(names[idx : (idx + int(len(names) / 20))]) - ) - ) + def print_agent_counter(counters): + names_len = [len(counter.name) for counter in counters] + names = [ + "{name:{width}}".format(name=counter.name, width=max(names_len)) + for counter in counters + ] + columns = get_number_columns(max(names_len)) + print("{:30}:\n".format("PMC")) + for idx in range(0, len(names), columns): + print("{:30}".format(" ".join(names[idx : (idx + columns)]))) agent_counters = avail.get_counters() agent_info_map = avail.get_agent_info_map() @@ -264,12 +286,22 @@ def listing(args): and args.device is not None and info["logical_node_type_id"] == args.device ): - print("GPU:{}\nNAME:{}".format(info["logical_node_type_id"], info["name"])) - print_agent_counter(agent_counters[agent], info) + print( + "{:30}:\t{}\n{:30}:\t{}".format( + "GPU", info["logical_node_type_id"], "Name", info["name"] + ) + ) + print_agent_counter(agent_counters[agent]) + print("\n") break elif info["type"] == 2 and args.device is None: - print("GPU:{}\nNAME:{}".format(info["logical_node_type_id"], info["name"])) - print_agent_counter(agent_counters[agent], info) + print( + "{:30}:\t{}\n{:30}:\t{}".format( + "GPU", info["logical_node_type_id"], "Name", info["name"] + ) + ) + print_agent_counter(agent_counters[agent]) + print("\n") def info_pmc(args): @@ -285,7 +317,7 @@ def info_pmc(args): else: for pmc in args.pmc: for counter in pmc_counters: - if pmc == counter.get_as_dict()["counter_name"]: + if pmc == counter.get_as_dict()["Counter_Name"]: print(counter) print("\n") @@ -295,11 +327,19 @@ def info_pmc(args): and args.device is not None and info["logical_node_type_id"] == args.device ): - print("GPU:{}\nNAME:{}".format(info["logical_node_type_id"], info["name"])) + print( + "{}:{}\n{}:{}".format( + "GPU", info["logical_node_type_id"], "Name", info["name"] + ) + ) print_pmc_info(args, agent_counters[agent]) break elif info["type"] == 2 and args.device is None: - print("GPU:{}\nNAME:{}".format(info["logical_node_type_id"], info["name"])) + print( + "{}:{}\n{}:{}".format( + "GPU", info["logical_node_type_id"], "Name", info["name"] + ) + ) print_pmc_info(args, agent_counters[agent]) @@ -314,10 +354,12 @@ def process_info(args): def process_list(args): - if not args.agent and args.pc_sampling is None: + if args.agent is None and args.pc_sampling is None and args.pmc is None: listing(args) if args.agent: list_basic_agent(args, False) + if args.pmc: + listing(args) if args.pc_sampling: os.environ["ROCPROFILER_PC_SAMPLING_BETA_ENABLED"] = "on" list_pc_sampling(args) @@ -341,7 +383,7 @@ def process_pmc_check(args): agent_counters = avail.get_counters() for agent, counters in agent_counters.items(): for counter in counters: - if counter.get_as_dict()["counter_name"] == counter_name: + if counter.get_as_dict()["Counter_Name"] == counter_name: return counter.counter_handle avail.fatal_error("Invalid counter name") @@ -418,8 +460,9 @@ def main(argv=None): ROCPROFV3_AVAIL_DIR = os.path.dirname(os.path.realpath(__file__)) ROCM_DIR = os.path.dirname(ROCPROFV3_AVAIL_DIR) ROCPROF_LIST_AVAIL_TOOL_LIBRARY = ( - f"{ROCM_DIR}/libexec/rocprofiler-sdk/librocprofv3-list-avail.so" + f"{ROCM_DIR}/lib/rocprofiler-sdk/librocprofv3-list-avail.so" ) + os.environ["ROCPROFILER_METRICS_PATH"] = f"{ROCM_DIR}/share/rocprofiler-sdk" avail.loadLibrary.libname = os.environ.get( "ROCPROF_LIST_AVAIL_TOOL_LIBRARY", ROCPROF_LIST_AVAIL_TOOL_LIBRARY ) diff --git a/source/bin/rocprofv3.py b/source/bin/rocprofv3.py index 97b0c6580b..6cc43190db 100755 --- a/source/bin/rocprofv3.py +++ b/source/bin/rocprofv3.py @@ -1056,7 +1056,7 @@ def run(app_args, args, **kwargs): f"{ROCM_DIR}/lib/rocprofiler-sdk/librocprofiler-sdk-tool-kokkosp.so" ) ROCPROF_LIST_AVAIL_TOOL_LIBRARY = ( - f"{ROCM_DIR}/libexec/rocprofiler-sdk/librocprofv3-list-avail.so" + f"{ROCM_DIR}/lib/rocprofiler-sdk/librocprofv3-list-avail.so" ) ROCPROF_TOOL_LIBRARY = resolve_library_path(ROCPROF_TOOL_LIBRARY, args) diff --git a/source/bin/rocprofv3_avail_module/avail.py b/source/bin/rocprofv3_avail_module/avail.py index 9e8dbecdbf..21e3d7972b 100644 --- a/source/bin/rocprofv3_avail_module/avail.py +++ b/source/bin/rocprofv3_avail_module/avail.py @@ -36,18 +36,16 @@ def fatal_error(msg, exit_code=1): def build_counter_string(obj): counter_str = "\n".join( - ["{:20}: {}".format(key, itr) for key, itr in obj.get_as_dict().items()] + ["{:20}:\t{}".format(key, itr) for key, itr in obj.get_as_dict().items()] ) - counter_str = counter_str + "\n" - for dim in obj.dimensions: - counter_str = counter_str + dim.__str__() - counter_str = counter_str + "\n" + + counter_str += "\n" + "{:20}:\t".format("Dimensions") + counter_str += " ".join(dim.__str__() for dim in obj.dimensions) return counter_str class dimension: - - columns = ["dimension_id", "dimension_name", "dimension_instances"] + columns = ["Dimension_Id", "Dimension_Name", "Dimension_Instances"] def __init__(self, dimension_id, dimension_name, dimension_instances): self.id = dimension_id @@ -58,18 +56,16 @@ class dimension: return dict(zip((self.columns), [self.id, self.name, self.instances])) def __str__(self): - dimension = "{:20}: {}\n".format( - "dimension_name", self.get_as_dict()["dimension_name"] - ) - dimension += "{:20}: [0:{}]".format( - "dimension_instances", self.get_as_dict()["dimension_instances"] + dimension = "{}[0:{}]".format( + self.get_as_dict()["Dimension_Name"], + self.get_as_dict()["Dimension_Instances"] - 1, ) return dimension class counter: - columns = ["counter_name", "description"] + columns = ["Counter_Name", "Description"] def __init__( self, @@ -90,13 +86,13 @@ class counter: def __str__(self): return "\n".join( - ["{:20}: {}".format(key, itr) for key, itr in self.get_as_dict().items()] + ["{:20}:\t{}".format(key, itr) for key, itr in self.get_as_dict().items()] ) class derived_counter(counter): - columns = ["counter_name", "description", "expression"] + columns = ["Counter_Name", "Description", "Expression"] def __init__( self, @@ -125,7 +121,7 @@ class derived_counter(counter): class basic_counter(counter): - columns = ["counter_name", "description", "block"] + columns = ["Counter_Name", "Description", "Block"] def __init__( self, @@ -154,7 +150,7 @@ class basic_counter(counter): class pc_config: - columns = ["method", "unit", "min_interval", "max_interval", "flags"] + columns = ["Method", "Unit", "Min_Interval", "Max_Interval", "Flags"] def __init__(self, config_method, config_unit, min_interval, max_interval, flags): @@ -168,9 +164,9 @@ class pc_config: return "\n".join( [ - " {:20}:{}".format( + " {:20}:\t{}".format( key, - itr if key == "method" or key == "unit" else self.get_value(key, itr), + itr if key == "Method" or key == "Unit" else self.get_value(key, itr), ) for key, itr in self.get_as_dict().items() ] @@ -178,9 +174,9 @@ class pc_config: @staticmethod def get_value(key, itr): - if key == "min_interval" or key == "max_interval": + if key == "Min_Interval" or key == "Max_Interval": return itr.value - elif key == "flags": + elif key == "Flags": if itr.value == 1: return "interval pow2" else: diff --git a/source/docs/how-to/using-pc-sampling.rst b/source/docs/how-to/using-pc-sampling.rst index 10e82dfa53..203ad72dfb 100644 --- a/source/docs/how-to/using-pc-sampling.rst +++ b/source/docs/how-to/using-pc-sampling.rst @@ -41,11 +41,14 @@ The output lists if ``rocprofv3`` supports PC sampling on the GPU and the suppor .. code-block:: bash - List available PC Sample Configurations for node_id 11 - Method: ROCPROFILER_PC_SAMPLING_METHOD_HOST_TRAP - Unit: ROCPROFILER_PC_SAMPLING_UNIT_TIME - Minimum_Interval: 1 - Maximum_Interval: 18446744073709551615 + GPU:0 + NAME:gfx90a + configs: + Method :host_trap + Unit :time + Min_Interval :1 + Max_Interval :18446744073709551615 + Flags :none The preceding output shows that the GPU supports PC sampling with the ``ROCPROFILER_PC_SAMPLING_METHOD_HOST_TRAP`` method and the ``ROCPROFILER_PC_SAMPLING_UNIT_TIME`` unit. The minimum and maximum intervals are also displayed. @@ -220,10 +223,14 @@ Output similar to the following indicates that the ``ROCPROFILER_PC_SAMPLING_MET .. code-block:: bash - Method: ROCPROFILER_PC_SAMPLING_METHOD_STOCHASTIC - Unit: ROCPROFILER_PC_SAMPLING_UNIT_CYCLES - Minimum_Interval: 256 - Maximum_Interval: 2147483648 + GPU:1 + NAME:gfx942 + configs: + Method :stochastic + Unit :cycle + Min_Interval :256 + Max_Interval :2147483648 + Flags :interval pow2 Please note that on gfx942, `ROCPROFILER_PC_SAMPLING_METHOD_STOCHASTIC` requires intervals to be specified in cycles, whose values are powers of 2 diff --git a/source/docs/how-to/using-rocprofv3-avail.rst b/source/docs/how-to/using-rocprofv3-avail.rst index d7371d24f0..2c0361e820 100644 --- a/source/docs/how-to/using-rocprofv3-avail.rst +++ b/source/docs/how-to/using-rocprofv3-avail.rst @@ -42,60 +42,55 @@ The following table lists ``rocprofv3-avail`` command-line options categorized a | ``list`` | ``pmc-check`` - | Info options for detailed information of counters, agents, and pc-sampling configurations. - | List options for hw counters, agents and pc-sampling support". - | Checking counters collection support on agents. + | List options for hardware counters, agents and pc-sampling support. + | Checking if a set of counters can be collected together on agent. - -Available Hardware Counters -++++++++++++++++++++++++++++ -.. code-block:: bash - - rocprofv3-avail -d 0 - -The preceding command selects a device with logical node type id as 0 in the node. -The option is applied to further sub commands and options - .. code-block:: bash rocprofv3-avail list -The preceding command generates an output listing agents and hardware counters +The preceding command generates an output listing agents and hardware counters. .. code-block:: bash rocprofv3-avail list --agent -The preceding command generates an output listing basic info for all agents, if used with -d only basic info for device -d is listed. +The preceding command generates an output listing basic info for all agents, if used with ``-d``, only basic info for device ``-d`` is listed. +Following is the sample output .. code-block:: bash rocprofv3-avail list --pmc -The preceding command generates an output listing counters for all agents, if used with -d only counters on the the -d device is listed +The preceding command generates an output listing counters for all agents, if used with ``-d``, only counters on the ``-d`` device is listed. +Output contains following information: logical node id, name and list of PMC counters supported on the agent. .. code-block:: bash rocprofv3-avail list --pc-sampling -The preceding command generates an output listing agents that supports any kind of PC Sampling. -d option is not applicable here. +The preceding command generates an output listing agents that supports any kind of PC Sampling. ``-d`` option is not applicable here. + .. code-block:: bash rocprofv3-avail info -The preceding command generates an output with agent information and listing all counters -supported on each +The preceding command generates an output with agent information and listing all counters supported on each agent. .. code-block:: bash rocprofv3-avail info --pmc -The preceding command generates an output with the pmc info, if used with -d information of pmc for device -d is generated. +The preceding command generates an output with the pmc info, if used with ``-d`` information of pmc for device ``-d`` is generated. +Output includes the following information: logical node id, name, counter_name, description of the counter, dimensions, block/expression for every counter. .. code-block:: bash rocprofv3-avail info --pc-sampling -The preceding command generates list of supported PC sampling configurations for each agent that supports PC sampling. -d option is not applicable here. +The preceding command generates list of supported PC sampling configurations for each agent that supports PC sampling. ``-d`` option is not applicable here. +Output has following information: logical node id, method supported, unit, minimum sampling interval, maximum sampling interval +flags. .. code-block:: bash @@ -107,11 +102,10 @@ The preceding command checks if the pmc can be collected together rocprofv3-avail pmc-check -d 0 :device=1 - The preceding command checks if the pmc1 and pmc2 can be collected together on agent 0 - and pmc3 on agent 1 - +The preceding command checks if the pmc1 and pmc2 can be collected together on agent 0 and pmc3 on agent 1 + .. note:: - The above command writes the ouptut to the standard output. - + All commands writes to the standard output. + diff --git a/source/lib/rocprofiler-sdk/CMakeLists.txt b/source/lib/rocprofiler-sdk/CMakeLists.txt index 1fc1ddfe65..a3e84960c4 100644 --- a/source/lib/rocprofiler-sdk/CMakeLists.txt +++ b/source/lib/rocprofiler-sdk/CMakeLists.txt @@ -158,3 +158,5 @@ set_target_properties( if(ROCPROFILER_BUILD_TESTS) add_subdirectory(tests) endif() + +add_subdirectory(rocprofiler-avail) diff --git a/source/libexec/rocprofiler-sdk/rocprofiler-avail/CMakeLists.txt b/source/lib/rocprofiler-sdk/rocprofiler-avail/CMakeLists.txt similarity index 94% rename from source/libexec/rocprofiler-sdk/rocprofiler-avail/CMakeLists.txt rename to source/lib/rocprofiler-sdk/rocprofiler-avail/CMakeLists.txt index 6d8a5ee603..0061a71068 100644 --- a/source/libexec/rocprofiler-sdk/rocprofiler-avail/CMakeLists.txt +++ b/source/lib/rocprofiler-sdk/rocprofiler-avail/CMakeLists.txt @@ -44,7 +44,7 @@ target_link_libraries( set_target_properties( rocprofv3-list-avail PROPERTIES LIBRARY_OUTPUT_DIRECTORY - ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBEXECDIR}/rocprofiler-sdk + ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/rocprofiler-sdk SOVERSION ${PROJECT_VERSION_MAJOR} VERSION ${PROJECT_VERSION} BUILD_RPATH "\$ORIGIN:\$ORIGIN/.." @@ -52,6 +52,6 @@ set_target_properties( install( TARGETS rocprofv3-list-avail - DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/rocprofiler-sdk + DESTINATION ${CMAKE_INSTALL_LIBDIR}/rocprofiler-sdk COMPONENT tools EXPORT rocprofiler-sdk-tool-targets) diff --git a/source/libexec/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.cpp b/source/lib/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.cpp similarity index 100% rename from source/libexec/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.cpp rename to source/lib/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.cpp diff --git a/source/libexec/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.hpp b/source/lib/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.hpp similarity index 100% rename from source/libexec/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.hpp rename to source/lib/rocprofiler-sdk/rocprofiler-avail/rocprofv3_avail.hpp diff --git a/source/libexec/rocprofiler-sdk/CMakeLists.txt b/source/libexec/rocprofiler-sdk/CMakeLists.txt index c380641a2b..5b6a160649 100644 --- a/source/libexec/rocprofiler-sdk/CMakeLists.txt +++ b/source/libexec/rocprofiler-sdk/CMakeLists.txt @@ -22,5 +22,4 @@ # -add_subdirectory(rocprofiler-avail) add_subdirectory(rocprofiler-sdk-launch-compiler) diff --git a/tests/rocprofv3-avail/CMakeLists.txt b/tests/rocprofv3-avail/CMakeLists.txt index 96cb7866a2..2c40cff554 100644 --- a/tests/rocprofv3-avail/CMakeLists.txt +++ b/tests/rocprofv3-avail/CMakeLists.txt @@ -50,7 +50,7 @@ set_tests_properties( ENVIRONMENT "${test-rocprofv3-avail-env}" PASS_REGULAR_EXPRESSION - "GPU:[0-9]*\\n*;Name:\\t[a-zA-Z_]*\\n;counter_name:\\t[a-zA-Z_]*\\n;description:\\t(.*)\\n*;expression:\\t(.)*\\n*;block:\\t[a-zA-Z]*\\n*;dimension_name:\\t([A-Z_]*)\\n*; dimension_instances:\\t([[0-9]*:[0-9]*\\])*\\n*" + "GPU:[0-9]*\\n*;Name:\\t[a-zA-Z_]*\\n;Counter_Name:\\t[a-zA-Z_]*\\n;Description:\\t(.*)\\n*;Expression:\\t(.)*\\n*;Block:\\t[a-zA-Z]*\\n*;Dimensions:\\t([A-Z_]*)\\t([[0-9]*:[0-9]*\\])*\\n*" DISABLED "${IS_DISABLED}") @@ -64,7 +64,7 @@ set_tests_properties( ENVIRONMENT "${test-rocprofv3-avail-env};${enable_pc_sampling}" PASS_REGULAR_EXPRESSION - "GPU:[0-9]*\\n*;Name:\\t[a-zA-Z_]*\\n;method:(.*)\\n*;unit:(.*)\\n*;min_interval:[0-9]*\\n*;max_interval:[0-9]*\\n*;flags:(.*)\\n*" + "GPU[:0-9 ]+\\n*;Name[:a-zA-Z_ ]+\\n;configs[: ]+;Method:(.*)\\n*;Unit:(.*)\\n*;Min_Interval:[0-9]*\\n*;Max_Interval:[0-9]*\\n*;Flags:(.*)\\n*" DISABLED "${IS_DISABLED}") diff --git a/tests/rocprofv3-avail/validate.py b/tests/rocprofv3-avail/validate.py index 95e0eada67..3d85dc0774 100644 --- a/tests/rocprofv3-avail/validate.py +++ b/tests/rocprofv3-avail/validate.py @@ -110,8 +110,9 @@ def test_counter_set(capsys, rocm_path): def set_library(rocm_path): ROCPROF_LIST_AVAIL_TOOL_LIBRARY = ( - f"{rocm_path}/libexec/rocprofiler-sdk/librocprofv3-list-avail.so" + f"{rocm_path}/lib/rocprofiler-sdk/librocprofv3-list-avail.so" ) + os.environ["ROCPROFILER_METRICS_PATH"] = f"{rocm_path}/share/rocprofiler-sdk" avail.loadLibrary.libname = os.environ.get( "ROCPROF_LIST_AVAIL_TOOL_LIBRARY", ROCPROF_LIST_AVAIL_TOOL_LIBRARY )