[RSERP-1802] Add trace decoder to API (#398)

* Add trace decoder to API.

* Cleanup and activity

* Rename

* Minor fix

* Replace tt/TT with thread_trace/THREAD_TRACE

- public API types are not abbreviated

* Fix aliases

* Build system updates

- activate clang-tidy for all subfolders in lib
- fix addition of sources for att-tool

* Fix clang-tidy issues with lib/att-tool/counters.{hpp,cpp}

* Delete counters.cpp

* Formatting

---------

Co-authored-by: Giovanni Baraldi <gbaraldi@amd.com>
Co-authored-by: Jonathan R. Madsen <jonathanrmadsen@gmail.com>
Этот коммит содержится в:
Baraldi, Giovanni
2025-05-17 21:08:33 +02:00
коммит произвёл GitHub
родитель 3eb921a34c
Коммит 65786f619d
56 изменённых файлов: 1175 добавлений и 1419 удалений
+59 -129
Просмотреть файл
@@ -24,7 +24,6 @@
import argparse
import os
import re
import subprocess
import textwrap
import sys
@@ -105,74 +104,30 @@ def strtobool(val):
raise ValueError(f"invalid truth value {val} (type={val_type})")
def search_path(path_list):
supported_option = []
lib_att_pattern = r"libatt_decoder_(trace|debug|testing1|testing2)\.so"
file_list = []
for path in path_list:
for root, dirs, files in os.walk(path, topdown=True):
file_list.extend(files)
break
for itr in file_list:
_match = re.match(lib_att_pattern, itr)
if _match:
lst = re.findall("trace|debug|testing1|testing2", itr)
supported_option.extend(lst)
return set(supported_option)
def check_att_capability(args):
ROCPROFV3_DIR = os.path.dirname(os.path.realpath(__file__))
ROCM_DIR = os.path.dirname(ROCPROFV3_DIR)
ld_library_paths = []
for itr in os.environ.get("LD_LIBRARY_PATH", "").split(":") + [f"{ROCM_DIR}/lib"]:
# don't add duplicates
if itr not in ld_library_paths:
ld_library_paths += [itr]
tmp_parser = argparse.ArgumentParser(add_help=False, allow_abbrev=False)
tmp_parser.add_argument(
"--att-library-path",
default=os.environ.get(
"ROCPROF_ATT_LIBRARY_PATH", ":".join(ld_library_paths)
).split(":"),
nargs="+",
type=str,
required=False,
)
if args.att_library_path:
ld_library_paths.extend(args.att_library_path)
else:
for itr in os.environ.get("LD_LIBRARY_PATH", "").split(":") + [f"{ROCM_DIR}/lib"]:
# don't add duplicates
if itr not in ld_library_paths:
ld_library_paths += [itr]
tmp_parser.add_argument(
"-i",
"--input",
default=None,
type=str,
required=False,
)
lib_att_name = "librocprof-trace-decoder.so"
att_args, _ = tmp_parser.parse_known_args(args)
for path in ld_library_paths:
for root, dirs, files in os.walk(path, topdown=True):
for itr in files:
if lib_att_name in itr:
args.att_library_path = itr.split(lib_att_name)[0]
return True
support = search_path(att_args.att_library_path)
support_input = {}
if att_args.input:
# If index of a pass in input file is a key in the support_input dict, then that pass has att-library-path arg
args_list = parse_input(att_args.input)
for index, itr in enumerate(args_list):
if itr.att_library_path:
library_path = (
itr.att_library_path.split(":")
if isinstance(itr.att_library_path, str)
else itr.att_library_path
)
_support = search_path(library_path)
# If the att-library-path in the input file for a pass is valid, then the value of index key in the dict,
# support_input, is updated to that valid path
# If the att-library-path in the input file for a pass is invalid, then the value of index key in the dict,
# support_input, is empty
support_input[index] = set(_support) if support else []
return (att_args.att_library_path, set(support), support_input)
return False
class booleanArgAction(argparse.Action):
@@ -687,72 +642,66 @@ For MPI applications (or other job launchers such as SLURM), place rocprofv3 ins
app_args = args[(idx + 1) :]
break
default_att_lib_path, att_support_args, att_support_inp = check_att_capability(
rocp_args
)
choice_list = []
for keys, values in att_support_inp.items():
choice_list.extend(values)
if att_support_args:
choice_list.extend(list(att_support_args))
# remove duplicates
choice_list = list(set(choice_list))
att_options = parser.add_argument_group("Advanced Thread Trace (ATT) options")
add_parser_bool_argument(
att_options,
"--advanced-thread-trace",
"--att",
help="Enable ATT",
help="Enables thread trace",
)
att_options.add_argument(
"--att-library-path",
help="Search path(s) to decoder library/libraries",
default=default_att_lib_path if not att_support_inp else None,
help="Search path to decoder library.",
default=None,
nargs="+",
)
att_options.add_argument(
"--att-target-cu",
help="ATT target compute unit",
help="Target compute unit ID (or WGP). Default 1",
default=None,
)
att_options.add_argument(
"--att-simd-select",
help="Select ATT SIMD",
help="Bitmask of SIMDs to enable (gfx9) or SIMD ID (gfx10+). Default 0xF",
default=None,
type=str,
)
att_options.add_argument(
"--att-buffer-size",
help="Buffer Size",
help="Thread trace buffer size. Default 96MB",
default=None,
type=str,
)
att_options.add_argument(
"--att-shader-engine-mask",
help="att shader engine mask",
help="Bitmask of shader engines to enable. Default 0x1",
default=None,
type=str,
)
att_options.add_argument(
"--att-perfcounters",
help="Set performance counters, and optionally their mask. gfx9 only.",
help="(gfx9) List of performance counters, and optionally their SIMD mask.",
default=None,
type=str.upper,
)
att_options.add_argument(
"--att-perfcounter-ctrl",
help="Integer in [0,32] range specifying collection period. gfx9 only.",
help="(gfx9) Integer in [1,32] range specifying collection period. 0 = disabled.",
default=None,
type=int,
)
att_options.add_argument(
"--att-activity",
help="(gfx9) Collect HW activity counters. Integer in [1,16] range specifying collection period. Recommended: 8",
default=None,
type=int,
)
@@ -761,10 +710,10 @@ For MPI applications (or other job launchers such as SLURM), place rocprofv3 ins
att_options,
"--att-serialize-all",
default=False,
help="Serialize all kernels",
help="Serialize all kernels, not just the traced ones.",
)
return (parser.parse_args(rocp_args), app_args, att_support_args, att_support_inp)
return (parser.parse_args(rocp_args), app_args)
def parse_yaml(yaml_file):
@@ -1496,12 +1445,17 @@ def run(app_args, args, **kwargs):
args.att_serialize_all,
overwrite=True,
)
if args.att_library_path:
if check_att_capability(args):
update_env(
"ROCPROF_ATT_LIBRARY_PATH",
":".join(args.att_library_path),
args.att_library_path,
overwrite=True,
)
else:
fatal_error(
"rocprof-trace-decoder library path not found in", args.att_library_path
)
if args.att_perfcounters:
if args.pmc:
fatal_error("ATT perfcounters cannot be enabled with PMC")
@@ -1520,6 +1474,24 @@ def run(app_args, args, **kwargs):
args.att_perfcounter_ctrl,
overwrite=True,
)
if args.att_activity:
if args.pmc:
fatal_error("ATT activity cannot be enabled with PMC")
elif args.att_perfcounters or args.att_perfcounter_ctrl:
fatal_error(
"ATT activity cannot be enabled with att-perfcounters or att-perfcounter-ctrl."
)
else:
update_env(
"ROCPROF_ATT_PARAM_PERFCOUNTER_CTRL",
args.att_activity,
overwrite=True,
)
update_env(
"ROCPROF_ATT_PARAM_PERFCOUNTERS",
"SQ_BUSY_CU_CYCLES SQ_VALU_MFMA_BUSY_CYCLES SQ_ACTIVE_INST_VALU SQ_ACTIVE_INST_LDS SQ_ACTIVE_INST_VMEM SQ_ACTIVE_INST_FLAT SQ_ACTIVE_INST_SCA SQ_ACTIVE_INST_MISC",
overwrite=True,
)
if args.log_level in ("info", "trace", "env", "config"):
log_config(app_env)
@@ -1547,45 +1519,9 @@ def run(app_args, args, **kwargs):
return exit_code
def check_att_path_parse_method(args, index, support_att_input, att_parse_supported):
if not att_parse_supported:
if index not in support_att_input.keys():
fatal_error(
f"Advanced_thread_trace enabled but no decoder library found in cmdline/env paths and att_library_path not set for pass-{index + 1}"
)
elif not support_att_input[index]:
fatal_error(
f"Advanced_thread_trace enabled but no decoder library found in att_library_path for pass-{index + 1}"
)
else:
if args.att_parse and args.att_parse not in support_att_input[index]:
fatal_error(
f"Advanced_thread_trace enabled but decoder library for requested parse method not found in att_library_path for pass-{index + 1}"
)
else:
if index in support_att_input.keys() and not support_att_input[index]:
fatal_error(
f"Advanced_thread_trace enabled but no decoder library found in att_library_path for pass-{index + 1}"
)
elif index not in support_att_input.keys():
if args.att_parse and args.att_parse not in att_parse_supported:
fatal_error(
"Advanced_thread_trace enabled but decoder library for requested parse method not found"
)
else:
if args.att_parse and args.att_parse not in support_att_input[index]:
fatal_error(
f"Advanced_thread_trace enabled but decoder library for requested parse method not found for pass-{index + 1}"
)
def main(argv=None):
# att_parse_supported is valid path for decoder in env or commandline arg
# support_att_input is a dict, where key is a pass index with value being a valid decoder path
cmd_args, app_args, att_parse_supported, support_att_input = parse_arguments(argv)
cmd_args, app_args = parse_arguments(argv)
inp_args = (
parse_input(cmd_args.input) if getattr(cmd_args, "input") else [dotdict({})]
)
@@ -1595,16 +1531,10 @@ def main(argv=None):
pass_idx = None
if has_set_attr(args, "pmc") and len(args.pmc) > 0:
pass_idx = 1
if args.advanced_thread_trace:
check_att_path_parse_method(args, 0, support_att_input, att_parse_supported)
run(app_args, args, pass_id=pass_idx)
else:
for idx, itr in enumerate(inp_args):
args = get_args(cmd_args, itr)
if args.advanced_thread_trace:
check_att_path_parse_method(
args, idx, support_att_input, att_parse_supported
)
run(
app_args,
args,