Files

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

202 строки
6.7 KiB
Python
Исходник Постоянная ссылка Обычный вид История

2025-06-06 04:03:14 -05:00
###############################################################################
# MIT License
#
# Copyright (c) 2023 Advanced Micro Devices, Inc.
#
# 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.
###############################################################################
import sys
import os
import argparse
try:
import ctypes
sqlite3lib = ctypes.CDLL("libsqlite3.so")
except Exception:
pass
from . import libpyrocpd
__all__ = ["format_path", "output_config", "add_args", "add_generic_args"]
2025-06-06 04:03:14 -05:00
def _generate_attribute_docs(data):
properties = []
for key, itr in data.items():
if not isinstance(key, str):
pass
if key.startswith("__") and key.endswith("__"):
pass
else:
properties += [key]
return "\n\t- ".join(properties)
class output_config(libpyrocpd.output_config):
__doc__ = f"""Output configuration
Read/Write properties:\n\t- {_generate_attribute_docs(libpyrocpd.output_config.__dict__)}
Example:
# folder for output data
output_dir = os.path.join(os.getcwd(), "rocpd-output")
# create output config instance
cfg = output_config(output_path=output_dir, output_file="out")
# using read/write properties
if cfg.output_path != output_dir:
cfg.output_path = output_dir
"""
def __init__(self, **kwargs):
super(output_config, self).__init__()
self.update(**kwargs)
def update(self, **kwargs):
_strict = kwargs.get("strict", False)
2025-06-06 04:03:14 -05:00
for key, itr in kwargs.items():
if hasattr(self, key):
if key == "agent_index_value":
if itr == "absolute":
setattr(self, key, libpyrocpd.agent_indexing.node)
elif itr == "type-relative":
setattr(self, key, libpyrocpd.agent_indexing.logical_node_type)
else:
setattr(self, key, libpyrocpd.agent_indexing.logical_node)
else:
setattr(self, key, itr)
elif _strict:
raise KeyError(f"output_config does not have {key} attribute")
return self
def format_path(path, tag=os.path.basename(sys.executable)):
return libpyrocpd.format_path(path, tag)
def sanitize_input_list(input: list):
sanitized_list = []
for items in input:
if isinstance(items, list):
sanitized_list.extend(sanitize_input_list(items))
else:
sanitized_list.append(items)
return sanitized_list
2025-06-06 04:03:14 -05:00
def check_file_exists(filename):
import glob
# Check for wildcards passed in
if any(char in filename for char in ["*", "?", "["]):
expanded_files = glob.glob(filename)
if not expanded_files:
raise argparse.ArgumentTypeError(f"File '{filename}' does not exist.")
return sanitize_input_list(expanded_files)
else:
if not os.path.exists(filename):
raise argparse.ArgumentTypeError(f"File '{filename}' does not exist.")
return filename
2025-06-06 04:03:14 -05:00
def add_args(parser):
"""Add output arguments to an existing parser."""
io_options = parser.add_argument_group("I/O options")
io_options.add_argument(
"-o",
"--output-file",
help="Sets the base output file name (default base filename: `out`)",
default=os.environ.get("ROCPD_OUTPUT_NAME", "out"),
type=str,
required=False,
)
io_options.add_argument(
"-d",
"--output-path",
help="Sets the output path where the output files will be saved (default path: `./rocpd-output-data`)",
default=os.environ.get("ROCPD_OUTPUT_PATH", "./rocpd-output-data"),
type=str,
required=False,
)
io_options.add_argument(
"--automerge-limit",
help="Change database auto-merge limit (default: 1, auto-merge to 1 DB. max: 8)",
type=int,
required=False,
)
def process_args(input, args):
valid_args = ["output_file", "output_path"]
ret = {}
for itr in valid_args:
if hasattr(args, itr):
val = getattr(args, itr)
if itr == "output_format":
ret[itr] = val
elif itr == "output_path" and val is not None:
ret[itr] = format_path(val)
elif val is not None:
ret[itr] = val
return ret
return process_args
def add_generic_args(parser):
"""Add generic arguments that apply to multiple output formats."""
2025-06-06 04:03:14 -05:00
kernel_naming_options = parser.add_argument_group("Kernel naming options")
kernel_naming_options.add_argument(
"--kernel-rename",
help="Use ROCTx marker names instead of kernel names",
action="store_true",
default=False,
)
generic_options = parser.add_argument_group("Generic options")
generic_options.add_argument(
"--agent-index-value",
choices=("absolute", "relative", "type-relative"),
help="""Device identification format in CSV/Perfetto/OTF2 output (default: relative):
absolute: uses node_id (Agent-0, Agent-2, Agent-4) ignoring cgroups restrictions.
relative: uses logical_node_id (Agent-0, Agent-1, Agent-2) considering cgroups restrictions.
type-relative: uses logical_node_type_id (CPU-0, GPU-0, GPU-1) with numbering that resets for each device type.""",
default="relative",
)
def process_args(input, args):
valid_args = ["agent_index_value", "kernel_rename"]
ret = {}
for itr in valid_args:
if hasattr(args, itr):
val = getattr(args, itr)
if val is not None:
ret[itr] = val
return ret
return process_args