Add support for structured YAML output

This commit adds a new `--yaml-out` flag to OSACA which allows the user
to dump the results of an analysis to a YAML file, allowing them to
analyse the file more easily. I have tried to make the output as
comprehensive as possible.
This commit is contained in:
Stephen Nicholas Swatman
2023-08-12 19:42:11 +02:00
parent 87ce1d2b29
commit 8615c33df6
2 changed files with 100 additions and 0 deletions

View File

@@ -201,6 +201,78 @@ class Frontend(object):
+ self.loopcarried_dependencies(kernel_dg.get_loopcarried_dependencies())
)
def full_analysis_dict(
self,
kernel,
kernel_dg: KernelDG,
arch_warning=False,
length_warning=False,
lcd_warning=False,
):
warnings = []
if arch_warning:
warnings.append("ArchWarning")
if length_warning:
warnings.append("LengthWarning")
if lcd_warning:
warnings.append("LcdWarning")
if INSTR_FLAGS.TP_UNKWN in [flag for instr in kernel for flag in instr["flags"]]:
warnings.append("UnknownInstrWarning")
tp_sum = ArchSemantics.get_throughput_sum(kernel) or kernel[0]["port_pressure"]
cp_kernel = kernel_dg.get_critical_path()
dep_dict = kernel_dg.get_loopcarried_dependencies()
lcd_sum = 0.0
if dep_dict:
longest_lcd = max(dep_dict, key=lambda ln: dep_dict[ln]["latency"])
lcd_sum = dep_dict[longest_lcd]["latency"]
return {
"Header": self._header_report_dict(),
"Warnings": warnings,
"Kernel": [
{
"Line": re.sub(r"\s+", " ", x["line"].strip()),
"Flags": list(x["flags"]),
"Instruction": x["instruction"],
"Label": x["label"],
"Latency": x["latency"],
"LatencyCP": x["latency_cp"],
"LatencyLCD": x["latency_lcd"],
"Throughput": float(x["throughput"]),
"LatencyWithoutLoad": x["latency_wo_load"],
"PortPressure": {
self._machine_model.get_ports()[i]: v
for i, v in enumerate(x["port_pressure"])
},
"PortUops": [
{
"Ports": list(y[1]),
"Cycles": y[0],
}
for y in x["port_uops"]
],
}
for x in kernel
],
"Summary": {
"PortPressure": {
self._machine_model.get_ports()[i]: v for i, v in enumerate(tp_sum)
},
"CriticalPath": sum([x["latency_cp"] for x in cp_kernel]),
"LCD": lcd_sum,
},
"Target": {
"Name": self._arch.upper(),
"Ports": list(self._machine_model.get_ports()),
},
}
def combined_view(
self,
kernel,
@@ -449,6 +521,14 @@ class Frontend(object):
)
return header + "\n"
def _header_report_dict(self):
"""Return header information in a dictionary format"""
return {
"Version": _get_version("__init__.py"),
"FileName": self._filename,
"Timestamp": dt.utcnow().strftime("%Y-%m-%d %H:%M:%S"),
}
def _symbol_map(self):
"""Prints instruction flag map."""
symbol_dict = {

View File

@@ -7,6 +7,8 @@ import re
import sys
from functools import lru_cache
import ruamel.yaml
from osaca.db_interface import import_benchmark_output, sanity_check
from osaca.frontend import Frontend
from osaca.parser import BaseParser, ParserAArch64, ParserX86ATT
@@ -188,6 +190,13 @@ def create_parser(parser=None):
type=argparse.FileType("w"),
help="Write analysis to this file (default to stdout).",
)
parser.add_argument(
"--yaml-out",
default=None,
dest="yaml_out",
type=argparse.FileType("w"),
help="Write YAML analysis to this file",
)
parser.add_argument(
"file",
type=argparse.FileType("r"),
@@ -360,6 +369,17 @@ def inspect(args, output_file=sys.stdout):
),
file=output_file,
)
if args.yaml_out is not None:
ruamel.yaml.dump(
frontend.full_analysis_dict(
kernel,
kernel_graph,
arch_warning=print_arch_warning,
length_warning=print_length_warning,
lcd_warning=kernel_graph.timed_out,
),
args.yaml_out,
)
def run(args, output_file=sys.stdout):