even better more structured throughput scheduling
Validate Operations / validate-operations (push) Has been cancelled
Validate Operations / validate-operations (push) Has been cancelled
plot adjustments validation adjustments
This commit is contained in:
@@ -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"
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user