add ablation study
Validate Operations / validate-operations (push) Has been cancelled

normalize names and artifact paths
This commit is contained in:
NiccoloN
2026-08-20 17:58:02 +02:00
parent add20e56eb
commit b009e1ff08
67 changed files with 1573 additions and 993 deletions
+33
View File
@@ -0,0 +1,33 @@
from pathlib import Path
ARTIFACTS_DIRNAME = "artifacts"
def artifacts_dir(workspace_dir: str | Path) -> Path:
return Path(workspace_dir) / ARTIFACTS_DIRNAME
def runner_uses_library(runner_path: str | Path, library_path: str | Path) -> bool:
runner_path = Path(runner_path)
library_path = Path(library_path)
try:
return (
runner_path.is_file()
and library_path.is_file()
and str(library_path.resolve()).encode() in runner_path.read_bytes()
)
except OSError:
return False
def remove_lock_files(root: str | Path) -> int:
root = Path(root)
if not root.exists():
return 0
removed = 0
for path in root.rglob("*.lock"):
if path.is_file() or path.is_symlink():
path.unlink(missing_ok=True)
removed += 1
return removed
@@ -0,0 +1,39 @@
from __future__ import annotations
import argparse
from pathlib import Path
REPO = Path(__file__).resolve().parents[2]
SUITE = REPO / "validation/networks/pimcomp_models"
MODELS = {
"vgg8": SUITE / "vgg8/vgg8-mnist-reconstructed.onnx",
"resnet18": SUITE / "resnet18/resnet18-v1-7.onnx",
"resnet34": SUITE / "resnet34/resnet34-v1-7.onnx",
"googlenet": SUITE / "googlenet/googlenet-12-pimsim-nn.onnx",
"yolo11n": SUITE / "yolo11n/yolo11n-pimsim-nn.onnx",
}
FUNCTIONAL_MODELS = {
**MODELS,
"yolo11n": REPO / "validation/networks/yolo11n/depth_51/yolo11n_depth_51.onnx",
}
MODEL_NAMES = tuple(MODELS)
DEFAULT_MODELS = MODEL_NAMES
ABLATION_DEFAULT_MODELS = ("vgg8", "resnet18", "resnet34", "googlenet")
def add_models_argument(
parser: argparse.ArgumentParser,
default: tuple[str, ...] = DEFAULT_MODELS,
) -> None:
help_text = "Models to run (default: " + ", ".join(default) + ")."
if "yolo11n" not in default:
help_text += " Select yolo11n explicitly when needed."
parser.add_argument(
"--models",
nargs="+",
choices=MODEL_NAMES,
default=list(default),
metavar="MODEL",
help=help_text,
)
+7 -7
View File
@@ -8,13 +8,13 @@ from .subprocess_utils import run_command_with_reporter
PIM_PASS_LABELS = (
("ONNXToSpatialPass", "ONNX to Spatial"),
("MergeComputeNodesPass", "Merge Compute Nodes"),
("SpatialToPimPass", "Spatial to PIM"),
("PimBufferizationPass", "Bufferize PIM"),
("HostConstantFoldingPass", "Fold Host Constants"),
("PimLocalMemoryPlanningPass", "Plan Local Memory"),
("VerificationPass", "Verify PIM"),
("EmitPimCodePass", "Emit PIM Code"),
("MergeComputeNodesPass", "Merge compute nodes"),
("SpatialToPimPass", "Spatial to Pim"),
("PimBufferizationPass", "Bufferize Pim"),
("HostConstantFoldingPass", "Fold host constants"),
("PimLocalMemoryPlanningPass", "Plan local memory"),
("VerificationPass", "Verify Pim"),
("EmitPimCodePass", "Emit Pim code"),
)
PIM_PASS_LABEL_BY_SUFFIX = dict(PIM_PASS_LABELS)
TIMING_LINE_RE = re.compile(r"^\s*([0-9]+\.[0-9]+)\s+\(\s*[0-9.]+%\)\s+(.+?)\s*$")
+49 -39
View File
@@ -9,6 +9,7 @@ import numpy as np
from dataclasses import dataclass, field
from pathlib import Path
from colorama import Style, Fore
from .artifacts import artifacts_dir, runner_uses_library
from .gen_network_runner import gen_network_runner
from .onnx_utils import (
_ONNX_TO_NP,
@@ -26,13 +27,13 @@ from .subprocess_utils import run_command_with_reporter
STAGE_TITLES = (
"Compile ONNX",
"Build Runner",
"Generate Inputs",
"Run Reference",
"Compile PIM",
"Run Functional Simulation",
"Compare Outputs",
"Run Non-functional Simulation",
"Build runner",
"Generate inputs",
"Run reference",
"Compile Pim",
"Run functional simulation",
"Compare outputs",
"Run non-functional simulation",
)
STAGE_COLORS = {
STAGE_TITLES[0]: Fore.BLUE,
@@ -46,8 +47,7 @@ STAGE_COLORS = {
}
STAGE_COUNT = len(STAGE_TITLES)
GENERATED_DIR_NAMES = (
"inputs", "outputs", "pimcomp", "raptor", "runner", "simulation",
"throughput_validation",
"artifacts",
)
MODE_FULL = "full"
@@ -58,15 +58,15 @@ MODE_STAGE_TITLES = {
MODE_FULL: STAGE_TITLES,
MODE_COMPILE_ONLY: (
"Compile ONNX",
"Build Runner",
"Compile PIM",
"Build runner",
"Compile Pim",
),
MODE_RUN_ONLY: (
"Generate Inputs",
"Run Reference",
"Run Functional Simulation",
"Compare Outputs",
"Run Non-functional Simulation",
"Generate inputs",
"Run reference",
"Run functional simulation",
"Compare outputs",
"Run non-functional simulation",
),
}
@@ -75,7 +75,7 @@ PIMSIM_FAILED = "ERROR"
PIMSIM_UNSUPPORTED = "UNSUPPORTED"
PIMSIM_SKIPPED = "SKIP"
PIMSIM_NOT_RUN = "-"
PIMSIM_UNSUPPORTED_VSOFTMAX = "pimsim-nn does not support opcode vsoftmax"
PIMSIM_UNSUPPORTED_VSOFTMAX = "Pimsim does not support opcode vsoftmax"
class PimSimUnsupportedError(RuntimeError):
@@ -338,7 +338,7 @@ def run_pimsim_nn(
else ("throughput", "average_latency_ms", "average_power_mw", "average_energy_pj")
)
if any(name not in metrics for name in required):
raise RuntimeError(f"pimsim-nn output did not contain required {execution_mode} metrics")
raise RuntimeError(f"Pimsim output did not contain required {execution_mode} metrics")
return metrics
@@ -361,6 +361,11 @@ def clean_workspace_artifacts(workspace_dir, model_stem):
for suffix in (".onnx.mlir", ".so", ".tmp"):
remove_path(workspace_dir / f"{model_stem}{suffix}")
for path in workspace_dir.rglob("*.lock"):
if path.is_file() or path.is_symlink():
path.unlink(missing_ok=True)
removed_paths.append(path)
return removed_paths
@@ -407,32 +412,34 @@ def build_dump_ranges(config_path, outputs_descriptor):
def build_pim_simulator_command(
pim_dir, output_bin_path, dump_ranges, input_paths, mode="latency",
pim_dir, output_bin_path, dump_ranges, input_dir, batch_size, mode="latency",
batch_output_dir=None):
if mode not in ("latency", "throughput"):
raise ValueError(f"unknown simulator mode: {mode}")
if not input_paths:
if batch_size < 1:
raise ValueError("simulator requires at least one input")
if input_dir is None:
raise ValueError("simulator requires an input directory")
command = [
"cargo", "run", "--no-default-features", "--release", "--package", "pim-simulator", "--bin", "pim-simulator",
"--", "-f", str(pim_dir), "-o", str(output_bin_path), "-d", dump_ranges,
"--mode", mode, "--batch-size", str(len(input_paths)),
"--mode", mode, "--batch-size", str(batch_size),
"--input-dir", str(input_dir),
]
if batch_output_dir is not None:
command += ["--batch-output-dir", str(batch_output_dir)]
for path in input_paths:
command += ["--input", str(path)]
return command
def run_pim_simulator(
simulator_dir, pim_dir, output_bin_path, dump_ranges, reporter=None,
timeout_sec=None, input_paths=(), mode="latency", batch_output_dir=None):
timeout_sec=None, input_dir=None, batch_size=1, mode="latency", batch_output_dir=None):
command = build_pim_simulator_command(
pim_dir,
output_bin_path,
dump_ranges,
input_paths,
input_dir,
batch_size,
mode=mode,
batch_output_dir=batch_output_dir,
)
@@ -516,7 +523,7 @@ def validate_execution(
try:
print_stage(
reporter, model_index, model_total, model_name,
"Run Functional Simulation", name,
"Run functional simulation", name,
)
write_inputs_to_memory_bin(
pim_dir / "memory.bin", pim_dir / "config.json", input_batch[0])
@@ -526,13 +533,13 @@ def validate_execution(
run_pim_simulator(
simulator_dir, pim_dir, simulation_dir / "out.bin", dump_ranges,
reporter=reporter, timeout_sec=command_timeout_seconds,
input_paths=input_paths[:batch_size], mode=name,
input_dir=input_paths[0].parent, batch_size=batch_size, mode=name,
batch_output_dir=output_dir)
reporter.advance()
print_stage(
reporter, model_index, model_total, model_name,
"Compare Outputs", name,
"Compare outputs", name,
)
reporter.suspend()
try:
@@ -553,7 +560,7 @@ def validate_execution(
print_stage(
reporter, model_index, model_total, model_name,
"Run Non-functional Simulation", name,
"Run non-functional simulation", name,
)
config_path = execution["pimsim_config"]
if state["compiled"] and pimsim_nn_build_dir is not None and config_path is not None:
@@ -580,7 +587,7 @@ def validate_execution(
elif not state["compiled"]:
state["pimsim_status"] = PIMSIM_NOT_RUN
else:
print_info(reporter, "pimsim-nn non-functional simulation skipped")
print_info(reporter, "Pimsim non-functional simulation skipped")
reporter.advance()
@@ -609,12 +616,12 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
owns_reporter = reporter is None
reporter = reporter or ProgressReporter(model_total, stages_per_model=len(MODE_STAGE_TITLES[mode]), verbose=verbose)
workspace_dir = network_onnx_path.parent
workspace_dir = artifacts_dir(network_onnx_path.parent)
raptor_dir = workspace_dir / "raptor"
runner_dir = workspace_dir / "runner"
runner_build_dir = runner_dir / "build"
if mode != MODE_RUN_ONLY:
clean_workspace_artifacts(workspace_dir, network_onnx_path.stem)
clean_workspace_artifacts(network_onnx_path.parent, network_onnx_path.stem)
Path.mkdir(raptor_dir, parents=True, exist_ok=True)
Path.mkdir(runner_build_dir, parents=True, exist_ok=True)
@@ -669,7 +676,7 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
print_info(reporter, f"Shared library saved to {network_so_path}")
reporter.advance()
print_stage(reporter, model_index, model_total, network_onnx_path.name, "Build Runner")
print_stage(reporter, model_index, model_total, network_onnx_path.name, "Build runner")
gen_network_runner(
network_onnx_path, network_so_path, onnx_include_dir,
entry="run_main_graph", out=runner_dir / "runner.c", verbose=False)
@@ -683,7 +690,10 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
report_validation_failure(reporter, "reference", "compilation", exc)
else:
required_paths = (network_so_path, network_mlir_path, runner_path)
reference_ready = all(path.exists() for path in required_paths)
reference_ready = (
all(path.exists() for path in required_paths)
and runner_uses_library(runner_path, network_so_path)
)
if not reference_ready:
report_validation_failure(reporter, "reference", "artifact lookup", FileNotFoundError(
"run-only mode requires the compiled shared library, ONNX MLIR, and runner"))
@@ -696,7 +706,7 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
states[name]["compiled"] = (pim_dir / "config.json").exists()
if not states[name]["compiled"]:
report_validation_failure(reporter, name, "artifact lookup", FileNotFoundError(
f"run-only mode requires compiled PIM artifacts at {pim_dir}"))
f"run-only mode requires compiled Pim artifacts at {pim_dir}"))
else:
states[name]["resource_metrics"] = collect_pim_resource_metrics(pim_dir)
if name == "latency":
@@ -705,7 +715,7 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
try:
print_stage(
reporter, model_index, model_total, network_onnx_path.name,
"Compile PIM", name,
"Compile Pim", name,
)
root.mkdir(parents=True, exist_ok=True)
started = time.perf_counter()
@@ -724,7 +734,7 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
states[name]["resource_metrics"] = collect_pim_resource_metrics(pim_dir)
if name == "latency":
resource_metrics = states[name]["resource_metrics"]
print_info(reporter, f"PIM artifacts saved to {pim_dir}")
print_info(reporter, f"Pim artifacts saved to {pim_dir}")
except Exception as exc:
report_validation_failure(reporter, name, "compilation", exc)
reporter.advance()
@@ -735,7 +745,7 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
else:
input_batch = input_paths = reference_dirs = outputs_descriptor = None
try:
print_stage(reporter, model_index, model_total, network_onnx_path.name, "Generate Inputs")
print_stage(reporter, model_index, model_total, network_onnx_path.name, "Generate inputs")
inputs_descriptor, outputs_descriptor = onnx_io(network_onnx_path)
first_inputs, _ = gen_random_inputs(inputs_descriptor, seed=seed)
input_batch = generate_input_batch(
@@ -754,7 +764,7 @@ def validate_network(network_onnx_path, raptor_path, onnx_include_dir,
if not reference_ready:
raise FileNotFoundError("reference runner is unavailable")
print_stage(reporter, model_index, model_total, network_onnx_path.name, "Run Reference")
print_stage(reporter, model_index, model_total, network_onnx_path.name, "Run reference")
reference_dirs = []
for index, flags in enumerate(input_flags):
reference_dir = workspace_dir / "outputs" / f"{index:06d}"