Warning, file /eic-opticks/tests/check_event_timing_profile.py was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002 """Validate a detailed EventTimingProfile CSV."""
0003
0004 from __future__ import annotations
0005
0006 import argparse
0007 import csv
0008 from pathlib import Path
0009
0010
0011 HEADER = (
0012 "name",
0013 "wall_time_us",
0014 "steady_time_ns",
0015 "vm_kb",
0016 "rss_kb",
0017 "metadata",
0018 )
0019 REQUIRED_PREFIXES = ("A000_SEvt__", "CSGFoundry__", "CSGOptiX__", "A000_QSim__")
0020 INTEGER_FIELDS = ("wall_time_us", "steady_time_ns", "vm_kb", "rss_kb")
0021
0022
0023 def fail(path: Path, message: str) -> None:
0024 raise AssertionError(f"{path}: {message}")
0025
0026
0027 def main() -> None:
0028 parser = argparse.ArgumentParser(description=__doc__)
0029 parser.add_argument("profile_csv", type=Path)
0030 args = parser.parse_args()
0031
0032 with args.profile_csv.open(newline="") as stream:
0033 reader = csv.DictReader(stream)
0034 if tuple(reader.fieldnames or ()) != HEADER:
0035 fail(args.profile_csv, f"expected header {HEADER}, found {reader.fieldnames}")
0036 rows = list(reader)
0037
0038 if not rows:
0039 fail(args.profile_csv, "contains no profile records")
0040
0041 prior_steady = -1
0042 names: set[str] = set()
0043 prefix_counts = {prefix: 0 for prefix in REQUIRED_PREFIXES}
0044 for line_number, row in enumerate(rows, start=2):
0045 name = row["name"]
0046 names.add(name)
0047 for prefix in REQUIRED_PREFIXES:
0048 prefix_counts[prefix] += name.startswith(prefix)
0049
0050 values: dict[str, int] = {}
0051 for field in INTEGER_FIELDS:
0052 try:
0053 values[field] = int(row[field])
0054 except (TypeError, ValueError) as error:
0055 fail(args.profile_csv, f"row {line_number} {name!r} has invalid {field}={row[field]!r}: {error}")
0056
0057 if values["steady_time_ns"] < prior_steady:
0058 fail(args.profile_csv, f"row {line_number} {name!r} has decreasing steady_time_ns")
0059 if values["vm_kb"] < 0 or values["rss_kb"] < 0:
0060 fail(args.profile_csv, f"row {line_number} {name!r} has negative memory")
0061 prior_steady = values["steady_time_ns"]
0062
0063 missing = [prefix for prefix, count in prefix_counts.items() if count == 0]
0064 if missing:
0065 fail(args.profile_csv, f"missing records with prefixes: {', '.join(missing)}")
0066
0067 launch_pairs = 0
0068 for name in names:
0069 if name.endswith("QSim__simulate_PREL"):
0070 launch_pairs += (name.removesuffix("PREL") + "POST") in names
0071 if launch_pairs == 0:
0072 fail(args.profile_csv, "contains no matching QSim PREL/POST launch pair")
0073
0074 print(f"PROFILE_RECORDS={len(rows)}")
0075 print(f"PROFILE_LAUNCH_PAIRS={launch_pairs}")
0076
0077
0078 if __name__ == "__main__":
0079 main()