even better more structured throughput scheduling
Validate Operations / validate-operations (push) Has been cancelled

plot adjustments
validation adjustments
This commit is contained in:
NiccoloN
2026-10-27 17:46:46 +01:00
parent 49d6fb42cf
commit a77edafcbf
46 changed files with 3265 additions and 1043 deletions
+68 -13
View File
@@ -5,6 +5,7 @@ import json
import os
from pathlib import Path
import shutil
import struct
import subprocess
import tempfile
@@ -19,6 +20,59 @@ def check_selected_program(out):
return report
def check_synchronization_ablation(root, compiler, env):
vgg = REPO / "validation/networks/pimcomp_models/vgg8/vgg8-mnist-reconstructed.onnx"
out = root / "synchronization-ablation"
# Ablation keeps normal selection and costs omitted synchronization separately.
for arch, cores, crossbars in (("arch-a", 168, 96), ("arch-b", 138, 128)):
programs, evidence, schedules = [], [], []
for disabled in (False, True):
out.mkdir()
command = [compiler, str(vgg), "-o", str(out / "model"), "--maccel=PIM",
"--EmitPimCodegen", "--pipeline=4", f"--core-count={cores}",
f"--crossbar-count={crossbars}", "--crossbar-size=128",
"--mlir-disable-threading", "--pim-detect-communication-deadlock",
f"--pim-target-config={REPO}/validation/pimsim_configs/pimcomp/{arch}/throughput_config_1000ms.json"]
if disabled:
command.append("--pim-disable-synchronization")
result = subprocess.run(command, cwd=root, env=env, capture_output=True, text=True, timeout=90)
assert result.returncode == 0, result.stdout + result.stderr
report = check_selected_program(out)
assert report["generated_candidates"] > 1
assert bool(report.get("synchronization_ablation")) == disabled
if disabled:
assert report["cost_model_program"] == "synchronized-reference"
assert "report zero-cost SYNC/WAIT separately" in result.stderr
ablation = report["backend_attempts"][0]["synchronization_ablation_cost"]
assert ablation["cost_model_program"] == "synchronization-omitted"
assert not ablation["used_for_selection"] and ablation["diagnostic_only"]
assert all(candidate["eligible"] for candidate in report["candidates"])
evidence.append((report["selection"], [(c["interval_ns"], c["alternative_tie_interval_ns"],
c["eligible"], c["stage_core_budgets"], c["task_stage_runs"])
for c in report["candidates"]]))
schedules.append((out / "reports/spatial3_scheduled_no_comm.txt").read_bytes())
program = {}
sync_count = 0
for path in (out / "pim").rglob("*"):
if not path.is_file():
continue
data = path.read_bytes()
if path.suffix == ".pim":
magic, version, count = struct.unpack("<4sII", data[:12])
assert magic == b"PIMB" and version == 1 and len(data) == 12 + 20 * count
records = [data[i:i + 20] for i in range(12, len(data), 20)]
sync_count += sum(record[0] in (31, 32) for record in records)
data = b"".join(record for record in records if record[0] not in (31, 32))
program[str(path.relative_to(out / "pim"))] = hashlib.sha256(data).hexdigest()
assert (sync_count == 0) == disabled
programs.append(program)
shutil.rmtree(out)
assert evidence[0] == evidence[1], arch
assert schedules[0] == schedules[1], arch
assert programs[0] == programs[1], arch
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--compiler", required=True)
@@ -87,7 +141,7 @@ def main():
result = subprocess.run(command, cwd=root, env=env, capture_output=True, text=True, timeout=90)
assert result.returncode == 0, result.stdout + result.stderr
report = check_selected_program(out)
assert report["selection"] != 0 and bool((out / "dialects").exists()) == diagnostics
assert bool((out / "dialects").exists()) == diagnostics
identity = {str(p.relative_to(out / "pim")): hashlib.sha256(p.read_bytes()).hexdigest()
for p in (out / "pim").rglob("*") if p.is_file()}
schedule = (out / "reports/spatial3_scheduled_no_comm.txt").read_bytes()
@@ -114,22 +168,23 @@ def main():
"--core-count=168", "--crossbar-count=96", "--crossbar-size=128", "--mlir-disable-threading",
f"--pim-target-config={hardware}"]
result = subprocess.run(command, cwd=root, env=env, capture_output=True, text=True, timeout=60)
assert result.returncode == 0, result.stdout + result.stderr
assert result.returncode != 0, result.stdout + result.stderr
assert "cannot compare the complete candidate set" in result.stderr
report = json.loads((out / "reports/pipeline_selection.json").read_text())
assert report["selection"] == 0 and report["single_candidate_analysis_skipped"]
assert report["generated_candidates"] == 1 and report["lowered_candidates"] == 1
assert "no cost comparison required" in report["reason"]
assert report["temporary_disk_bytes"] == 0 and not list(root.glob("candidate*"))
assert report["status"] == "incomplete-costs" and "backend_attempts" not in report
assert "ROB capacity one" in report["reason"]
shutil.rmtree(out)
out.mkdir()
command[-1] = f"--pim-target-config={config_path}"
command += ["--pim-disable-synchronization"]
result = subprocess.run(command, cwd=root, env=env, capture_output=True, text=True, timeout=60)
assert result.returncode == 0, result.stdout + result.stderr
result = subprocess.run([*command, "--pim-disable-synchronization"],
cwd=root, env=env, capture_output=True, text=True, timeout=60)
assert result.returncode != 0, result.stdout + result.stderr
report = json.loads((out / "reports/pipeline_selection.json").read_text())
assert report["selection"] == 0 and report["single_candidate_analysis_skipped"]
assert report["generated_candidates"] == 1 and report["lowered_candidates"] == 1
assert "no cost comparison required" in report["reason"]
assert report["status"] == "incomplete-costs" and "backend_attempts" not in report
assert "ROB capacity one" in report["reason"]
shutil.rmtree(out)
check_synchronization_ablation(root, compiler, env)
assert not (root / "executed").exists(), "production compiler executed a diagnostic or simulator"